In a comparison operator:
template
bool operator==(Manager m1, Manager m2) {
return m1.internal_field == m2
A trait you want might look like this:
template <typename B, typename D>
struct is_base_of // check if B is a base of D
{
typedef char yes[1];
typedef char no[2];
static yes& test(B*);
static no& test(...);
static D* get(void);
static const bool value = sizeof(test(get()) == sizeof(yes);
};
Then you just need a static assert of some sort:
// really basic
template <bool>
struct static_assert;
template <>
struct static_assert<true> {}; // only true is defined
#define STATIC_ASSERT(x) static_assert<(x)>()
Then put the two together:
template<class R1, class R2>
bool operator==(Manager<R1> m1, Manager<R2> m2)
{
STATIC_ASSERT(is_base_of<R1, R2>::value || is_base_of<R2, R1>::value);
return p1.internal_field == p2.internal_field;
}
If one does not derive from the other, the function will not compile. (Your error will be similar to "static_assert<false>
not defined", and it will point to that line.)
I must admit, I don't see the motivation behind this, particularly if it requires writing shedloads of supporting code. For your operator:
template<class R1, class R2>
bool operator==(Manager<R1> m1, Manager<R2> m2) {
return p1.internal_field == p2.internal_field;
}
to compile without a warning, both template parameter types must be capable of being parameters to the Manager template, and those types must have private members (I assume p1 & p2 should be m1 & m2) called internal_field. Given those constraints, what is the chance that this template function can be called by accident on the wrong type(s)?
In this post I'm considering the problem of checking if a type exactly matches another, it's not exactly what is asked for, but it is simpler and I hope it can help to understand the applied template tricks.
As done in boost, template specializations can be adopted for that task, in fact you can define a template struct containing operations on a given type, and use nested template structs for that operations. In our case:
// Working on a specific type:
template <typename T1>
struct is_type {
// For all types T2!=T1 produce false:
template <typename T2>
struct same_of { static const bool value = false; };
// Specialization for type T2==T1 producing true:
template <>
struct same_of<T1> { static const bool value = true; };
};
Defining a macro allows to use it easily:
#define is_type_same(T1,T2) (is_type<T1>::same_of<T2>::value)
as follows:
template<class R1, class R2>
bool operator==(Manager<R1> m1, Manager<R2> m2) {
return is_type_same(R1,R2) && m1.internal_field == m2.internal_field;
}
If concepts would have been included in C++0x you might have been able to use them with a compiler that implement them (like gcc).
As it's not the case, the only alternative currently available to do what you want seem to be the Boost Concept Check library.
template<class T, class B> struct Derived_from {
static void constraints(T* p) { B* pb = p; }
Derived_from() { void(*p)(T*) = constraints; }
};
template<class R2, class R1>
bool test(R1& r1) {
Derived_from<R1,R2>(); // accept if R1 is derived from R2
return false;
}
class Base {
public:
virtual ~Base() { }
};
class Derived : public Base {
};
class Other {
};
int _tmain(int argc, _TCHAR* argv[])
{
Derived d;
Other o;
test<Base>(d); // OK
test<Base>(o); // Fails in VC++ 2005
return 0;
}
Credits go to http://www2.research.att.com/~bs/bs_faq2.html#constraints
You can use boost's typetraits (is_base_of), and boost's enable_if.
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
template <class R1, class R2>
struct has_derived_base_relationship :
boost::integral_constant<
bool, boost::is_base_of<R1, R2>::value || boost::is_base_of<R2, R1>::value
>
{};
template<class R1, class R2>
typename boost::enable_if<has_derived_base_relationship<R1, R2>, bool>::type
operator==(Manager<R1> m1, Manager<R2> m2) {
return p1.internal_field == p2.internal_field;
}
On the other hand, why would operator== usage have more value with types of the same inheritance tree? Wouldn't it have to use double dispatch to achieve meaningful results?