Dmi*_*bev 3 c++ templates partial-specialization template-specialization c++20
我有一个类可以用作某些基元或自定义类型的包装器。我想为自定义模板类型编写显式专业化。我的代码重现了该问题:
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;
}
Run Code Online (Sandbox Code Playgroud)
A<DerrType>使用默认函数,而不是专门化。我怎样才能针对这些课程进行专门化?我将有很多类型,例如DerrType,并且我想为所有类型制定共同的行为。
DerrType和其他将被用作奇怪的重复模板模式
不确定我完全理解你想要什么,但也许是这样的:
template<typename T>
concept DerivedFromBaseCrtp = requires(T& t) {
[]<typename U, typename CRTP>(BaseCrtp<U, CRTP>&){}(t);
};
template < DerivedFromBaseCrtp T >
struct A<T> {
void func() { std::cout << "sometype\n"; }
};
Run Code Online (Sandbox Code Playgroud)
该概念基本上检查是否T等于或从 的某些专业化公开继承(直接或间接)BaseCrtp。否则对 lambda 的调用将是错误的。仅当参数和参数类型完全匹配或者参数具有参数的派生类型时,模板参数推导才会在调用中成功。如果该类是非公开继承的,则调用中的引用无法绑定到参数。
然而,如果类型是从多个 BaseCrtp专业化继承的,则该概念将失败,在这种情况下,调用上的模板参数推导将无法在多个选择之间进行选择。
或者,您也可以使用更严格的概念
template<typename T>
concept CrtpDerivedFromBaseCrtp = requires(T& t) {
[]<typename U>(BaseCrtp<U, T>&){}(t);
};
Run Code Online (Sandbox Code Playgroud)
这还要求该类型T实际上使用 CRTP 模式(直接或通过和BaseCrtp之间的某个基类)。同样,如果从某些特化多次继承,这将会失败,尽管它会忽略第二个位置以外的类型的特化。BaseCrtpTTBaseCrtp<U, T>T
对于另一种选择,您可能想要检查是否T派生自某种类型X,例如X派生自BaseCrtp<U, X>某些类型U(意味着X正确使用 CRTP 模式)。这可以使用以下变体来完成:
template <typename T>
concept CrtpDerivedFromBaseCrtp =
requires(T& t) {
[]<typename U, typename CRTP>(BaseCrtp<U, CRTP>&)
requires(std::is_base_of_v<CRTP, T> &&
std::is_base_of_v<BaseCrtp<U, CRTP>, CRTP>)
{}
(t);
};
Run Code Online (Sandbox Code Playgroud)
同样,如果直接或间接T源自多个BaseCrtp专业化,则此方法会失败。