Reputation: 3975
Suppose I have a base class like this:
class Abstract {
public:
/* This type should be the deriver of this class */
virtual DerivedType foo(void) = 0;
};
And I want DerivedType
to be different depending on who derives from this class. In fact I want DerivedType
to be the type that Derives
from Abstract
.
I realize that I could do something like this:
template<typename der_t>
class Abstract {
public:
virtual der_t foo(void) = 0;
};
And then it should be used like this:
class Derived : public virtual Abstract<Derived> { };
Unfortunately there is no way to force someone to pass in the right type in the template. That is someone could do this:
class Derived : public virtual Abstract<int> { };
So is there any better way to do this, or is there a way to force someone to pass in the right parameter?
Upvotes: 2
Views: 90
Reputation: 63124
The usual trick for CRTP's is to have a private constructor that only the passed-in class can access via a friend
directive:
template <class Derived>
struct Crtp {
private:
friend Derived;
Crtp() = default;
};
It isn't perfect, but guards against errors.
Note : static_assert
ing is not a practical solution, because at the time Crtp
is instantiated Derived
is still incomplete, and can't be checked for base classes.
Upvotes: 2