【问题标题】:Partial specialization or instantiation of template class method模板类方法的部分特化或实例化
【发布时间】:2019-09-06 23:01:12
【问题描述】:

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

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 和类型 trait is_void_v 组合,但我想知道是否有办法:

  • 模板类方法部分显式的特化

  • 模板类方法的实例化

【问题讨论】:

  • void main() 无效,已为您修复
  • @user463035818 编译器不会抱怨你没有从 main 返回任何东西吗?
  • @Chipster main 是一个例外,其中return 是可选的,如果您不编写它,编译器将为您提供return 0;
  • 对我来说,使用类模板的部分特化似乎是一个好策略。您在使用过程中是否遇到任何问题?

标签: c++ templates


【解决方案1】:

虽然你做不到

Result foo()
{
    return Result{};
}

如果Resultvoid,你可以使用

Result foo()
{
    return Result();
}

在这种情况下的行为是相同的,你会得到一个值初始化对象返回。当 Resultvoid by [expr.type.conv]\2 时,允许使用此语法

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

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

return Result{};

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

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

【讨论】:

  • daaaaaaaaaaaaamn,非常感谢。通常我避免将 () 用于构造函数,但在这种情况下我必须使用它
  • @Demaunt 是的,不幸的是统一初始化是完全统一的。幸好这个案子正在修复中。
  • 统一初始化一致性的另一个例子;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多