#include <iostream>
#include <type_traits>
#include <sstream>

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

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

  no const any_t any_t::operator+(const any_t &other) const;

  yes& test( any_t&, any_t );
  no test( no );

  template<typename T>
  struct has_insertion_operator {
    static any_t& a;
    static any_t& b;
    static T const &t;
    static bool const value = sizeof( test(a + b) ) == 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 lhs, T rhs) {
    std::cout << lhs + rhs << std::endl;
}

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

struct Foo
{
public:
    Foo() : val(0) { }
    Foo(int v) : val(v) { }
    ~Foo() { }
    
    int value() const { return val; }
    
    Foo & operator+=(const Foo &rhs);
    const Foo operator+(const Foo &other) const;
private:
    int val;
};

Foo & Foo::operator+=(const Foo &rhs) {
    this->val += rhs.value();

    return *this;
}

const Foo Foo::operator+(const Foo &other) const {
    Foo result = *this;     // Make a copy of myself.  Same as MyClass result(*this);
    result += other;            // Use += to add other to the copy.
    return result;              // All done!
}

int main()
{
    print(42, 42);
    print(Foo(42), Foo(42));
    return 0;
}