我明白使用templates
是一种值得赞赏的重载方式,但我想知道为什么auto
不能用于函数参数类型推导,从而有助于函数的重载?
N3690
在7.6.1.4/3中说使用auto可以使lambda表达式成为通用的,提供此示例
auto glambda = [](int i, auto a) { return i; };//OK: a generic lambda
(注意:N3485中未提及)
1)。为什么我不能为正常的功能做类似的事情,例如
void swap(auto& param1, decltype(param1)& param2)
{
decltype(param1) temp = param1;
param1 = param2;
param2 = temp;
}
这会产生错误error : parameters declared auto
。
来自N3690 7.1.6.4/4
假设使用auto或decltype(auto)声明的变量的类型是从它推导出来的 初始化。在块(6.3),命名空间范围(3.3.6)和for-init-statement(6.5.3)中声明变量时,允许使用。[...] < / p>
param1
和param2
属于区块范围,因此有资格自动扣除,我错了吗?
2)。如果允许这样的功能会有什么陷阱?
我正在使用gcc 4.8.1。
谢谢
答案 0 :(得分:5)
n3690 7.1.6.4/2
7.1.6.4/3占位符类型可以在decl-specifier-seq,type-specifier-seq中带有函数声明符, convert-function-id或trailing-return-type,在这种声明符有效的任何上下文中。
7.1.6.4/4如果auto类型说明符显示为参数的decl-specifier-seq中的decl-specifiers之一 - lambda表达式的声明,lambda是一个通用的lambda。
7.1.6.4/5使用auto或decltype(auto)声明的变量的类型是从其初始化程序推导出来的。这种用途是 在块(6.3),命名空间范围(3.3.6)和for-init-statement(6.5.3)中声明变量时降低。 auto或decltype(auto)将作为decl-specifier-seq和decl-中的decl-specifiers之一出现 specifier-seq后面应跟一个或多个init-declarator,每个init-declarator都有一个非空的初始化 - IZER。
只有这样的用法才有用。禁止使用任何其他用法(特别是在
占位符类型也可用于在选择语句(6.4)或条件中声明变量 迭代语句(6.5),在new-expression-type的type-specifier-seq或new-expression(5.3.4)的type-id中,in 一个for-range-declaration,并声明一个静态数据成员,它出现了一个大括号或等于初始化程序 在类定义的成员规范(9.4.2)中。
parameter-declaration-clause
中使用)。
7.1.6.4/6
在本节未明确允许的上下文中使用auto或decltype(auto)的程序格式不正确。
答案 1 :(得分:2)
N3690是C ++ 14的委员会草案,即尚未发布的下一个C ++标准,在大多数编译器中可能还没有实现。如果实现了通用lambda,你应该参考编译器的文档 - 我猜它们不是。
但是,使用gcc,您很有可能在新标准正式发布之前实现C ++ 14功能,尽管您可能必须使用命令行标志显式启用C ++ 14支持。查看文档应该是-std=gnu++1y
根据this site,GCC尚未实施通用lambda。
<强>更新强>
至于使用auto
参数的普通泛型函数:这些参数不存在,下次不会出现。原因是模板化函数只是稍微更加冗长,更强大,因为您可以引用类型并直接将模板元函数应用于它们。在通用lambdas中,这只能通过使用decltype(a)
来完成,这有点繁琐,必须小心使用,因为它的行为与模板参数推导有点不同。
与自动参数相比,模板的额外奖励更具有类型安全性或表现力:
void func(auto a, auto b); //a and b might be different types
template <class T>
void func(T a, T b); //a and b must be the same type
答案 2 :(得分:1)
为什么我不能为例如
的正常功能做类似的事情
void swap(auto& param1, decltype(param1)& param2)
仅仅因为语言不允许这样做。在auto
(重新)在C ++ 11中发明之前,你想要的是通过模板实现的:
template <class T, class U>
void swap(T& param1, U& param2);
C ++ 11也是通过lambda表达式而C ++ 14可能会引入多态lambda,这些lambdas基本上是operator ()
为模板的lambdas。例如,对于多态lambda,考虑了类似于模板的语法(示例来自N3418)
[]<class T>(T* p) { /* ... */ }
最后,首选语法使用auto
而不是引入模板参数列表。
确实可以考虑将这个terser语法扩展到函数模板(正如OP建议的那样),但据我所知,委员会没有考虑过这种可能性。它可能会在将来发生,但有人必须正式提出它。这可能是一个“很好的功能”,但恕我直言,这只是语法糖,不会给语言带来太大的影响。
另外,我看不出这个terser语法(没有模板参数列表)如何用于模板类,也许模板函数的语法与模板类的语法不同也不值得。
答案 3 :(得分:0)
已经有办法写出你想要的东西: -
template <class T>
void swap(T& param1, T& param2)
{
T temp = param1;
param1 = param2;
param2 = temp;
}
那么为什么要创建一种新的语法,它不会让你做任何你以前无法做的事情。对lambdas的建议更改是允许你以前不能做的通用lambdas,我猜任何使用模板语法的语法都会在这里变得丑陋。