lambdas中的auto模板参数列表是标准的一部分吗?

时间:2015-09-01 01:33:49

标签: c++ templates c++11 lambda type-deduction

今天,我偶然发现了以下代码段:

#include <utility>

int main()
{

  auto a = [](std::pair<auto, auto> value)
  {

  };

  a(std::pair<int, bool>{ 3, true });
}

http://cpp.sh/5p34

我只有一个问题:标准是否支持此代码?

它在GCC中编译(使用-std=c++14),但不是clang或Visual Studio 2015(VC ++ 14)。

这似乎应该是标准的一部分,因为如果lambdas应该具有与常规函数相同的模板支持,那么应该支持它。

这似乎转换为所有模板类型,而不仅仅是std::pair

2 个答案:

答案 0 :(得分:8)

在C ++ 14中,模板参数中不允许auto,无论是否在lambda中。 Clang和Visual Studio都拒绝接受此代码。

C ++ 14标准参考是[dcl.spec.auto]。在以下上下文中允许auto说明符:

  • 在函数声明符的 decl-specifier-seq 中(例如auto f();)(第2段)
  • conversion-function-id ,例如类中的operator auto())(第2段)
  • 在函数声明符的 trailing-return-type 中(例如auto f() -> auto;)(第2段)
  • 在lambda的参数声明(作为 decl-specifiers 之一)的 decl-specifier-seq 中3); - 这是允许通用lambda存在的原因 -
  • 在块范围或命名空间范围内声明变量(第4段)
  • 在for循环控制变量的声明中(第4段),包括基于范围的for循环(第5段)
  • ifswitch声明或循环(第5段)的情况下
  • new表达式中, new auto(42)(第5段)
  • 在类定义中声明静态数据成员(第5段)

最后,

  

在本节未明确允许的上下文中使用autodecltype(auto)的程序格式不正确。

因此,模板参数中不允许auto,因为[dcl.spec.auto]中没有枚举该情况。

我不知道为什么gcc允许它。它可能与Concepts Lite有关,但我不知道Concepts Lite是否实际允许这种用法。它可能只是一个易于实现的无关扩展。我认为

[](std::pair<auto, auto> value) { /* ... */ }

被翻译成

struct __some_unique_name {
    template <typename T1, typename T2>
    auto operator()(std::pair<T1, T2> value) const { /* ... */ }
    // ...
};

答案 1 :(得分:2)

据我所知,这是concepts lite的一部分,gcc允许这作为C ++ 14中的扩展,类似于'auto' not allowed in function prototype with Clang中的问题,尽管与之前使用{{1}的情况不同不会像扩展名那样产生警告。

据我所知,上面链接的概念精简提案中最相关的更改允许这是-pedantic [dcl.spec.auto] 和{{1}部分} [dcl.fct] ;来自7.1.6.4

  

修改段落3以允许在lambda或函数的参数类型中使用auto。

     
      
  1. 如果auto类型说明符出现,作为参数声明的decl-specifier-seq中的decl-specifiers之一   lambda表达式的参数类型,lambda是一个通用的lambda   (5.1.2)。 [例如:

         

    auto glambda = [](int i,auto a){return i; }; //好的:通用lambda

  2.         

    结束示例] 同样,如果auto类型说明符出现在函数声明的参数类型中,则函数声明   声明一个缩写的函数模板(8.3.5)。 [例如:

    8.3.5
         

    - 结束示例]

7.1.6.4

  

在第15段之后添加以下段落。

     
      
  1. 缩写函数模板是一个函数声明,其参数类型列表包含一个或多个占位符(7.1.6.4,   7.1.6.5)。缩写函数模板相当于函数模板(14.5.6),其模板参数列表包含一个发明的函数模板   每次出现占位符的模板参数   参数声明子句,按出现顺序排列。如果   占位符由auto类型说明符指定,然后是   相应的发明模板参数是一种类型   模板参数。否则,占位符由a指定   约束类型说明符,以及相应的发明参数   匹配原型参数(?)的类型和形式   约束类型指定符指定的概念(14.9.5)。该   发明的模板参数是一个参数包,如果相应的话   parameter-declaration声明一个函数参数包和类型   该参数仅包含一个占位符。如果原型   指定概念的参数声明模板参数   pack,相应的参数声明应声明一个函数   参数包。调整后的函数参数为缩写   函数模板是从parameter-declaration-clause派生的   用名称替换占位符的每个匹配项   相应的发明模板参数。如果更换一个   占位符与模板参数的名称导致   参数声明无效,程序格式不正确。 [例如:

    void f(const auto&, int); // OK: an abbreviated function template
    
  2.         

    [...]