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.