In a comparison operator:
template<class R1, class R2>
bool operator==(Manager<R1> m1, Manager<R2> m2) {
return m1.internal_field == m2.internal_field;
}
Is there any way I could enforce that R1 and R2 must have a supertype or subtype relation? That is, I'd like to allow either R1 to be derived from R2, or R2 to be derived from R1, but disallow the comparison if R1 and R2 are unrelated types.
It is possible to inherit from a template class. All the usual rules for inheritance and polymorphism apply. If we want the new, derived class to be generic it should also be a template class; and pass its template parameter along to the base class.
CLASS TEMPLATE WITH MULTIPLE PARAMETERSWe can use more than one generic data type in a class template, and each generic data type is separated by the comma.
The compiler usually instantiates members of template classes independently of other members, so that the compiler instantiates only members that are used within the program. Methods written solely for use through a debugger will therefore not normally be instantiated.
Function templates. Function templates are special functions that can operate with generic types. This allows us to create a function template whose functionality can be adapted to more than one type or class without repeating the entire code for each type. In C++ this can be achieved using template parameters.
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.)
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With