在C++ 14中使用自动返回'type'进行显式模板特化是否有效?

5 c++ explicit-specialization auto c++11 c++14

上一个问题.

我重复上一个问题的代码,使这个问题自成一体.如果使用gcc 4.8.3编译,下面的代码将编译并不会发出任何警告.与-std=c++1y.但是,如果使用-std=c++0xflag 编译,它会发出警告.在前一个问题的上下文中,声明代码不使用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"));
}
Run Code Online (Sandbox Code Playgroud)

dyp*_*dyp 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
Run Code Online (Sandbox Code Playgroud)

同一段落规定:

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

因此,函数模板的显式特化必须使用返回类型推导.我找不到任何禁止不同特殊化的不同返回类型的东西.类似地,在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开发人员为什么他们已将其从警告更改为错误.)