I have a class that works as wrapper for some primitives or custom types. I want to write explicit specialization for custom template type. My code that reproduces the problem:
template < class T >
struct A {
void func() { std::cout << "base\n"; }
};
template <>
struct A<int> {};
template < class T, class CRTP >
struct BaseCrtp {
void someFunc() {
CRTP::someStaticFunc();
}
};
struct DerrType : BaseCrtp<int, DerrType> {
static void someStaticFunc() {}
};
template < class T, class CRTP >
struct A< BaseCrtp<T, CRTP> > {
void func() { std::cout << "sometype\n"; }
};
int main() {
A<DerrType> a;
a.func(); // print: "base". should be: "sometype"
return 0;
}
A<DerrType> use default function, not a specialization. How can I make specialization for these set of classes?
I will have a lot of types like DerrType, and I want to make common behavior for all of them.
DerrType and others will be used as curiously recurring template pattern
Not sure I fully understood what you want, but maybe something like this:
The concept basically checks whether
Tis equal to or is publicly inherited (directly or indirectly) from some specialization ofBaseCrtp. Otherwise the call to the lambda would be ill-formed. Template argument deduction only succeeds in the call if the argument and parameter type match exactly or the argument has a derived type of the parameter. If the class is inherited non-publicly, the reference in the call can't bind to the parameter.The concept will however fail if the type is inherited from multiple
BaseCrtpspecializations, in which case template argument deduction on the call will not be able to choose between the multiple choices.Alternatively you can also use the stricter concept
which will also require that the type
Tis actually using the CRTP pattern onBaseCrtp(directly or through a some base class betweenBaseCrtpandT). Again, this will fail ifTis inherited multiple times from someBaseCrtp<U, T>specialization, although it will ignore specializations with a type other thanTin the second position.For another alternative you might want to check that
Tis derived from some typeXsuch thatXis derived fromBaseCrtp<U, X>for someU(meaning thatXuses the CRTP pattern correctly). That could be done using this variation:Again, this fails if
Tis derived from multipleBaseCrtpspecializations, directly or indirectly.