15

我知道 usingtemplates是一种受欢迎的重载方式,但我想知道为什么auto不能用于函数参数类型推导从而帮助函数重载?

N3690在 7.6.1.4/3 中说 lambda 表达式可以使用 auto 进行泛型,提供这个例子

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) 中声明变量时,允许使用此用法。[...]

我是否错误地假设param1andparam2属于块范围并因此有资格自动扣除?

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

我正在使用 gcc 4.8.1。

谢谢

4

4 回答 4

5

n3690 7.1.6.4/2

占位符类型可以与 decl-specifier-seq、type-specifier-seq、conversion-function-id 或 trailing-return-type 中的函数声明符一起出现,在此类声明符有效的任何上下文中。

7.1.6.4/3

如果 auto 类型说明符作为 lambda 表达式的参数声明的 decl-specifier-seq 中的 decl-specifiers 之一出现,则 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-specifiers 之一出现在 decl-specifier-seq 中,并且 decl-specifier-seq 后面应跟随一个或多个 init-declarators,每个 init-declarators 应具有非空初始- 泽。

7.1.6.4/5

占位符类型也可用于在选择语句 (6.4) 或迭代语句 (6.5) 的条件中,在 new-type-id 或 type-id 中的 type-specifier-seq 中声明变量-expression (5.3.4),在 for-range-declaration 中,以及在声明带有大括号或等号初始化器的静态数据成员时,该初始化器出现在类定义的成员规范中 (9.4.2)。

只允许这种用法。禁止任何其他用途(特别是在 中的用途parameter-declaration-clause)。

7.1.6.4/6

在本节未明确允许的上下文中使用 auto 或 decltype(auto) 的程序是格式错误的。

于 2013-06-21T09:32:53.730 回答
2

N3690 是 C++14 的委员会草案,即尚未发布的下一个 C++ 标准,可能尚未在大多数编译器中实现。因此,如果实现了通用 lambda,您应该参考编译器的文档——我猜他们没有。

但是,使用 gcc,您很有可能在新标准正式发布之前实现 C++14 功能,尽管您可能必须使用命令行标志显式启用 C++14 支持。看文档应该是-std=gnu++1y

根据这个站点,通用 lambdas 尚未在 GCC 中实现。

更新: 至于使用auto参数的普通泛型函数:这些不存在,下次不会出现。原因是模板化函数的类型只是稍微冗长且功能更强大,因为您可以引用类型并直接将模板元函数应用于它们。在通用 lambda 中,这只能通过 using 来完成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
于 2013-06-21T09:42:45.180 回答
1

ForEveR回答之上:

为什么我不能为正常功能做类似的事情,例如

void swap(auto& param1, decltype(param1)& param2)

仅仅是因为语言不允许这样做。在autoC++11 中(重新)发明之前,您想要的可以通过模板实现:

template <class T, class U>
void swap(T& param1, U& param2);

C++11 也引入了 lambda 表达式,而 C++14 可能会引入多态 lambda,它们基本上operator ()是模板的 lambda。例如,多态 lambda 考虑了类似于模板的语法(示例取自N3418

[]<class T>(T* p) { /* ... */ }

最后,首选语法是使用auto而不是引入模板参数列表。

确实可以考虑将这种更简洁的语法扩展到函数模板(正如 OP 所建议的那样),但据我所知,委员会尚未考虑这种可能性。将来可能会这样做,但必须有人正式提出。这可能是一个“不错的功能”,但恕我直言,这只是语法糖,不会给语言带来太多。

此外,我看不出如何将这种简洁的语法(没有模板参数列表)用于模板类,并且可能不值得将模板函数的语法与模板类的语法分开。

于 2013-06-21T09:56:05.367 回答
0

已经有一种方法可以写出您想要的内容:-

template <class T>
void swap(T& param1, T& param2)
{
     T temp = param1;
     param1 = param2;
     param2 = temp;
}

那么为什么要创建一个新的语法,它不会让你做任何你以前不能做的事情。对 lambdas 的建议更改是允许您以前无法使用的通用 lambdas,我猜任何使用模板语法的语法在这里都会很丑陋。

于 2013-06-21T09:56:26.173 回答