VC10中的C++0x特性 Part 1 (3) : Lambdas,auto,以及 static_assert
来源:vcblog 翻译:飘飘白云 kesalin@gmail.com
注意可选的 lambda 参数声明语法上包括:
( lambda-parameter-declaration-listopt ) mutableopt exception-specificationopt lambda-return-type-clauseopt
因此,如果你想使用 mutable 或 -> ReturnType,你需要在 lambda 导引符和它们之间插入空括号。
最后,因为 lambda 产生普通的函数对象,你可以在 tr1::function 中存储它们。
C:Temp>type tr1kitty.cpp
#include <algorithm>
#include <functional>
#include <iostream>
#include <ostream>
#include <vector>
using namespace std;
using namespace std::tr1;
void meow(const vector<int>& v, const function<void (int)>& f) {
for_each(v.begin(), v.end(), f);
cout << endl;
}
int main() {
vector<int> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
meow(v, [](int n) { cout << n << " "; });
meow(v, [](int n) { cout << n * n << " "; });
function<void (int)> g = [](int n) { cout << n * n * n << " "; };
meow(v, g);
}
C:Temp>cl /EHsc /nologo /W4 tr1kitty.cpp > NUL && tr1kitty
0 1 2 3 4 5 6 7 8 9
0 1 4 9 16 25 36 49 64 81
0 1 8 27 64 125 216 343 512 729
auto
关键词 auto 是从 C++ 98 得来的,它在 C++ 98 中实际上并没起什么作用,但在 C++ 0x 中被重用于自动类型推导(automatic type deduction)。 在一个声明中使用 auto ,意味着“让它和初始化它的事物具有相同的类型”。你看:
C:Temp>type autocat.cpp
#include <iostream>
#include <map>
#include <ostream>
#include <regex>
#include <string>
using namespace std;
using namespace std::tr1;
int main() {
map<string, string> m;
for (string s; getline(cin, s); ) {
smatch results;
if (regex_match(s, results, r)) {
m[results[1]] = results[2];
}
}
for (auto i = m.begin(); i != m.end(); ++i) {
cout << i->second << " are " << i->first << endl;
}
}
C:Temp>cl /EHsc /nologo /W4 autocat.cpp > NUL && autocat
cute kittens
ugly puppies
evil goblins
^Z
kittens are cute
goblins are evil
puppies are ugly
map<string, string>::iterator,你近10年的恐怖统治终于到头了。
(注意:m.begin()返回 iterator,而不是 cosnt_iterator,因为 map 不是 const 属性的。C++ 0x cbegin() 允许你从一个 non-cosnt 容器中获得一个 const_iterator。)
lambdas and auto
先前我提到过在 tr1::functions 中存储 lambda 函数。但是如非必要请别这么做,因为 tr1::function 会增加一些开销。如果你想重用 lambda 函数,或只想给它命名的话,你可以使用 auto。这儿有一个简洁的例子:
C:Temp>type autolambdakitty.cpp
#include <algorithm>
#include <iostream>
#include <ostream>
#include <vector>
using namespace std;
template <typename T, typename Predicate> void keep_if(vector<T>& v, Predicate pred) {
auto notpred = [&](const T& t) {
return !pred(t);
};
v.erase(remove_if(v.begin(), v.end(), notpred), v.end());
}
template <typename Container> void print(const Container& c) {
for_each(c.begin(), c.end(), [](const typename Container::value_type& e) { cout << e << " "; });
cout << endl;
}
int main() {
vector<int> a;
for (int i = 0; i < 100; ++i) {
a.push_back(i);
}
vector<int> b;
for (int i = 100; i < 200; ++i) {
b.push_back(i);
}
auto prime = [](const int n) -> bool {
if (n < 2) {
return false;
}
for (int i = 2; i <= n / i; ++i) {
if (n % i == 0) {
return false;
}
}
return true;
};
keep_if(a, prime);
keep_if(b, prime);
print(a);
print(b);
}
C:Temp>cl /EHsc /nologo /W4 autolambdakitty.cpp
autolambdakitty.cpp
C:Temp>autolambdakitty
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199
notpred 是一个否定 lambda 函数,注意我们不能使用 C++ 98 <functional>中的 not1() 函数,因为那要求你的谓词函数继承自 unary_function,而 lambda 函数并不满足这个条件。
static_assert
static_assert 让你能够在触发编译器错误时使用定制的错误信息:
C:Temp>type staticfluffykitten.cpp
template <int N> struct Kitten {
static_assert(N < 2, "Kitten<N> requires N < 2.");
};
int main() {
Kitten<1> peppermint;
Kitten<3> jazz;
}
C:Temp>cl /EHsc /nologo /W4 staticfluffykitten.cpp
staticfluffykitten.cpp
staticfluffykitten.cpp(2) : error C2338: Kitten<N> requires N < 2.
staticfluffykitten.cpp(8) : see reference to class template instantiation 'Kitten<N>' being compiled
with
[
N=3
]
如果你有任何疑问,我很乐意在评论中回答它们。
Stephan T. Lavavej
Visual C++ Libraries Developer
Published Tuesday, October 28, 2008 9:31 AM by vcblog
标签:C++0x,