普通函数的参数 auto
从 C++14 开始,lambda 可以使用占位符(如 auto)来声明/定义它们的参数:
auto printCol1=[] (const auto& coll) { //generic lambda
for (const auto& elem:coll){ std::cout <<elem <<'\n'; }
}
它们允许我们传递任何类型的参数,只要lambda内部的操作是受支持的
std::vector coll{1,2,4,5};
...
printColl(coll);
// 编译矢量<int>的 lambda
printColl(std::string{"he11o"});
//编译 std::string 的 lambda
从c++ 20开始,你可以为所有函数(包括成员函数和操作符)使用占位符,比如auto。
void printColl(const auto& coll) //generic function {
or (const auto& elem : co11){
std::cout<<elem <<'\n'; }
}
此类声明只是声明/定义模板的快捷方式,如下所示:
void printColl(const T& coll)
//equivalent generic function {
for (const auto& elem: coll) { std::cout <<elem <<'\n'; }
}
唯一的区别是,通过使用auto,模板形参t就不再有名字了。因此,这个特性也被称为缩写的函数模板语法。
因为带有auto的函数是函数模板,所以所有使用函数模板的规则都适用。这尤其会导致不能在一个翻译单元(CPP文件)中实现具有自动参数的函数,而在另一个翻译单元中调用它。
带有auto参数的函数属于头文件,以便在多个CPP文件中可用(或者必须显式地实例化函数)
auto 成员函数的参数
您还可以使用此特性定义成员函数
class MyType {
...
void assign(const auto& newVal); };
该声明等价于(不同的是没有定义类型T):
class MyType {
template<typename T>
void assign(const T& newVal); };
但是,请注意,模板不能在函数内部声明。因此,有了这个特性,您就不能再在函数内部本地定义类或数据结构了
void foo() {
struct Data{
void mem(auto); //ERROR can't declare templates insides functions };
}
auto函数 与 Lambdas
具有自动形参的函数不同于lambda。例如,在不指定泛型参数的情况下,仍然不能传递带有auto作为参数的函数
bool lessByNameFunc(const auto& c1, const auto& c2) { //sorting criterion return c1.getName() < c2.getName(); //compare by name
} ...
std::sort(persons.begin(),persons.end(),
1essByNameFunc);
//ERROR:can't deduce type of parameters in sorting criterion
记住,lessByName()的声明相当于:
template<typename T1, typename T2>
bool lessByName(const T1& c1, const T1& c2) { //sorting criterion
return c1.getName()< c2.getName();
//compare by name }
因为函数模板不是直接调用的,所以编译器无法推断模板参数来编译调用。因此,必须显式地指定模板参数
std::sort(persons.begin(),persons.end(),
lessByName<Customer,Customer>); //OK
通过使用lambda,在传递lambda作为参数时不必指定模板参数的类型
lessByNameLambda = [] (const auto& c1, const auto& c2) { //sorting criterion
return c1.getName()< c2.getName();//compure by name };
std::sort(persons.begin(),persons.end(),
1essByNameLambda);
//OK
另一方面,函数模板参数很容易指定
void printFunc(const auto& arg) {
...
printFunc<std::string>("hel1o");
//剔除函数 templute 编译为 std::string
}
因为泛型lambda是一个带有泛型函数调用操作符operator()的函数对象,要显式指定模板形参,必须将其作为参数传递给operator():
auto printFunc = [] (const auto& arg) {
};
printFunc.operator()<std::string>("he11o");
//为std::string剔除lambda编译
auto详细参数
使用auto声明函数形参的规则与使用它声明lambda形参的规则相同
-
对于使用 auto 声明的每个参数,该函数都有一个隐式模板参数。
-
参数可以是参数包:
void foo(auto... args);这相当于以下内容(不引入类型)
template<typename...Types> void foo(Types... args);不允许使用 decltype(auto)。
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 N 天,点击查看活动详情”