Colin’s Blog

A C++ Programmer

现代C++白皮书 笔记1

现代C++白皮书 笔记1

C++14

  • 0b11001010
  • 0b1100'1010'0010
  • 函数返回类型推导
1auto add(auto&x,auto&y)
2{
3    return x+y;
4}
  • constexpr中的局部变量
  • 移动捕获 [p = move(ptr)](){};
  • 按类型访问元组 x = get<int>(t);
  • 用户定义字面量 3ms, 55us, 10i, "hello"s
  • 变量模版
1template <typename T>
2T x = T(3.1);
3
4cout << x<int> << " " << x<double> << endl; // 3 3.1
  • 泛型lambda表达式
1auto get_size = [](auto& m){return m.size();};

在其他一些语言里面,有专门的特殊语法:

1C#      x => x*x
2JAVA    x -> x*x
3D       (x){return x*x;}

Bjarne认为不使用特殊记法是对的,但认为应该引入概念。

Concept 概念

概念——用于指定对于模版参数要求的编译期谓词 类型和值概念:Buffer<unsigned char, 128> 即值也可以作为概念的参数 (感觉BS就是让Alexander Stepanov和STL给带坏了才老想着整Concept)

Concept的问题:

 1template <typename T>
 2concept Tickable = requires(T t)
 3{
 4    t.tick();
 5};
 6
 7struct Foo
 8{
 9    void tick() { cout << "tick\n"; }
10    void tock() {}
11};
12
13void Bar(Tickable auto &t)
14{
15    t.tock();
16    t.tock1();
17    t.tick();
18}
19
20int main()
21{
22    Foo f{};
23    Bar(f);
24}

tickable即可表达 可以tick的概念 例如原子钟,手表,金表,都可以属于这个概念 但C++的CONCEPT的一个问题就是: 我们在Bar里面可以使用t.tock()这样的语句。 这个时候你传Foo进去是可以编译通过的。但是传别的Tickable的东西就不一定能通过。 而还有一种做法是你只能用明确写出的接口。例如Tickable里面只写了tick,那就只能用tick而不能用tock. 这种必须都写明白才能用的方式在 C++ 社区里称作 full template definition checking C++ 的 Concept 不可能做到这样,因为:

  1. 兼容性 你这么搞了,之前的代码怎么办?之前没有 concept 的代码都是无约束的,这么改直接全死。

  2. 编译性能

我的天,你想想,C++ ,每个函数里面每一个表达式都检查一通,啧啧啧…… 但是你不这么搞,那这个 Concept 的作用就没啥意思了——万一不小心用了什么没约束的操作错误信息不还是很难看。 要我说,这方面 Rust 做得太好了。我认为 Rust 的这个 Trait 真是把静态接口和所谓的“动态接口”完美地、无缝地结合到一块去了。真好。