Skip to content

Commit c61ed18

Browse files
committed
Reviewed Chapter 7~13; Fixed code-in-book incompletely
1 parent 3adfbc2 commit c61ed18

File tree

50 files changed

+483
-744
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+483
-744
lines changed

.vscode/Test.cpp

Lines changed: 0 additions & 11 deletions
This file was deleted.

.vscode/Test.exe

-126 KB
Binary file not shown.

.vscode/settings.json

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,51 @@
6363
"iomanip": "cpp",
6464
"fstream": "cpp",
6565
"sstream": "cpp",
66-
"*.tcc": "cpp"
66+
"*.tcc": "cpp",
67+
"any": "cpp",
68+
"array": "cpp",
69+
"barrier": "cpp",
70+
"cfenv": "cpp",
71+
"chrono": "cpp",
72+
"cinttypes": "cpp",
73+
"codecvt": "cpp",
74+
"complex": "cpp",
75+
"condition_variable": "cpp",
76+
"coroutine": "cpp",
77+
"csetjmp": "cpp",
78+
"csignal": "cpp",
79+
"cstdarg": "cpp",
80+
"cuchar": "cpp",
81+
"cwctype": "cpp",
82+
"deque": "cpp",
83+
"forward_list": "cpp",
84+
"map": "cpp",
85+
"unordered_map": "cpp",
86+
"expected": "cpp",
87+
"functional": "cpp",
88+
"memory_resource": "cpp",
89+
"numeric": "cpp",
90+
"random": "cpp",
91+
"ratio": "cpp",
92+
"regex": "cpp",
93+
"source_location": "cpp",
94+
"string_view": "cpp",
95+
"future": "cpp",
96+
"latch": "cpp",
97+
"mutex": "cpp",
98+
"numbers": "cpp",
99+
"ranges": "cpp",
100+
"scoped_allocator": "cpp",
101+
"semaphore": "cpp",
102+
"shared_mutex": "cpp",
103+
"span": "cpp",
104+
"spanstream": "cpp",
105+
"stacktrace": "cpp",
106+
"stdfloat": "cpp",
107+
"stop_token": "cpp",
108+
"syncstream": "cpp",
109+
"thread": "cpp",
110+
"typeindex": "cpp",
111+
"variant": "cpp"
67112
}
68113
}

code_in_book/11.2-11.3/main.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
#include "Header.hpp"
1+
#include "is_same.hpp"
22
#include <iostream>
33
int main() {
44
int (*p1)[3] {}, *p2[3] {};
55
std::cout << user::is_same<int(*)[3], int*[3]>() << std::endl //输出0
66
<< user::is_same<int(&)[3]>(*p1) << std::endl //输出0
7-
<< user::is_same<int*>(*p1) << std::endl //输出1
8-
//提示:函数参数传递过程中发生了int[3]到int*的隐式类型转换
7+
<< user::is_same<int[3]>(*p1) << std::endl //输出1
98
<< user::is_same<>(p1, p2) << std::endl; //输出0
109
return 0;
1110
}

