That said, here's one possible place where it might make sense with SFINAE. Note that I haven't fully thought this through, I'm just doing this off the top of my head right now, so it's possible I'll miss something:
#include <iterator>
#include <type_traits>
namespace stdext { template<class> class checked_array_iterator; } // Forward-declare MSVC-specific type
namespace bar {
namespace {
template<class T>
std::enable_if_t<(std::is_same_v<stdext::checked_array_iterator<typename std::iterator_traits<typename T::foo_iterator>::value_type *>, typename T::foo_iterator> && ((void)sizeof(typename T::foo_iterator), true))> debug_verify(const T &obj, ...) {
// extra sanity checks against obj.get_foo_iterator()
}
template<class T>
std::enable_if_t<!(std::is_same_v<stdext::checked_array_iterator<typename std::iterator_traits<typename T::foo_iterator>::value_type *>, typename T::foo_iterator> && ((void)sizeof(typename T::foo_iterator), true))> debug_verify(const T &) {
// nothing to do
}
}
class S {
auto foo() {
bar::debug_verify(this->field1);
bar::debug_verify(this->field2);
}
// ...
};
}
Note that I'm by no means claiming this is the only way to do this.(Edit: Removed a final comment about turning it into a is_checked_array_iterator trait - messed up that part.)