C++ 防止编译完整模板特化

Jef*_*f G 1 c++ templates template-specialization c++17

我有如下代码,将模板类型映射到枚举值。但是,MyEnum::C仅当代码使用 template 时才定义该值something<double>。有没有办法更改模板声明/定义,以便可以编译以下内容?

例如,我想如果我在模板声明的末尾添加一个默认模板参数something,就足以使完整的专业化成为部分专业化,这只会在使用时编译专业化。但是,我无法找出正确的语法来执行此操作。

#include <iostream>

using namespace std;

enum class MyEnum
{
    A,
    B
};

template<typename T>
struct something;

template<>
struct something<int>
{
    static constexpr auto value = MyEnum::A;
};

template<>
struct something<double>
{
    static constexpr auto value = MyEnum::C;
};

int main()
{
    cout << static_cast<int>(something<int>::value) << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我认为以下内容会起作用,但没有:

template<typename T>
constexpr MyEnum toEnum()
{
    if constexpr (std::is_same_v<int, T>)
        return MyEnum::A;
    else if constexpr (std::is_same_v<double, T>)
        return MyEnum::C;
}
Run Code Online (Sandbox Code Playgroud)

Bri*_*ian 7

即使您something<double>根据其他模板参数将完全专业化更改为部分专业化T,您仍然不能MyEnum::C在该专业化内部使用并期望您的程序格式良好,因为MyEnum::C是一个非依赖的构造,编译器可能会拒绝包含无效的模板非依赖构造,即使这些模板从未被实例化。

出于同样的原因,坚持MyEnum::C到废弃的if constexpr分支并不会使程序有效。

但是,您可以执行以下操作:

template<typename T, typename E = MyEnum>
struct something;

template<>
struct something<int>
{
    static constexpr auto value = MyEnum::A;
};

template<typename E>
struct something<double, E>
{
    static constexpr auto value = E::C;
};
Run Code Online (Sandbox Code Playgroud)

现在,你不再直接提及MyEnum::C;依赖构造E::C可能有效也可能无效,具体取决于是否E实际上最终成为MyEnum

我不知道这个策略是否适合您的特定用例。