TL; DR: see last paragraph.
I have operator& defined for several template classes, for example:
template <typename T> struct Class { Class(T const &t) { } }; template <typename T_Lhs, typename T_Rhs> struct ClassAnd { ClassAnd(T_Lhs const &lhs, T_Rhs const &rhs) { } }; template <typename T, typename T_Rhs> ClassAnd<Class<T>, T_Rhs> operator&(Class<T> const &lhs, T_Rhs const &rhs) { return ClassAnd<Class<T>, T_Rhs>(lhs, rhs); } template <typename T0, typename T1, typename T_Rhs> ClassAnd<ClassAnd<T0, T1>, T_Rhs> operator&(ClassAnd<T0, T1> const &lhs, T_Rhs const &rhs) { return ClassAnd<ClassAnd<T0, T1>, T_Rhs>(lhs, rhs); } int main() { Class<int> a(42); Class<double> b(3.14); auto c = a & b; }
This works great.
The problem occurs when I want to add a not operation, which is only allowed on one or the other side of the operation, and should return an instance of ClassAndNot , not ClassAnd :
template <typename T> struct ClassNot { ClassNot(T const &t) : value(t) { } T value; }; template <typename T_Lhs, typename T_Rhs> struct ClassAndNot { ClassAndNot(T_Lhs const &lhs, T_Rhs const &rhs) { } }; template <typename T_Lhs, typename T_Rhs> ClassAndNot<T_Lhs, T_Rhs> operator&(T_Lhs const &lhs, ClassNot<T_Rhs> const &rhs) { return ClassAndNot<T_Lhs, T_Rhs>(lhs, rhs.value); } template <typename T_Rhs> ClassNot<T> operator!(T_Rhs const &rhs) { return ClassNot<T_Rhs>(rhs); } ... auto c = a & !b;
This leads to ambiguity between operator& , which takes an arbitrary right side, to return a ClassAnd , and operator& on the right side of ClassNot to return ClassAndNot .
Question:
How can std::enable_if be used here to disable the first operator& if its right side is of any type of ClassNot ? Is there something like std::is_same that returns true if one side is an instance of the template of the other?
ps You can find a complete working example of ideone .