Why won't the compiler select the Interface template when running the following code? Are additional declarations / hints needed or won't this work in general?
I'm just curious if this is actually possible.
class Interface {
public :
virtual void Method() = 0;
virtual ~Interface() { }
};
class Derived : Interface {
public :
void Method() {
cout<<"Interface method"<<endl;
}
};
template<typename T>
struct Selector {
static void Select(T& o) {
cout<<"Generic method"<<endl;
}
};
template<>
struct Selector<Interface> {
static void Select(Interface& o) {
o.Method();
}
};
int i;
Selector<int>::Select(i) // prints out "Generic method" -> ok
Derived d;
Selector<Derived>::Select(d); // prints out "Generic method" -> wrong
// should be "Interface method"
Try this (and #include <type_traits>
):
template <typename T, typename = void>
struct Selector
{
static void Select(T & o)
{
std::cout << "Generic method" << std::endl;
}
};
template <typename T>
struct Selector<T,
typename std::enable_if<std::is_base_of<Interface, T>::value>::type>
{
static void Select(Interface & o)
{
o.Method();
}
};
It turns out that enable_if
combined with defaulted template arguments can be used to guide partial specialisations.
The compiler will select the version of a function that is the closest match. A function that takes the exact type for a parameter always wins over one that requires a conversion. In this case the template function is an exact match, since it matches anything; the Interface
specialization would require the conversion of the parameter from a Derived
to an Interface
.
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