The curiously recurring template pattern may be used to implement a sort of static polymorphism. For example:
#include <iostream>
template<
class Derived
>
struct Base
{
static void print ( )
{
std::cout << Derived::number_to_print << '\n';
}
};
struct Derived final :
Base<
Derived
>
{
static constexpr unsigned int number_to_print = 27;
};
int main ( )
{
Derived::print();
}
This behaves as expected and prints 27
.
Now, I would like to add checks to the base class to assert that derived classes meet certain requirements. In the example given above, such checks could be:
#include <iostream>
#include <type_traits>
template<
class Derived
>
struct Base
{
// --- Checks begin
static_assert( std::is_same<
decltype(Derived::number_to_print),
unsigned int
>::value,
"static member `number_to_print' should be of type `unsigned int'" );
// --- Checks end
static void print ( )
{
std::cout << Derived::number_to_print << '\n';
}
};
struct Derived final :
Base<
Derived
>
{
static constexpr unsigned int number_to_print = 27;
};
int main ( )
{
Derived::print();
}
This doesn't work because, at the point where Base<Derived>
is instantiated, Derived
has only been forward-declared, i.e., it's incomplete, and nothing of it is yet known beyond the fact that it's a struct.
I've been scratching my head, as I think these checks could prove helpful to users of the base class, but haven't found any way to do this.
Is it possible?, and if so, how?