Skip to content

Commit ab6b4ea

Browse files
committed
Update public notes
1 parent 70f9e8a commit ab6b4ea

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

content/编程相关/编程语言/Cpp 之旅 第三版 读书笔记.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,61 @@ Num sum(Seq s, Num n);
877877
878878
就是用概念不同来重载。编译器会选择满足最严格参数需求的版本。
879879
880+
标准库 advance() 函数向前移动迭代器。
881+
882+
```cpp
883+
template<forward_iterator Iter>
884+
void advance(Iter p, int n) {
885+
while (n--) ++p;
886+
}
887+
888+
template<random_access_iterator Iter>
889+
void advance(Iter p, int n) {
890+
p += n;
891+
}
892+
```
893+
880894
跟其他的重载一样,这是编译时机制,没有任何运行时开销,如果编译器找不到最佳选择,就会报告二义性错误。基于概念的重载比一般的重载效率更高。
881895

882896
#### 有效代码
883897

898+
*这下知道为什么要起名了。*
899+
900+
不使用标准库的概念 `random_access_iterator` 而是手动实现的话,可以是这样:
901+
902+
```cpp
903+
template<forward_iterator Iter>
904+
requires requires(Iter p, int i) { p[i]; p+i; } // Iter 拥有下标操作以及整数操作
905+
void advance(Iter p, int n) {
906+
while (n--) ++p;
907+
}
908+
```
909+
910+
第一个 `requires` 开始一个 **requirements 子句**,第二个 `requires` 开始一个 **requires 表达式**。
911+
912+
第二个 requires 表达式是一个谓词,如果代码为有效代码则为 true,否则为 false。
913+
914+
> 我认为requires表达式可以被叫作泛型编程中的汇编代码。与常规汇编代码一样,requires子句非常灵活,并且不隐含任何编码规则。从某种程度上说,它是泛型编程中的底层代码,如同说汇编代码是普通编程的底层代码一样。因此,与汇编代码类似,requires子句不该出现在常规代码中。它们应当隐藏在抽象的具体实现中。如果你在你的代码中看到了requires requires子句,很可能这样的代码过于底层,最终可能产生潜在问题。
915+
916+
*没得喷,这个设计确实神。*
917+
918+
上面那段 `requires requires` 代码是刻意的、不优雅的黑客行为。
919+
920+
#### 定义概念
921+
922+
*终于要来了吗,我很好奇为什么要把定义概念放在应用概念后。甚至早在模板那章就提及概念使用而不是概念定义——让当时的我我一头雾水。*
923+
924+
直接用库的优秀概念比写新的要容易。不过写新的概念也很容易。
925+
926+
概念是一个编译时谓词,指示了一个或多个类型如何被使用。
927+
928+
```cpp
929+
template<typename T>
930+
concept Equality_comparable =
931+
requires (T a, T b) {
932+
{ a == b } -> Boolean; // 使用 == 比较 T 类型变量
933+
{ a != b } -> Boolean;
934+
}
935+
```
936+
937+
#todo

0 commit comments

Comments
 (0)