Here you can try the replacement methods Failure Is Not Error (SFINAE).
First, you need a function to determine if the type has an iterator member ...
template <typename T> struct Has_Iterator { template <typename> static char test(...); template <typename U> static int test(typename U::const_iterator*); static const bool result = sizeof test<T>(0) != sizeof(char); };
In the above code, the C ++ standard needs to use test(typename U::const_iterator*)
to prefer the undefined parameter "..." if U
is actually a struct / class with the element type const_iterator
, otherwise you have "replacement failure" is not a fatal error that stops compilation (hence SFINAE), and trying to find the appropriate function is saturated with test(...)
. As the return types of the two functions differ, the sizeof
operator can check which one has been matched by setting the result
boolean value accordingly.
Then you can redirect print requests to specialized templates that support them ...
template <typename T> void print(const T& data) { printer<Has_Iterator<T>::result, T>()(data); } // general case handles types having iterators... template <bool Has_It, typename T> struct printer { void operator()(const T& data) { for (typename T::const_iterator i = data.begin(); i != data.end(); ++i) std::cout << *i << ' '; std::cout << '\n'; } }; // specialisation for types lacking iterators... template <typename T> struct printer<false, T> { void operator()(const T& data) { std::cout << data << '\n'; } };
source share