I am trying to specialize a template this way:
class PropertyBase
{
public:
SfPropertyBase(string name)
{
Name = name;
}
virtual ~SfPropertyBase() {}
string Name;
virtual bool FromString(Object* obj, string str) = 0;
};
template< typename T>
class Property : public SfPropertyBase
{
public:
Property(string name) : SfPropertyBase(name)
{
//specific to Property stuff
}
template<typename U = T>
typename std::enable_if<(std::is_class<U>::value && std::is_pointer<U>::value), bool>::type
FromString(Object* obj, string str)
{
//do something
return true;
}
template<typename U = T>
typename std::enable_if<!std::is_class<U>::value || !std::is_pointer<U>::value), bool>::type
FromString(Object* obj, string str)
{
//do something
return true;
}
}
Then, when I try to initialize an instance of this class:
auto prop = new Property<int>("IntProperty");
I get invalid new-expression of abstract class type Property<int>
. I understand that there is an abstract function in PropertyBase
, but I also provide both specializations for Property
, where T
is a class and where it isn't.
What is going on and how to fix it?
Note: what I want to achieve is to specialize FromString
if T is a class/pointer and all the other cases.
Both the FromString
in Property
are function template, they can't override the non-template virtual
function of the base class. (In fact functions templates cannot be virtual
functions).
You could add another non-template FromString
in Property
; and you can ensure the overriding by using the keyword orverride
. e.g.
bool FromString(Object* obj, string str) override {
return FromString<>(obj, str);
}
LIVE
A function template cannot be used as an overrider for a non-template virtual function. A function template is not a function, it's a recipe for creating functions on demand when a call is made.
Code will have to call FromString
on your derived class object directly for SFINAE to work. If you want to provide a different overrider based on the template parameter type, one approach is to go via an intermediate base.
template<typename T, typename = void>
struct FromStringProvider;
template<typename T>
struct FromStringProvider<T, typename std::enable_if<(std::is_class<U>::value && std::is_pointer<U>::value)>::type> : SfPropertyBase {
bool FromString(Object* obj, string str) override
{
//do something
return true;
}
};
If you need access to the deriving class, then a CRTP based approach can be used. Just pass the deriving class as an extra parameter and rely on its static interface to access the parts you need.
This alternative approach is especially useful if you have sets of virtual functions, all under the same conditions.
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