针对未来派生类型的基本模板类型的模板专门化

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和其他将被用作奇怪的重复模板模式

use*_*522 5

不确定我完全理解你想要什么,但也许是这样的:

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专业化,则此方法会失败。