C ++ template operator not found as a match

I am trying to create a generic operator<< for std::ostream and any type of Iterable.

This is the code:

 template <class T,template<class> class Iterable> inline std::ostream& operator<<(std::ostream& s,const Iterable<T>& iter){ s << "[ "; bool first=false; for(T& e : iter){ if(first){ first=false; s << e; }else{ s << ", " << e; } } s << " ]"; return s; } 

Unfortunately, my operator was not found as a match for vector<uint> , and the compiler is trying to match with operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x) .

Any idea how I can change the overload for recognition?

+7
c ++ c ++ 11 operator-overloading templates iterable
source share
1 answer

A direct solution to your problem is that vector is a template for two types, not one, so you want to write:

 template <typename... T, template <typename... > class Iterable> inline std::ostream& operator<<(std::ostream& os, const Iterable<T...>& iter) { s << "[ "; bool first = true; // not false for (const auto& e : iter) { // rest as before } return s << " ]"; } 

This works, but a little unsatisfactorily - since some things that are templates are not iterable, and some things that are not templates. In addition, in our solution, we actually do not need Iterable or T So, how about we write something that accepts any range - where we define Range as something that begin() and end() :

 template <typename Range> auto operator<<(std::ostream& s, const Range& range) -> decltype(void(range.begin()), void(range.end()), s) { // as above, except our container is now named 'range' } 

If this is too general, then you can do:

 template <typename T> struct is_range : std::false_type; template <typename T, typename A> struct is_range<std::vector<T,A>> : std::true_type; // etc. template <typename Range> typename std::enable_if< is_range<Range>::value, std::ostream& >::type operator<<(std::ostream& s, const Range& range) 
+4
source share

All Articles