#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;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CiNpbmNsdWRlIDxzc3RyZWFtPgoKbmFtZXNwYWNlIGhhc19pbnNlcnRpb25fb3BlcmF0b3JfaW1wbCB7CiAgdHlwZWRlZiBjaGFyIG5vOwogIHR5cGVkZWYgY2hhciB5ZXNbMl07CgogIHN0cnVjdCBhbnlfdCB7CiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBUPiBhbnlfdCggVCBjb25zdCYgKTsKICB9OwoKICBubyBjb25zdCBhbnlfdCBhbnlfdDo6b3BlcmF0b3IrKGNvbnN0IGFueV90ICZvdGhlcikgY29uc3Q7CgogIHllcyYgdGVzdCggYW55X3QmLCBhbnlfdCApOwogIG5vIHRlc3QoIG5vICk7CgogIHRlbXBsYXRlPHR5cGVuYW1lIFQ+CiAgc3RydWN0IGhhc19pbnNlcnRpb25fb3BlcmF0b3IgewogICAgc3RhdGljIGFueV90JiBhOwogICAgc3RhdGljIGFueV90JiBiOwogICAgc3RhdGljIFQgY29uc3QgJnQ7CiAgICBzdGF0aWMgYm9vbCBjb25zdCB2YWx1ZSA9IHNpemVvZiggdGVzdChhICsgYikgKSA9PSBzaXplb2YoIHllcyApOwogIH07Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnN0cnVjdCBoYXNfaW5zZXJ0aW9uX29wZXJhdG9yIDoKICBoYXNfaW5zZXJ0aW9uX29wZXJhdG9yX2ltcGw6Omhhc19pbnNlcnRpb25fb3BlcmF0b3I8VD4gewp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsCiAgICB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjwKICAgICAgICBoYXNfaW5zZXJ0aW9uX29wZXJhdG9yPFQ+Ojp2YWx1ZSwgVD46OnR5cGUqID0gbnVsbHB0cj4Kdm9pZCBwcmludChUIGxocywgVCByaHMpIHsKICAgIHN0ZDo6Y291dCA8PCBsaHMgKyByaHMgPDwgc3RkOjplbmRsOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwKICAgIHR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPAogICAgICAgICFoYXNfaW5zZXJ0aW9uX29wZXJhdG9yPFQ+Ojp2YWx1ZSwgVD46OnR5cGUqID0gbnVsbHB0cj4Kdm9pZCBwcmludChUIGxocywgVCByaHMpIHsKICAgIHN0ZDo6Y291dCA8PCA0MiA8PCBzdGQ6OmVuZGw7Cn0KCnN0cnVjdCBGb28KewpwdWJsaWM6CiAgICBGb28oKSA6IHZhbCgwKSB7IH0KICAgIEZvbyhpbnQgdikgOiB2YWwodikgeyB9CiAgICB+Rm9vKCkgeyB9CiAgICAKICAgIGludCB2YWx1ZSgpIGNvbnN0IHsgcmV0dXJuIHZhbDsgfQogICAgCiAgICBGb28gJiBvcGVyYXRvcis9KGNvbnN0IEZvbyAmcmhzKTsKICAgIGNvbnN0IEZvbyBvcGVyYXRvcisoY29uc3QgRm9vICZvdGhlcikgY29uc3Q7CnByaXZhdGU6CiAgICBpbnQgdmFsOwp9OwoKRm9vICYgRm9vOjpvcGVyYXRvcis9KGNvbnN0IEZvbyAmcmhzKSB7CiAgICB0aGlzLT52YWwgKz0gcmhzLnZhbHVlKCk7CgogICAgcmV0dXJuICp0aGlzOwp9Cgpjb25zdCBGb28gRm9vOjpvcGVyYXRvcisoY29uc3QgRm9vICZvdGhlcikgY29uc3QgewogICAgRm9vIHJlc3VsdCA9ICp0aGlzOyAgICAgLy8gTWFrZSBhIGNvcHkgb2YgbXlzZWxmLiAgU2FtZSBhcyBNeUNsYXNzIHJlc3VsdCgqdGhpcyk7CiAgICByZXN1bHQgKz0gb3RoZXI7ICAgICAgICAgICAgLy8gVXNlICs9IHRvIGFkZCBvdGhlciB0byB0aGUgY29weS4KICAgIHJldHVybiByZXN1bHQ7ICAgICAgICAgICAgICAvLyBBbGwgZG9uZSEKfQoKaW50IG1haW4oKQp7CiAgICBwcmludCg0MiwgNDIpOwogICAgcHJpbnQoRm9vKDQyKSwgRm9vKDQyKSk7CiAgICByZXR1cm4gMDsKfQ==
prog.cpp:13:18: error: expected initializer before ‘any_t’
prog.cpp:23:48: error: no match for ‘operator+’ in ‘has_insertion_operator_impl::has_insertion_operator<T>::a + has_insertion_operator_impl::has_insertion_operator<T>::b’
prog.cpp: In function ‘int main()’:
prog.cpp:75:17: error: no matching function for call to ‘print(int, int)’
prog.cpp:75:17: note: candidates are:
prog.cpp:35:6: note: template<class T, typename std::enable_if<has_insertion_operator<T>::value, T>::type* <anonymous> > void print(T, T)
prog.cpp:35:6: note: template argument deduction/substitution failed:
prog.cpp:34:55: note: invalid template non-type parameter
prog.cpp:42:6: note: template<class T, typename std::enable_if<(! has_insertion_operator<T>::value), T>::type* <anonymous> > void print(T, T)
prog.cpp:42:6: note: template argument deduction/substitution failed:
prog.cpp:41:56: error: in argument to unary !
prog.cpp:41:56: note: invalid template non-type parameter
prog.cpp:76:27: error: no matching function for call to ‘print(Foo, Foo)’
prog.cpp:76:27: note: candidates are:
prog.cpp:35:6: note: template<class T, typename std::enable_if<has_insertion_operator<T>::value, T>::type* <anonymous> > void print(T, T)
prog.cpp:35:6: note: template argument deduction/substitution failed:
prog.cpp:34:55: note: invalid template non-type parameter
prog.cpp:42:6: note: template<class T, typename std::enable_if<(! has_insertion_operator<T>::value), T>::type* <anonymous> > void print(T, T)
prog.cpp:42:6: note: template argument deduction/substitution failed:
prog.cpp:41:56: error: in argument to unary !
prog.cpp:41:56: note: invalid template non-type parameter