    #include <iostream>
    #include <string>
    #include <type_traits>

    namespace has_insertion_operator_impl {
      typedef char no;
      typedef char yes[2];

      struct any_t {
        template<typename T> any_t( T const& );
      };

      no operator<<( std::ostream const&, any_t const& );

      yes& test( std::ostream& );
      no test( no );

      template<typename T>
      struct has_insertion_operator {
        static std::ostream &s;
        static T const &t;
        static bool const value = sizeof( test(s << t) ) == sizeof( yes );
      };
    }

    template<typename T>
    struct has_insertion_operator :
      has_insertion_operator_impl::has_insertion_operator<T> {
    };

    template <typename T,
        typename std::enable_if<has_insertion_operator<T>::value, T>::type* = nullptr>
    void print(T obj) {
        std::cout << "from print()" << std::endl;
    }

    template <typename T,
        typename std::enable_if<!has_insertion_operator<T>::value, T>::type* = nullptr>
    void print(T obj) {
        std::cout << obj.to_string() << std::endl;
    }

    struct Foo
    {
    public:
        friend std::ostream& operator<<(std::ostream & os, Foo const& foo);
    };

    struct Bar
    {
    public:
        std::string to_string() const
        {
            return "from to_string()";
        }
    };

    int main()
    {
        print<Foo>(Foo());
        print<Bar>(Bar());

        //print<Bar>(Foo()); doesn't compile
        //print<Foo>(Bar()); doesn't compile

        print(Foo());
        print(Bar());

        print(42);
        print('a');
        print(std::string("Hi"));
        print("Hey");
        //print({1, 2, 3}); doesn't compile
        return 0;
    }
