Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Derive class A from a template class Base<A> so that Base<A> can use A::B?

Tags:

c++

template <typename T>
class Base
{
private:
    typename T::B c;
};

class A : public Base<A>
{
public:
    class B;
};

Is something like this even possible? VC++ 2013 says B is not a member of A.

like image 386
NFRCR Avatar asked Mar 24 '14 12:03

NFRCR


People also ask

How do you derive a class from base class?

Protected Inheritance − When deriving from a protected base class, public and protected members of the base class become protected members of the derived class. Private Inheritance − When deriving from a private base class, public and protected members of the base class become private members of the derived class.

Can a template base class derived?

It is possible to inherit from a template class. All the usual rules for inheritance and polymorphism apply. If we want the new, derived class to be generic it should also be a template class; and pass its template parameter along to the base class.

Can a derived class be a base class for another class?

Derived classes acquire the properties of an existing class. The original class is called the base class. A derived class inherits member functions of base class. A derived class can be used anywhere the base class is expected.

What can be inherited by a derived class from a base class?

Which among the following is inherited by a derived class from base class? Explanation: The class inheriting another class, inherits all the data members and member functions that are not private. This is done to ensure the security features with maximum flexibility. 3.


1 Answers

THE STORY

As stated in the comments directly on your question what you are trying to accomplish simply isn't possible since it's illegal to refer to an incomplete type (which T = A is inside Base).


THE WORKAROUND

The common workaround in cases of CRTP is to use a trait to denote members that should be available in both Derived and Base, but which are not meant to be declared/defined in Base.

Even though this isn't really equivalent of what you are trying to accomplish it is very close to it, and follow somewhat equivalent semantics.

template<class> struct some_trait;       // primary template

template <class T>
struct A : some_trait<T> {               // (1)
  typename some_trait<T>::C a;
};

template<> struct some_trait<struct B> { // (2)
  class C { };
};

struct B : A<B> {                        // (3)
  C b;
};

int
main (int argc, char *argv[])
{
  B a; // legal
}

WHY DOES THE WORKAROUND... WORK?

To cut it short; we are no longer trying to access the internals of an incomplete type.

some_trait<B> is a complete type directly after it's definition (ie. the specialization) marked (2), and because of this it can be used by (1) and (3) without causing any issues.

like image 79
Filip Roséen - refp Avatar answered Sep 30 '22 18:09

Filip Roséen - refp