今天,我偶然发现了以下代码段:
#include <utility>
int main()
{
auto a = [](std::pair<auto, auto> value)
{
};
a(std::pair<int, bool>{ 3, true });
}
我只有一个问题:标准是否支持此代码?
它在GCC中编译(使用-std=c++14
),但不是clang或Visual Studio 2015(VC ++ 14)。
这似乎应该是标准的一部分,因为如果lambdas应该具有与常规函数相同的模板支持,那么应该支持它。
这似乎转换为所有模板类型,而不仅仅是std::pair
。
答案 0 :(得分:8)
在C ++ 14中,模板参数中不允许auto
,无论是否在lambda中。 Clang和Visual Studio都拒绝接受此代码。
C ++ 14标准参考是[dcl.spec.auto]。在以下上下文中允许auto
说明符:
auto f();
)(第2段)operator auto()
)(第2段)auto f() -> auto;
)(第2段)if
或switch
声明或循环(第5段)的情况下new
表达式中,即 new auto(42)
(第5段)最后,
在本节未明确允许的上下文中使用
auto
或decltype(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。
- 醇>
如果auto类型说明符出现
,作为参数声明的decl-specifier-seq中的decl-specifiers之一lambda表达式的参数类型,lambda是一个通用的lambda (5.1.2)。 [例如:auto glambda = [](int i,auto a){return i; }; //好的:通用lambda
结束示例] 同样,如果auto类型说明符出现在函数声明的参数类型中,则函数声明 声明一个缩写的函数模板(8.3.5)。 [例如:
8.3.5
- 结束示例]
和7.1.6.4
:
在第15段之后添加以下段落。
- 醇>
缩写函数模板是一个函数声明,其参数类型列表包含一个或多个占位符(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
[...]