I have
a class Value which can be construct with different types (Foo, Bar, int,...).
class Value should have common operations like <<, ==, <,... proceeded at the underlying type
I added the operator << outside class definition.
I have to the following code:
#include <iostream>
struct Foo {
};
struct Bar {
};
struct Value {
template<typename T>
Value(T) {
}
};
std::ostream &operator<<(std::ostream &os, const Bar &) {
return os << "Bar\n";
}
std::ostream &operator<<(std::ostream &os, const Value &value) {
auto visitor = [&](auto a) -> decltype(os << a) {
return os << a;
};
// Works
visitor(Bar{});
// Infinity call of this function with Value.
visitor(Foo{});
return os;
}
int main() {
std::cout << Value(1);
return 0;
}
The problem: If the underlying type does not implements the operator<<, the operator<< from Value gets called recursive infinity. I want to get a compiler error like no match for call operator<<(std:ostream&, const Value&)... to use SFINAE with my visitor pattern (not shown here).
What I need is something like:
[&](auto a) -> std::enable_if_t<addressof?(os << a) != addressof?(os << Value{})>::value> {
return os << a;
};
to disable this lambda, if the functions are the same. Is this possible?
Not valuable solutions:
- make Value explicit
- disable construction of Value with Foo