Skip to content

Commit 69e4c62

Browse files
committed
see #1: concepts demo
1 parent 7a4a605 commit 69e4c62

File tree

5 files changed

+121
-18
lines changed

5 files changed

+121
-18
lines changed

book/zh-cn/10-cpp20.md

+39-17
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,19 @@ order: 10
66

77
# 第 10 章 展望:C++20 简介
88

9-
> 内容修订中
10-
119
[TOC]
1210

13-
本章对即将到来的 C++17 进行介绍,几个月前(2016 年),目前为止,还没有一个正式发布的编译器来编译 C++17 特性的代码,本节作为扩展主题,供对 C++ 的历史进程及其未来发展感兴趣的读者阅读
14-
15-
C++ 组委会在讨论投票最终确定 C++17 有很多提案,诸如 **Concepts**/**Ranges**/**Module** 等等,其中最受关注的就是 **Concepts**,可惜这一提案最终被拒,作为技术规范(Technical Specifications, TS) 将其发布
11+
C++20 如同 C++17 一样,似乎能够成为一个振奋人心的更新。例如,早在 C++11 时期就跃跃欲试呼声极高却最终落选的 `Concept`,如今已经箭在弦上
12+
C++ 组委会在讨论投票最终确定 C++20 有很多提案,诸如 **Concepts**/**Module**/**Coroutine**/**Ranges**/ 等等。
13+
本章我们就来一览 C++20 即将引入的那些重要特性
1614

17-
## Concepts TS
15+
## 概念与约束
1816

19-
**Concepts** 是对 C++ 模板编程的进一步增强扩展。简单来说,**Concepts** 是一种编译期的特性,它能够让编译器在编译期时对模板参数进行判断,从而大幅度增强我们在 C++ 中模板编程的体验。使用模板进行编程时候我们经常会遇到各种令人发指的错误,这是因为到目前为止我们始终不能够对模板参数进行检查与限制,例如下面简单的两行代码会造成大量的几乎不可读的编译错误:
17+
概念(Concepts)是对 C++ 模板编程的进一步增强扩展。简单来说,概念是一种编译期的特性,
18+
它能够让编译器在编译期时对模板参数进行判断,从而大幅度增强我们在 C++ 中模板编程的体验。
19+
使用模板进行编程时候我们经常会遇到各种令人发指的错误,
20+
这是因为到目前为止我们始终不能够对模板参数进行检查与限制。
21+
举例而言,下面简单的两行代码会造成大量的几乎不可读的编译错误:
2022

2123
```cpp
2224
#include <list>
@@ -28,11 +30,13 @@ int main() {
2830
}
2931
```
3032

31-
而这段代码出现错误的根本原因在于,`std::sort` 对排序容器必须提供随机迭代器,否则就不能使用,而我们知道 `std::list` 是不支持随机访问的。用 **Concepts** 的话来说就是:`std::list`中的迭代器不满足`std::sort`中随机迭代器这个 **Concepts**(概念) 的 **requirements**(要求)。有了 **Concepts**,我们就可以这样:
33+
而这段代码出现错误的根本原因在于,`std::sort` 对排序容器必须提供随机迭代器,否则就不能使用,而我们知道 `std::list` 是不支持随机访问的。
34+
用概念的语言来说就是:`std::list` 中的迭代器不满足 `std::sort` 中随机迭代器这个概念的约束(Constraint)。
35+
在引入概念后,我们就可以这样对模板参数进行约束:
3236

