C++ 的最新版本,C++14 于2014年8月通过了。C++14 带来了一些期待已久的变化,比如auto类型可以作为函数返回值类型,通用的lambda表达式——也是本篇文章的主题。
C++ 中的 lambda,在 C++11 标准中就有介绍。主要是为了书写更简洁,还有就是匿名函数用以代替函数对象,避免单独创建一个 class 和一个函数定义。这里有一个 C++11 lambda 用法的典型例子:返回一个数的平方。
int result = [](int input) {return input * input; }(10);
cout<< result << endl;
如果你想在多个地方复用这段代码,你可以将这个函数保存在一个变量里:
auto func = [](int input) { return input * input; };
// first use
std::cout << func(10) << std::endl;
// second use
std::cout << func(23) << std::endl;
你能看到上面代码中的问题吗?它只能用于计算一个integer数的平方。然而,我们想让这个 lambda 表达式应用于 double 类型或是用于一个 complex 数字。我们想要的是下面的这些:
// square of an int
std::cout << func(10) << std::endl;
// square of a double
std::cout << func(2.345) << std::endl;
// square of a complex number
std::cout << func(std::complex(3, -2)) << std::endl;
显然,我们可以用函数模板:
template
T func(T z) {
return z * z;
}
然而,定义一个有名的、全局的函数的方法不是我们本篇文章要讲的,C++14 标准介绍了通用化的 lambda 表达式,允许我们用 auto 来作为一个 lambda 表达式的参数类型。我们可以写一段更简洁、更优雅的代码:
auto func = [](auto input) { return input * input; };
下面是上面这个例子的完整的程序:
#include
#include
int main() {
// Store a generalized lambda, that squares a number, in a variable
auto func = [](auto input) { return input * input; };
// Usage examples:
// square of an int
std::cout << func(10) << std::endl;
// square of a double
std::cout << func(2.345) << std::endl;
// square of a complex number
std::cout << func(std::complex(3, -2)) << std::endl;
return 0;
}
上面的代码可以用现在的 C++ 编译器编译,比如:GCC 4.9.x 或 Clang。下面是用 Clang 、GCC 编译以及运行结果:
$ clang++ -std=c++1y -pedantic -Wall -stdlib=libc++ test_01.cpp -o test_01
$ ./test_01
100
5.49903
(5,-12)
$ g++-4.9.1 -std=c++14 -pedantic -Wall test_01.cpp -o test_01
$ ./test_01
100
5.49903
(5,-12)
$
std::sort(V.begin(), V.end(), [](auto i, auto j) { return (i > j); });
下面是一个完整的用 lambda 实现对有10个 integer 数字的 vector 进行降序排序的程序:
#include
#include
#include
#include
int main() {
std::vector V(10);
// Use std::iota to create a sequence of integers 0, 1, ...
std::iota(V.begin(), V.end(), 1);
// Print the unsorted data using std::for_each and a lambda
std::cout << "Original data" << std::endl;
std::for_each(V.begin(), V.end(), [](auto i) { std::cout << i << " "; });
std::cout << std::endl;
// Sort the data using std::sort and a lambda
std::sort(V.begin(), V.end(), [](auto i, auto j) { return (i > j); });
// Print the sorted data using std::for_each and a lambda
std::cout << "Sorted data" << std::endl;
std::for_each(V.begin(), V.end(), [](auto i) { std::cout << i << " "; });
std::cout << std::endl;
return 0;
}
下面是上面程序的运行结果:
$ g++-4.9.1 -std=c++14 -pedantic -Wall test_02.cpp -o test_02
$ ./test_02
Original data
1 2 3 4 5 6 7 8 9 10
Sorted data
10 9 8 7 6 5 4 3 2 1
$