code_in_book/11.4-11.6/Definition.tpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -136,36 +136,55 @@ auto user::array<bool, N>::operator=(const array &arr) -> array& {
136136
return *this;
137137
}
138138
template<std::size_t N>
139-
constexpr bool& user::array<bool, N>::at(std::size_t pos) {
139+
constexpr auto user::array<bool, N>::at(std::size_t pos)
140+
-> reference {
140141
if (pos >= N)
141142
pos = N - 1;
142143
return _elem[pos];
143144
}
144145
template<std::size_t N>
145-
constexpr const bool& user::array<bool, N>::at(std::size_t pos)const {
146+
constexpr bool user::array<bool, N>::at(std::size_t pos)const {
146147
if (pos >= N)
147148
pos = N - 1;
148149
return _elem[pos];
149150
}
150151
template<std::size_t N>
151-
constexpr bool& user::array<bool, N>::operator[](std::size_t pos) {
152+
constexpr auto user::array<bool, N>::operator[](std::size_t pos)
153+
-> reference {
152154
return _elem[pos];
153155
}
154156
template<std::size_t N>
155-
constexpr const bool& user::array<bool, N>::operator[](std::size_t pos)const {
157+
constexpr bool user::array<bool, N>::operator[](std::size_t pos)const {
156158
return _elem[pos];
157159
}
158160
template<std::size_t N>
159161
void user::array<bool, N>::fill(bool val) {
160162
for (std::size_t i = 0; i < N; i++)
161163
_elem[i] = val;
162164
}
163-
//比较运算符和get函数均无需再重载
165+
template<std::size_t I, std::size_t N>
166+
typename std::bitset<N>::reference user::get(array<bool, N> &arr) {
167+
return arr._elem[I];
168+
}
169+
template<std::size_t I, std::size_t N>
170+
const bool user::get(const array<bool, N> &arr) {
171+
return arr._elem[I];
172+
}
173+
template<std::size_t N>
174+
constexpr bool user::operator<(
175+
const array<bool, N> &lhs, const array<bool, N> &rhs
176+
) {
177+
return lhs._elem.to_string() < rhs._elem.to_string();
178+
} //这里我们可以用std::bitset的to_string成员函数,转换成std::string再比较
179+
//其它比较运算符无需再重载
164180
template<std::size_t N, std::size_t M>
165181
void user::swap(array<bool, N> &lhs, array<bool, M> &rhs) {
166182
constexpr std::size_t minlen {std::min(N, M)};
167-
for (std::size_t i = 0; i < minlen; i++)
168-
std::swap(lhs._elem[i], rhs._elem[i]);
183+
for (std::size_t i = 0; i < minlen; i++){
184+
bool tmp {lhs._elem[i]};
185+
lhs._elem[i] = rhs._elem[i];
186+
rhs._elem[i] = tmp;
187+
}
169188
}
170189
template<std::size_t N> //类模板参数
171190
template<std::size_t M> //函数模板参数

code_in_book/11.4-11.6/Specification.tpp

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,42 @@ namespace user{
44
//array类模板特化部分
55
template<std::size_t N>
66
class array<bool, N>; //特化的声明
7-
template<std::size_t N, std::size_t M> //模板参数与另一个不同,所以它是一个重载
7+
template<std::size_t I, std::size_t N> //模板参数与另一个不同,所以它是一个重载
8+
typename std::bitset<N>::reference get(array<bool, N>&);
9+
template<std::size_t I, std::size_t N>
10+
const bool get(const array<bool, N>&);
11+
template<std::size_t N, std::size_t M> //它也是函数模板重载
812
void swap(array<bool, N>&, array<bool, M>&);
913
template<std::size_t N>
14+
constexpr bool operator<(
15+
const array<bool, N>&, const array<bool, N>&
16+
); //这个是专门为bool数组比较而设计的,因为std::bitset没有迭代器这个概念
17+
//模板定义部分
18+
template<std::size_t N>
1019
class array<bool, N> { //定义array<bool,N>部分特化
1120
std::bitset<N> _elem; //std::bitset可以更方便地解决我们的问题
1221
public:
22+
using reference = typename std::bitset<N>::reference;
23+
//类型别名,方便我们使用reference
1324
array(std::initializer_list<bool>); //构造函数
1425
array(const array&); //拷贝构造函数,这里的array是array<bool,N>
1526
array& operator=(const array&); //赋值运算符
16-
constexpr bool& at(std::size_t);
17-
constexpr const bool& at(std::size_t)const;
18-
constexpr bool& operator[](std::size_t);
19-
constexpr const bool& operator[](std::size_t)const;
20-
constexpr bool& front() { return _elem[0]; } //std::bitset支持下标运算符
21-
constexpr const bool& front()const { return _elem[0]; }
22-
constexpr bool& back() { return _elem[N - 1]; }
23-
constexpr const bool& back()const { return _elem[N - 1]; }
27+
constexpr reference at(std::size_t);
28+
constexpr bool at(std::size_t)const;
29+
constexpr reference operator[](std::size_t);
30+
constexpr bool operator[](std::size_t)const;
31+
constexpr reference front() { return _elem[0]; } //std::bitset支持下标
32+
constexpr bool front()const { return _elem[0]; }
33+
constexpr reference back() { return _elem[N - 1]; }
34+
constexpr bool back()const { return _elem[N - 1]; }
2435
constexpr bool empty()const { return !N; }
2536
constexpr std::size_t size()const { return N; }
26-
void fill(bool); //对于bool来说,传值比传常量引用更省内存空间
27-
template<std::size_t I, typename U, std::size_t M>
28-
friend U& get(array<U, M>&); //不建议把U改成bool,因为U不是T
29-
//声明模板友元,所有的get<U,M>函数实例都是类实例array<bool,N>的友元
30-
template<std::size_t I, typename U, std::size_t M>
31-
friend const U& get(const array<U, M>&);
37+
void fill(bool); //对于bool类型来说,传值比传常量引用更省内存空间
38+
template<std::size_t I, std::size_t M>
39+
friend typename std::bitset<M>::reference get(array<bool, M>&);
40+
//声明模板友元,所有的get<I,M>函数实例都是类实例array<bool,N>的友元
41+
template<std::size_t I, std::size_t M>
42+
friend const bool get(const array<bool, M>&);
3243
//同上
3344
template<std::size_t N1, std::size_t N2>
3445
friend void swap(array<bool, N1>&, array<bool, N2>&);
@@ -37,5 +48,9 @@ public:
3748
//声明友元类模板,任何一个array实例都是array<bool,N>的友元
3849
template<std::size_t M>
3950
void swap(array<bool, M>&);
40-
}; //其中有些友元不需要重新定义(因为特化也是原模板的一部分),但有些需要
51+
template<std::size_t M>
52+
friend constexpr bool operator<(
53+
const array<bool, M>&, const array<bool, M>&
54+
);
55+
};
4156
}; //end namespace user

code_in_book/11.4-11.6/array.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ template<typename T, std::size_t N>
2323
constexpr bool operator==(const array<T, N>&, const array<T, N>&);
2424
template<typename T, std::size_t N>
2525
constexpr bool operator!=(const array<T, N>&, const array<T, N>&);
26-
2726
//类模板定义部分
2827
template<typename T, std::size_t N>
2928
class array {
@@ -59,6 +58,9 @@ class array {
5958
template<std::size_t M>
6059
void swap(array<T, M>&);
6160
//作为array<T,N>的成员函数,它可与array<T,M>对象交换
61+
template<typename U, std::size_t M>
62+
friend constexpr bool operator<(const array<U,M>&, const array<U,M>&);
63+
//这里也用到了一些array的私有成员,所以它需要是友元
6264
};
6365
}; //end namespace user
6466
#include "Specification.tpp" //包含Specification.tpp文件的代码

code_in_book/11.8-11.9/Definition.tpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ std::ostream& user::operator<<(
1010
std::ostream &out,
1111
const user::unique_ptr<T> &ptr
1212
) {
13-
return out << ptr._ptr; //其实就是直接输出ptr内部的指针值,这也正是我们想要的
13+
return out << ptr._ptr;
14+
//其实就是直接输出ptr内部的指针值,这也正是我们想要的
1415
}
1516
//主模板成员函数定义部分
1617
template<typename T>

code_in_book/11.8-11.9/unique_ptr.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class unique_ptr { //分配动态单对象,使用unique_ptr<T>语法
1818
using pointer = T*; //通过using定义成员类型pointer,公有
1919
using element_type = T; //定义成员类型element_type
2020
private:
21-
pointer _ptr {nullptr}; //pointer类型的私有成员,成员类型pointer必须定义在前面
21+
pointer _ptr {nullptr}; //pointer类私有成员,成员类型pointer必须定义在前面
2222
static std::unordered_set<pointer> record;
2323
public:
2424
explicit unique_ptr(pointer = {nullptr}); //接收pointer类参数,或nullptr

generalized_parts/08_a_step_forward_in_classes_and_functions/02_member_functions_and_friend.tex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ \subsubsection*{加法运算符的重载}
162162
v._arr[i] = _arr[i] + n; //这两个_arr成员不是同一个东西
163163
return v; //返回值是v
164164
}
165-
\end{lstlisting}
165+
\end{lstlisting}\pagebreak
166166
读者可能关心以下几个问题,我将逐一说明:\par
167167
{\kaishu 为什么重载的加法运算符只接收了一个参数?不是说,成员函数接收的操作数个数不变吗?}\par
168168
我们在下一节中会讲到,任何一个成员函数都带有一个隐藏参数,即``调用此函数的对象''。以 \lstinline@size@ 成员函数为例,当我们调用它的时候,比如写成 \lstinline@_arr.size()@。这里看似不需要传递参数;但在汇编代码中我们就可以看出,实际上这个过程把 \lstinline@_arr@ 以指针(或引用)的形式传递过去了。\par
@@ -178,7 +178,7 @@ \subsubsection*{加法运算符的重载}
178178
v._size = std::min(_size, a._size);
179179
\end{lstlisting}
180180
它有三个 \lstinline@_size@ 成员出现。\lstinline@v._size@ 和 \lstinline@a._size@ 分别是 \lstinline@v@ 和 \lstinline@a@ 的成员,这个不会搞混吧。而 \lstinline@_size@ 正是``调用此运算符的对象''的成员。\par
181-
如果放在 \lstinline@arr1+arr2@ 的情境下,那么 \lstinline@_size@, \lstinline@a._size@ 和 \lstinline@v._size@ 分别对应 \lstinline@arr1._size@\footnote{这只是象怔性的写法,实际上 \lstinline@arr1._size@ 的写法相当于在 \lstinline@valarri@ 的类作用域外部访问该类的私有成员,这是禁止的。}, \lstinline@arr2._size@ 和 \lstinline@(arr1+arr2)._size@\footnote{初学者可能对 \lstinline@(arr1+arr2)._size@ 这种写法感到困惑,但是不要忘记,\lstinline@arr1+arr2@ 的返回值也是一个 \lstinline@valarri@ 类型的对象,所以它当然也有自己的成员咯。}。图8.1展示了它们之间的关系。\par
181+
如果放在 \lstinline@arr1+arr2@ 的情境下,那么 \lstinline@_size@, \lstinline@a._size@ 和 \lstinline@v._size@ 分别对应 \lstinline@arr1._size@\footnote{这只是象怔性的写法,实际上 \lstinline@arr1._size@ 的写法相当于在 \lstinline@valarri@ 的类作用域外部访问该类的私有成员,这是禁止的。}, \lstinline@arr2._size@ 和 \lstinline@(arr1+arr2)._size@\footnote{初学者可能对 \lstinline@(arr1+arr2)._size@ 这种写法感到困惑,但是不要忘记,\lstinline@arr1+arr2@ 的返回值也是一个\\\lstinline@valarri@ 类型的对象,所以它当然也有自己的成员咯。}。图8.1展示了它们之间的关系。\par
182182
\begin{figure}[htbp]
183183
\centering
184184
\includegraphics[width=\textwidth]{../images/generalized_parts/08_operator_overloading_as_member_function.drawio.png}
@@ -227,7 +227,7 @@ \subsubsection*{\texttt{this}指针与赋值运算符的重载}
227227
\begin{lstlisting}
228228
arr1 = arr1; //这是需要特殊考虑的!
229229
\end{lstlisting}
230-
如果进行了自我赋值,那就应该什么也不做直接返回 \lstinline@*this@,否则就是在浪费时间。
230+
如果进行了自我赋值,那就应该什么也不做直接返回 \lstinline@*this@,否则就是在浪费时间。\pagebreak
231231
\begin{lstlisting}
232232
valarri& valarri::operator=(const valarri &a) { //其中的a应作为常量引用
233233
if (&a == this) //检测a的地址是否与本对象一致

0 commit comments

Comments
 (0)