0

I would like to know the C++ equivalent of the following Java code.

public Class MyClass <T extends MyClass<T>> {...}

I have tried the following but failed using C11:

template <class T> class Parent {
    static_assert(std::is_base_of<Parent<T>, T>::value);
public:
    T* next;
};

class Child: public Parent<Child> {
public:
    Child* next;
};

Which results in:

incomplete type `Child` used in type trait expressions
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Alphaharrius
  • 210
  • 1
  • 9
  • 2
    Can you provide a [mcve] as required here please. – πάντα ῥεῖ Jul 26 '22 at 11:19
  • 2
    what is the actual problem you are trying to solve? I have a hard time to understand the title. force a derived class to inherit from its base? You dont need to "force" anything. Once Child inherits from Parent it does already inherit from Parent. I suppose you actually want to ask "How to require a template type argument of Parent to derive from Parent?" – 463035818_is_not_an_ai Jul 26 '22 at 11:20
  • btw I suggest to not try too hard to see parallels between Java generics and C++ templates, under the hood they are rather different concepts (and also not under the hood) – 463035818_is_not_an_ai Jul 26 '22 at 11:22
  • 1
    This is known as the CRTP (Curiously Recurring Template Pattern) and is widely used. The `next` member is not necessary, btw. you can static cast Parent up to Child. – bitmask Jul 26 '22 at 11:29
  • 1
    See https://stackoverflow.com/questions/4173254/what-is-the-curiously-recurring-template-pattern-crtp – πάντα ῥεῖ Jul 26 '22 at 11:32
  • @463035818_is_not_a_number sorry to be unclear on the topic... What I am trying to do is to create a template linked list nodes so that other classes can inherits. But the problem is I dont want the ```next``` variable to have the type of the super class but the child class itself. Just wondering if there is a way to do that. – Alphaharrius Jul 26 '22 at 14:07

1 Answers1

2

Unfortunately, within CRTP, T is an incomplete type (so most traits won't work on it).

You might add the check in a member instead (type would be complete at that point).

Good candidates are constructor and destructor:

template <class T>
class Parent
{
    // T is incomplete here.
public:
    ~Parent() noexcept
    {
       // T is complete here.
       static_assert(std::is_base_of<Parent<T>, T>::value);
    }
public:
    T* next;
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302