Uzaku
Uzaku

Reputation: 541

How to tell a Template that the Parameter is derived from a certain class

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

Answers (1)

Deduplicator
Deduplicator

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

Related Questions