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);
}
// Addition of ClassNot and the appropriate operators causes an ambiguity in operator&.
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_Rhs> operator!(T_Rhs const &rhs) {
return ClassNot<T_Rhs>(rhs);
}
// Sample usage.
int main() {
Class<int> a(42);
Class<double> b(3.14);
auto c = a & !b;
}
dGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnN0cnVjdCBDbGFzcyB7CglDbGFzcyhUIGNvbnN0ICZ0KSB7IH0KfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBUX0xocywgdHlwZW5hbWUgVF9SaHM+CnN0cnVjdCBDbGFzc0FuZCB7CglDbGFzc0FuZChUX0xocyBjb25zdCAmbGhzLCBUX1JocyBjb25zdCAmcmhzKSB7IH0KfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBUX1Jocz4KQ2xhc3NBbmQ8Q2xhc3M8VD4sIFRfUmhzPiBvcGVyYXRvciYoQ2xhc3M8VD4gY29uc3QgJmxocywgVF9SaHMgY29uc3QgJnJocykgewoJcmV0dXJuIENsYXNzQW5kPENsYXNzPFQ+LCBUX1Jocz4obGhzLCByaHMpOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVDAsIHR5cGVuYW1lIFQxLCB0eXBlbmFtZSBUX1Jocz4KQ2xhc3NBbmQ8Q2xhc3NBbmQ8VDAsIFQxPiwgVF9SaHM+IG9wZXJhdG9yJihDbGFzc0FuZDxUMCwgVDE+IGNvbnN0ICZsaHMsIFRfUmhzIGNvbnN0ICZyaHMpIHsKCXJldHVybiBDbGFzc0FuZDxDbGFzc0FuZDxUMCwgVDE+LCBUX1Jocz4obGhzLCByaHMpOwp9CgovLyBBZGRpdGlvbiBvZiBDbGFzc05vdCBhbmQgdGhlIGFwcHJvcHJpYXRlIG9wZXJhdG9ycyBjYXVzZXMgYW4gYW1iaWd1aXR5IGluIG9wZXJhdG9yJi4KdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnN0cnVjdCBDbGFzc05vdCB7CglDbGFzc05vdChUIGNvbnN0ICZ0KSA6IHZhbHVlKHQpIHsgfQoJVCB2YWx1ZTsKfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBUX0xocywgdHlwZW5hbWUgVF9SaHM+CnN0cnVjdCBDbGFzc0FuZE5vdCB7CglDbGFzc0FuZE5vdChUX0xocyBjb25zdCAmbGhzLCBUX1JocyBjb25zdCAmcmhzKSB7IH0KfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBUX0xocywgdHlwZW5hbWUgVF9SaHM+CkNsYXNzQW5kTm90PFRfTGhzLCBUX1Jocz4gb3BlcmF0b3ImKFRfTGhzIGNvbnN0ICZsaHMsIENsYXNzTm90PFRfUmhzPiBjb25zdCAmcmhzKSB7CglyZXR1cm4gQ2xhc3NBbmROb3Q8VF9MaHMsIFRfUmhzPihsaHMsIHJocy52YWx1ZSk7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBUX1Jocz4KQ2xhc3NOb3Q8VF9SaHM+IG9wZXJhdG9yIShUX1JocyBjb25zdCAmcmhzKSB7CglyZXR1cm4gQ2xhc3NOb3Q8VF9SaHM+KHJocyk7Cn0KCi8vIFNhbXBsZSB1c2FnZS4KaW50IG1haW4oKSB7CglDbGFzczxpbnQ+IGEoNDIpOwoJQ2xhc3M8ZG91YmxlPiBiKDMuMTQpOwoJYXV0byBjID0gYSAmICFiOwp9Cg==
prog.cpp: In function ‘int main()’:
prog.cpp:47:13: error: ambiguous overload for ‘operator&’ (operand types are ‘Class<int>’ and ‘ClassNot<Class<double> >’)
auto c = a & !b;
^
prog.cpp:47:13: note: candidates are:
prog.cpp:12:27: note: ClassAnd<Class<T>, T_Rhs> operator&(const Class<T>&, const T_Rhs&) [with T = int; T_Rhs = ClassNot<Class<double> >]
ClassAnd<Class<T>, T_Rhs> operator&(Class<T> const &lhs, T_Rhs const &rhs) {
^
prog.cpp:34:27: note: ClassAndNot<T_Lhs, T_Rhs> operator&(const T_Lhs&, const ClassNot<T_Rhs>&) [with T_Lhs = Class<int>; T_Rhs = Class<double>]
ClassAndNot<T_Lhs, T_Rhs> operator&(T_Lhs const &lhs, ClassNot<T_Rhs> const &rhs) {
^