我重复上一个问题的代码,使这个问题自成一体。如果使用gcc 4.8.3编译,下面的代码将编译并不会发出任何警告。与-std=c++1y
。但是,如果使用-std=c++0x
标志进行编译,它会发出警告。在上一个问题的上下文中,声明代码不使用gcc 4.9.0进行编译。不幸的是,目前我还不完全了解auto
的实施方式。因此,如果有人能回答以下问题,我将不胜感激:
1)。下面的代码是否与C ++ 14标准有效?
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"));
}
答案 0 :(得分:6)
1)。下面的代码是否与C ++ 14标准有效?
是的,据我所知。它有时候有点难以证明,因为通常没有什么可以禁止的。但是,我们可以看一下最近草案中的一个例子(后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开发人员为什么他们已将其从警告更改为错误。)