Home > Back-end >  Class template refers to itself in type-constraint expression
Class template refers to itself in type-constraint expression

Time:08-11

I'm trying to implement CRTP with C 20 concept. The key is to prevent the parent class template from being instantiated by any type argument except its subclass.

Compiler complains about the self-referencing CRTP_Root in the requires-clause:

#include <concepts>

//error: ‘CRTP_Root’ was not declared in this scope
//     | requires std::derived_from<derived_type, CRTP_Root<derived_type>>

template<typename derived_type>
requires std::derived_from<derived_type, CRTP_Root<derived_type>>
class CRTP_Root {

};

class CRTP_child : public CRTP_Root<CRTP_child> {

};

Since requires-clause must be part of the declaration, there seems no way to write a forward declaration of such self-referring constrained class template. Is there any workaround?

CodePudding user response:

If you just want to prevent the parent class template from being instantiated by any type argument except its subclass. one possible solution might be making the CRTP_Root's ctor private, and use friend to decorate derived_type

template<typename derived_type>
class CRTP_Root {
public:
  // polymorphic interfaces
private:
  CRTP_Root() {}
  friend derived_type;
};

class CRTP_child : public CRTP_Root<CRTP_child> {

};

CodePudding user response:

You could use CRTP to refer to yourself in the constraints.

template<typename derived_type, template <typename> typename tml_base>
requires std::derived_from<derived_type, tml_base<derived_type>>
struct CRTP_Helper {};

template<typename derived_type>
class CRTP_Root : CRTP_Helper<derived_type, CRTP_Root> {};

The problem here is you can't check it because the derived class is incomplete at that time.

See the error message in Demo.

  • Related