problem:I need to prevent given operator from being generated
if underlying operation can't be compiled. Basically, this operator==:
template<class T> class accessor {
typedef accessor<T> Self;
public:
template<class C> friend inline bool operator==(Self l, C& r)
{ return l.m_ref == r; }
}
should not be instantiated if 'l.m_ref == r' fails to compile due to, for example, absence of related operator==.
solution:
template <bool Enable, typename T = void>
struct enable_if {
typedef T type;
};
template <typename T>
struct enable_if<false, T> {
};
namespace Details {
struct Shim
{
Shim(); // Can be implicitely constructed by
// everything (Not defined).
};
struct NoMatchType
{
};
// Only declared, never defined:
NoMatchType operator==(const Shim&, const Shim&);
template <typename T, typename U>
struct IsEqualComparableImpl
{
private:
static const T& t();
static const U& u();
static char Check(bool); // Expected result
static char (&Check(const NoMatchType&))[2]; // Fallback
public:
static const bool value = sizeof(Check(t() == u())) == 1;
};
}
template <typename T, typename U>
struct IsEqualComparable {
static const bool value =
Details::IsEqualComparableImpl<T, U>::value;
};
//test example
template<class T> class accessor {
typedef accessor<T> Self;
public:
accessor() : m_ref() {}
template<class C> friend inline typename enable_if<IsEqualComparable<T, C>::value, bool>::type
operator==(Self l, C& r) {
return l.m_ref == r;
}
private:
T m_ref;
};
class C{};
class D {};
bool operator==(D, D) { return true; }
bool test() {
accessor<D> a1;
D d;
bool b = a1 == d; // OK
accessor<int> a;
C c;
return a == c; // Error
}
int main() {
return test();
}
http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/3aa0bd9ea133b967/9ca97b1308becafe#9ca97b1308becafe