【问题标题】:Is it valid to do explicit template specialisation with auto return 'type' in C++14?在 C++14 中使用自动返回“类型”进行显式模板特化是否有效?
【发布时间】:2015-02-22 03:41:09
【问题描述】:

Previous question.

我重复上一个问题的代码以使这个问题独立。如果使用 gcc 4.8.3 编译下面的代码,它不会发出任何警告。与-std=c++1y。但是,如果使用-std=c++0x 标志编译,它会发出警告。在上一个问题的上下文中,有人说代码不能使用 gcc 4.9.0 编译。不幸的是,目前我还没有完全理解auto是如何实现的。因此,如果有人能回答以下问题,我将不胜感激:

1)。就 C++14 标准而言,下面的代码是有效的 C++ 吗?

2)。如果是的话,这段代码会被认为是一种好的风格吗?如果没有,为什么不呢?

3)。为什么在使用 C++11 编译器时下面的代码会编译和工作(有时)?或者,为什么它并不总是有效?是否有任何特定的标志/选项/设置可能会阻止它工作?

template<int N> auto getOutputPort2();
template<> auto getOutputPort2<0>();
template<> auto getOutputPort2<1>();

template<>
auto getOutputPort2<0>()
{
    return std::unique_ptr<int>(new int(10));
}

template<>
auto getOutputPort2<1>()
{
    return std::unique_ptr<string>(new string("qwerty"));
}

【问题讨论】:

  • 参见 [dcl.spec.auto]/13 “具有使用占位符类型的已声明返回类型的函数或函数模板的重新声明或特化也应使用该占位符,而不是推导类型。”
  • 对我来说,使用 auto 似乎很好。使用 int 值来打开同一函数的不同含义看起来很可疑。
  • “如果是,这段代码会被认为是一个好的样式吗?如果不是,为什么不呢?” 对于这部分问题,我建议你在@上提问987654322@
  • “工作(有时)”是什么意思?
  • @frasnian 恐怕这是对我之前问题的引用(请参阅本问题开头的链接之一)。使用 c++11 时,代码不使用 gcc 4.9 编译,而是编译(带有警告)并按预期使用 gcc 4.8.3 运行。

标签: c++ c++11 auto c++14 explicit-specialization


【解决方案1】:

1)。就 C++14 标准而言,下面的代码是有效的 C++ 吗?

是的,据我所知。有时很难证明,因为通常没有什么可以禁止它。但是,我们可以在最近的草稿(N4296 后)[dcl.spec.auto]/13 中查看一个示例:

template <typename T> auto g(T t) { return t; } // #1
template auto g(int);                           // OK, return type is int
template char g(char);                          // error, no matching template
template<> auto g(double);                      // OK, forward declaration with
                                                // unknown return type

同一段指定:

具有使用占位符类型的已声明返回类型的函数或函数模板的重新声明或特化也应使用该占位符,而不是推导类型。

所以函数模板的显式特化必须使用返回类型推导。 我找不到任何禁止不同专业化的不同返回类型的东西。类似地,在 C++98 中,可以通过使返回类型依赖于模板参数来实现(同一主模板的)函数模板特化的不同返回类型。通过使用元编程,您基本上可以实现与使用返回类型推导为不同专业指定不相关的返回类型时相同的效果。


3)。为什么下面的代码似乎使用 C++11 编译器编译和工作(有时)?

OP 中的代码在 C++11 中格式错误。普通函数(非 lamdas)的返回类型推导是 C++14 中引入的一个特性。包含此代码 sn-p 的程序是格式错误的。但是,该标准并未强制要求实现(编译器)必须拒绝格式错误的程序。它只是在 [intro.compliance]/2.2 中声明:

如果程序包含违反任何可诊断规则的行为 [...] 符合要求的实现应发出至少一条诊断消息。

在 /8 中

只要不改变任何格式良好的程序的行为,符合标准的实现可能具有扩展(包括额外的库函数)。需要实现来诊断使用根据本国际标准格式错误的扩展的程序。然而,这样做之后,他们就可以编译和执行这样的程序了。

(因此实现可以接受这个程序作为扩展。)

g++4.8.3 发出警告,这被视为诊断消息。 g++4.9 发出一个错误,这也是一个诊断消息。两者都是合规的。通过指定-Werror,您可以告诉 g++4.8.3 拒绝该程序。 (您必须询问 gcc 开发人员为什么将其从警告更改为错误。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-26
    • 1970-01-01
    • 2022-01-23
    • 2013-09-02
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    • 2013-12-20
    相关资源
    最近更新 更多