Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fallback to to_string() when operator<<() fails

I've seen types that have corresponding to_string() function, but haven't overloaded operator<<(). So, when inserting to stream, one has to << to_string(x) which is verbose. I'm wondering whether it's possible to write a generic function that users operator<<() if supported and falls back to << to_string() if not.

like image 422
Lingxi Avatar asked Jan 22 '16 06:01

Lingxi


2 Answers

SFINAE is overkill, use ADL.

The trick is to make sure that an operator<< is available, not necessarily the one supplied by the type definition:

namespace helper {
   template<typename T> std::ostream& operator<<(std::ostream& os, T const& t)
   {
      return os << to_string(t);
   }
}
using helper::operator<<;
std::cout << myFoo;

This trick is commonly used in generic code which needs to choose between std::swap<T> and a specialized Foo::swap(Foo::Bar&, Foo::Bar&).

like image 183
MSalters Avatar answered Sep 28 '22 00:09

MSalters


Try

template <typename T>
void print_out(T t) {
    print_out_impl(std::cout, t, 0);
}

template <typename OS, typename T>
void print_out_impl(OS& o, T t, 
                    typename std::decay<decltype(
                      std::declval<OS&>() << std::declval<T>()
                    )>::type*) {
    o << t;
}

template <typename OS, typename T>
void print_out_impl(OS& o, T t, ...) {
    o << t.to_string();
}

LIVE

like image 42
songyuanyao Avatar answered Sep 28 '22 00:09

songyuanyao