5

上一个问题

我重复上一个问题的代码以使这个问题自成一体。如果使用 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"));
}
4

1 回答 1

6

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 中引入的一个特性。包含此代码片段的程序是格式错误的。但是,该标准并未强制要求实现(编译器)必须拒绝格式错误的程序。它仅在 [intro.compliance]/2.2 中声明:

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

在 /8

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

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

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

于 2014-12-24T01:31:18.283 回答