Reputation: 541
Right now, I'm writing a program on a feature-based approach. Every functionality besides the bare skeleton comes as its own package, derived from a feature class.
I have the Following Header definition:
class Feature
{
public:
Feature(std::string Name)
: Parent(nullptr), Name(Name)
{
if (FeatureNames.count(Name) == 0)
FeatureNames.insert(Name);
else
throw std::logic_error(std::string("Feature: The Feature with the name '") + Name + "' already exists");
}
virtual ~Feature(){}
const std::string &getName(){ return Name; }
virtual void shutDown() = 0;
protected:
Feature *Parent;
private:
static std::set<std::string> FeatureNames;
std::string Name;
};
template<class ChildFeat>
class FeatureEx : public Feature
{
public:
FeatureEx(std::string Name) :Feature(Name){}
virtual ~FeatureEx(){}
void addChildFeature(ChildFeat *Child);
protected:
std::vector<ChildFeat*> Children;
};
//implementation
template<class ChildFeat>
void FeatureEx<ChildFeat>::addChildFeature(ChildFeat *child)
{
Children.push_back(child);
child->Parent = this;
}
And I have a Feat-class and a ChildFeat-Class, like the following:
class FeatureClass : public FeatureEx<MyChildFeatureInterface>
{
...
}
class MyChildFeat : public Feature, public MyChildFeatureInterface
{
...
}
When I now try to call the addChildFeature()
method on an Instance of FeatureClass
the compiler is crying, because the addChildFeat()
method only sees a MyChildFeatureInterface
, which of course does not have the member Parent
.
I could easily bypass this problem by deriving MyChildFeatureInterface
directly from Feature
, but on the one hand I find that sub-optimal and on the other hand I was wondering whether there is a way to tell the Compiler: "This template Argument, can be any class, BUT IT MUST BE DERIVED from class X".
Upvotes: 0
Views: 134
Reputation: 45654
Sure, you can easily say to the compiler that a class must be derived from Base.
An example with a function:
template<class X> auto my_function1(X&& x)
-> decltype(*declval<const volatile Base**>() = &x, declval<void>());
If x
is not a kind of Base
, so does not derive from it, the assignment is ill-formed and thus the function is removed from consideration at the overload-resolution step.
I like this form, because it is immediately transferable to checking any odd expressions you might want.
Or using the pre-packaged tests from the standard-library as Matthieu M. rightly mentions in a comment (only work on classes):
template<class X> auto my_function2(X&& x)
-> enable_if_t<is_base_of<Base, typename decay<X>::type>::value, void>;
Upvotes: 2