为什么auto不能用于超载功能?

时间:2013-06-21 09:15:05

标签: c++ auto overloading c++14

我明白使用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>

假设param1param2属于区块范围,因此有资格自动扣除,我错了吗?

2)。如果允许这样的功能会有什么陷阱?

我正在使用gcc 4.8.1。

谢谢

4 个答案:

答案 0 :(得分:5)

n3690 7.1.6.4/2

占位符类型可以在decl-specifier-seq,type-specifier-seq中带有函数声明符, convert-function-id或trailing-return-type,在这种声明符有效的任何上下文中。

7.1.6.4/3

如果auto类型说明符显示为参数的decl-specifier-seq中的decl-specifiers之一 - lambda表达式的声明,lambda是一个通用的lambda。

7.1.6.4/4

使用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。

7.1.6.4/5

占位符类型也可用于在选择语句(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)

ForEveRanswer之上:

  
    

为什么我不能为例如

的正常功能做类似的事情   
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,我猜任何使用模板语法的语法都会在这里变得丑陋。