首页 > 解决方案 > 模板类方法的部分特化或实例化

问题描述

我有带有几个模板参数的模板结构

template<class Result, class T, class K>
struct MyClass
{
public:
    Result foo()
    {
        return Result{};
    }
};

除了 Result 为 void 的情况外,此结构适用于所有模板。我知道,这Result{}不能实现为 void 类型,所以我目前的解决方案是使用这样的部分专业化:

template<class T, class K>
struct MyClass<void, T, K>
{
public:
    void foo()
    {
        return;
    }
};

这允许执行以下操作:

int main()
{
    MyClass<void, double, char> mycl1;
    MyClass<int, double, char> mycl2;

    mycl1.foo();
    mycl2.foo();
}

有没有办法mycl1.foo()在 C++ 14 标准中不进行部分类专业化的编译?我可以使用if constexr并输入特征is_void_v组合,但我想知道是否有办法:

标签: c++templates

解决方案


虽然你做不到

Result foo()
{
    return Result{};
}

如果Resultvoid,您可以使用

Result foo()
{
    return Result();
}

这种情况下的行为是相同的,您将返回一个值初始化对象。Result当is voidby [expr.type.conv]\2时允许使用此语法

如果初始值设定项是带括号的单个表达式,则类型转换表达式等效于(在定义上,如果在含义上定义)对应的强制转换表达式。如果类型是 cv void 并且初始化程序是 (),则表达式是指定类型的纯右值,不执行初始化。否则,表达式是指定类型的纯右值,其结果对象使用初始化程序直接初始化。对于 T() 形式的表达式,T 不应是数组类型。

即将推出,但您将能够使用

return Result{};

即使ResultvoidC++20 添加到该部分{}也适用于void. [expr.type.conv]\2现在状态

如果初始值设定项是带括号的单个表达式,则类型转换表达式等价于相应的强制转换表达式。否则,如果类型是 cv void 并且初始化程序是 () 或 {}(在包扩展之后,如果有),则表达式是指定类型的纯右值,不执行初始化。否则,表达式是指定类型的纯右值,其结果对象使用初始化程序直接初始化。如果初始值设定项是带括号的可选表达式列表,则指定类型不应是数组类型。


推荐阅读