c++templatesinheritancecrtp

Base Class accepting template arguments of child class and inner child class


I am making a library and I want a user to be able to instantiate it like this:

int main (int, char**)
{
    Child_Type1<int> c1 = Child_Type1<int>();
    Child_Type2<int> c2 = Child_Type2<int>();
    // ...
}

The Base class is defined with three template arguments and is used as interface to all deriving classes. Type T represents the data type, type U represents the deriving class itself and type W represents the inner class of U.

template <class T, class U, class W>
class Base
{
public:
    virtual void test(void) = 0;
};

One of the deriving classes would be:

template <class T>
class Child_Type1
{
    class Inner;

public:
    Inner* var;

    void test(void) override
    {
        // some code here
    }
};

With the nested class Inner being defined across all Child_TypeX with the same name, but different elements, like for example:

template <class T>
class Child_Type1::Inner
{
    T some_variable;
};

template <class T>
class Child_Type2::Inner
{
    T other_variable
};

// etc.

When I try to create inheritance such as:

template <class T>
class Child_Type1 : public Base<T, Child_Type1<T>, Child_Type1<T>::Inner>

I run into the problem since the Child_Type1::Inner does not exist yet. Since I cannot forward declare it prior to this inheritance, I am wondering if someone has an idea how to hack this around.


Solution

  • You might declare/define Inner outside:

    template <typename T>
    struct Inner;
    
    template <class T> class Child_Type1;
    template <class T> class Child_Type2;
    
    template <typename T>
    struct Inner<Child_Type1<T>>
    {
        T some_variable;
    };
    template <typename T>
    struct Inner<Child_Type2<T>>
    {
        T other_variable;
    };
    

    And then

    template <class T>
    class Child_Type1 : public Base<T, Child_Type1<T>, Inner<Child_Type1<T>>>
    {
    public:
        Inner<Child_Type1<T>>* var;
    
        void test() override
        {
            // some code here
        }
    };