3337
```cpp
3438
template <typename T>
35-
requires Sortable<T> // Sortable 是一个 concept
39+
requires Sortable<T> // Sortable 是一个概念
3640
void sort(T& c);
3741
```
3842
@@ -49,23 +53,41 @@ void sort(T& c)
4953
void sort(Sortable& c); // c 是一个 Sortable 类型的对象
5054
```
5155
52-
遗憾的是,C++组委会没有将 **Concetps** 纳入新标准,而是将其作为TS正式发布(其实早在 C++11 最终定案之前就已经有 **Concepts** 的呼声了,但 Concepts TS 是2015年才完整正式发布),也就是我们现在看到的 Concepts TS。C++组委会拒绝将 Concepts 纳入新标准的原因其实很简单,并不是技术层面上的原因,纯粹是觉得它还不够成熟。
56+
我们现在来看一个实际的例子。
57+
58+
TODO
59+
60+
## 模块
61+
62+
TODO
63+
64+
## 合约
65+
66+
TODO
67+
68+
## 范围
69+
70+
TODO
71+
72+
## 协程
5373
54-
Concepts TS 的发布到最后一次 C++17 的讨论会只相隔了不到四个月的时间,**Concepts** 的(唯一)实现只存在于一个未发布的 gcc 版本中。而 gcc 中关于 **Concepts** 的实现就是由撰写 Concepts TS 的人开发的,虽然它能够进行相关测试,但还没有认真讨论过这份 TS 会产生哪些不良后果,更何况这份 TS 都没有被测试过。此外,已知的 **Concepts** 的一个明显的作用就是去辅助实现 Ranges TS 等提案,但实际上它们也没有被选入 C++17,所以可以把 **Concepts** 继续延后。
74+
TODO
5575
5676
## 总结
5777
58-
总的来说,类似于 Concepts/Ranges/Modules 这些令人兴奋的特性并没有入选至 C++17,这注定了 C++17 某种意义上来说相较于 C++11/14 依然只是小幅度更新,但我们有望在 C++2x 中看到这些东西的出现,这些内容对于一门已经三十多岁『高龄』的编程语言,依然是充满魅力的。
78+
总的来说,终于在 C++2a 中看到 Concepts/Ranges/Modules 这些令人兴奋的特性,
79+
这对于一门已经三十多岁『高龄』的编程语言,依然是充满魅力的。
5980
60-
[返回目录](./toc.md) | [上一章](./09-others.md) | [下一章 附录:进一步阅读的学习材料](./appendix1.md)
81+
[返回目录](./toc.md) | [上一章](./09-others.md) | [下一章 进一步阅读的学习材料](./appendix1.md)
6182
6283
6384
## 进一步阅读的参考资料
6485
65-
1. [Final features of C++17](https://meetingcpp.com/index.php/br/items/final-features-of-c17.html)
66-
2. [C++17: will it be great or just ok?](https://codeplay.com/public/uploaded/filehost/0cbdaf_c++17post-oulu2016.pdf)
67-
3. [Why Concepts didn't make C++17?](http://honermann.net/blog/2016/03/06/why-concepts-didnt-make-cxx17/)
68-
4. [C++11/14/17/20 编译器支持情况](http://en.cppreference.com/w/cpp/compiler_support)
86+
- [Final features of C++17](https://meetingcpp.com/index.php/br/items/final-features-of-c17.html)
87+
- [C++17: will it be great or just ok?](https://codeplay.com/public/uploaded/filehost/0cbdaf_c++17post-oulu2016.pdf)
88+
- [Why Concepts didn't make C++17?](http://honermann.net/blog/2016/03/06/why-concepts-didnt-make-cxx17/)
89+
- [C++11/14/17/20 编译器支持情况](http://en.cppreference.com/w/cpp/compiler_support)
90+
- [C++ 历史](https://en.cppreference.com/w/cpp/language/history)
6991
7092
## 许可
7193

book/zh-cn/appendix1.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ order: 11
1515
- [Ulrich Drepper. 每位程序员都需要知道的内存知识. 2007](https://people.freebsd.org/~lstewart/articles/cpumemory.pdf)
1616
- 待补充
1717

18-
[返回目录](./toc.md) | [上一章](./10-cpp20.md) | [下一章](./12-appendix2.md)
18+
[返回目录](./toc.md) | [上一章](./10-cpp20.md) | [下一章 现代 C++ 的最佳实践](./appendix2.md)
1919

2020
## 许可
2121

code/10/10.1.without.concepts.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include <list>
2+
#include <algorithm>
3+
4+
int main() {
5+
std::list<int> l = {1, 2, 3};
6+
// std::sort(l.begin(), l.end()); // tons of compile error
7+
return 0;
8+
}

code/10/10.2.concepts.cpp

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#include <iostream>
2+
#include <string>
3+
#include <vector>
4+
#include <list>
5+
6+
using namespace std;
7+
8+
template<typename T>
9+
concept bool Stringable = requires(T a){
10+
{a.to_string()} -> string;
11+
};
12+
13+
template<typename T>
14+
concept bool HasStringFunc = requires(T a){
15+
{ to_string(a) } -> string;
16+
};
17+
18+
struct Person {
19+
double height, weight;
20+
Person(double a, double b) : height(a), weight(b) {}
21+
string to_string(){
22+
return "weight: "+ std::to_string(weight) + ", height: "+ std::to_string(height);
23+
}
24+
};
25+
26+
27+
namespace std {
28+
29+
string to_string(list<int> l){
30+
string s = "";
31+
for(int a : l ){
32+
s+=(" " + to_string(a) + " ");
33+
}
34+
return s;
35+
}
36+
37+
}
38+
39+
string to_string(std::vector<int> v){
40+
string s = "";
41+
for(int a : v ){
42+
s += (" " + to_string(a) + " ");
43+
}
44+
return s;
45+
}
46+
47+
48+
void print(Stringable a){
49+
std::cout << a.to_string() << std::endl;
50+
}
51+
52+
void print(HasStringFunc a){
53+
std::cout << to_string(a) << std::endl;
54+
}
55+
56+
int main() {
57+
std::list<int> l {1, 2, 3};
58+
Person p(57, 170.0);
59+
std::vector<int> v { 34, 23, 34, 56, 78};
60+
61+
print(p); // uses concept Stringable
62+
print(l);
63+
print(3); // uses concept HasStringFunc
64+
// print(v); // error
65+
return 0;
66+
}

code/10/Makefile

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
all: $(patsubst %.cpp, %.out, $(wildcard *.cpp))
2+
3+
%.out: %.cpp Makefile
4+
clang++ $< -o $@ -std=c++2a -Xclang -fconcepts-ts -pedantic
5+
6+
clean:
7+
rm *.out

0 commit comments

Comments
 (0)