Skip to content

Commit 80dc435

Browse files
feat: volumn 4, templated programmings (#123)
* feat: volumn 4, templated programmings * fix: ci
1 parent 9165373 commit 80dc435

27 files changed

Lines changed: 4368 additions & 37 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
---
2121

2222
<!-- COVERAGE_START -->
23-
![English Coverage](https://img.shields.io/badge/en_coverage-100%25-green.svg) 592/594 docs translated
23+
![English Coverage](https://img.shields.io/badge/en_coverage-100%25-green.svg) 602/604 docs translated
2424
<!-- COVERAGE_END -->
2525

2626
## 这是什么项目
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Comparable<Derived>:CRTP mixin,只实现 < 和 ==,自动补齐 > <= >= !=
2+
// 对应文章:documents/vol4-advanced/vol1-basics-cpp11-14/09-crtp.md
3+
// 编译:g++ -Wall -Wextra -std=c++20 comparable_mixin.cpp -o comparable && ./comparable
4+
#include <iostream>
5+
6+
template <typename Derived> struct Comparable {
7+
friend bool operator>(const Derived& a, const Derived& b) { return b < a; }
8+
friend bool operator<=(const Derived& a, const Derived& b) { return !(b < a); }
9+
friend bool operator>=(const Derived& a, const Derived& b) { return !(a < b); }
10+
friend bool operator!=(const Derived& a, const Derived& b) { return !(a == b); }
11+
};
12+
13+
struct Point : Comparable<Point> {
14+
int x, y;
15+
Point(int x_, int y_) : x(x_), y(y_) {}
16+
// 只实现 < 和 ==,其余四个由 Comparable<Point> 自动补齐
17+
friend bool operator<(const Point& a, const Point& b) { return a.x < b.x; }
18+
friend bool operator==(const Point& a, const Point& b) { return a.x == b.x; }
19+
};
20+
21+
int main() {
22+
Point p1{1, 2}, p2{3, 4};
23+
std::cout << std::boolalpha;
24+
std::cout << "p1 < p2: " << (p1 < p2) << "\n";
25+
std::cout << "p1 > p2: " << (p1 > p2) << "\n";
26+
std::cout << "p1 <= p2: " << (p1 <= p2) << "\n";
27+
std::cout << "p1 >= p2: " << (p1 >= p2) << "\n";
28+
std::cout << "p1 != p2: " << (p1 != p2) << "\n";
29+
return 0;
30+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// CRTP 静态多态:派生类把自己传给基类,编译期绑定,无 vtable 无运行时分派
2+
// 对应文章:documents/vol4-advanced/vol1-basics-cpp11-14/09-crtp.md
3+
// 编译运行:g++ -Wall -Wextra -std=c++20 crtp_static_polymorphism.cpp -o crtp && ./crtp
4+
// 看零开销汇编:g++ -O2 -std=c++20 -DCRTP_BENCH -S crtp_static_polymorphism.cpp -o crtp.s
5+
// use_crtp() 会被完全内联成 mov $0x2a,%eax; ret(对比虚函数版的 vtable 解引用)
6+
#include <iostream>
7+
8+
template <typename Derived> struct Shape {
9+
const char* name() { return static_cast<Derived*>(this)->name_impl(); }
10+
double area() { return static_cast<Derived*>(this)->area_impl(); }
11+
};
12+
13+
struct Circle : Shape<Circle> {
14+
double r;
15+
explicit Circle(double r_) : r(r_) {}
16+
const char* name_impl() { return "Circle"; }
17+
double area_impl() { return 3.14159 * r * r; }
18+
};
19+
20+
struct Square : Shape<Square> {
21+
double side;
22+
explicit Square(double s) : side(s) {}
23+
const char* name_impl() { return "Square"; }
24+
double area_impl() { return side * side; }
25+
};
26+
27+
#ifdef CRTP_BENCH
28+
// 汇编基准:use_crtp 在 -O2 下被完全内联,直接返回常量 42,零函数调用
29+
template <typename D> struct BenchBase {
30+
int compute() { return static_cast<D*>(this)->compute_impl(); }
31+
};
32+
struct BenchConcrete : BenchBase<BenchConcrete> {
33+
int compute_impl() { return 42; }
34+
};
35+
int use_crtp() {
36+
BenchConcrete c;
37+
return c.compute();
38+
}
39+
#endif
40+
41+
int main() {
42+
Circle c{2.0};
43+
Square s{3.0};
44+
std::cout << c.name() << " area = " << c.area() << "\n"; // Circle 走 Circle::area_impl
45+
std::cout << s.name() << " area = " << s.area() << "\n"; // Square 走 Square::area_impl
46+
return 0;
47+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// fixed_vector<T, N>:编译期定长、连续存储、零动态分配的 vector
2+
// 对应文章:documents/vol4-advanced/vol1-basics-cpp11-14/10-fixed-vector.md
3+
// 编译:g++ -Wall -Wextra -std=c++20 fixed_vector.cpp -o fixed_vector && ./fixed_vector
4+
#include <array>
5+
#include <cstddef>
6+
#include <iostream>
7+
#include <stdexcept>
8+
9+
template <typename T, std::size_t N> class FixedVector {
10+
std::array<T, N> data_{};
11+
std::size_t size_ = 0;
12+
13+
public:
14+
static constexpr std::size_t capacity_v = N;
15+
16+
constexpr void push_back(const T& value) {
17+
if (size_ >= N)
18+
throw std::out_of_range("FixedVector full");
19+
data_[size_++] = value;
20+
}
21+
constexpr T& operator[](std::size_t i) { return data_[i]; }
22+
constexpr const T& operator[](std::size_t i) const { return data_[i]; }
23+
constexpr std::size_t size() const { return size_; }
24+
25+
// 裸指针当迭代器:元素连续存储,T* 天生满足随机访问迭代器要求
26+
constexpr T* begin() { return data_.data(); }
27+
constexpr T* end() { return data_.data() + size_; }
28+
constexpr const T* begin() const { return data_.data(); }
29+
constexpr const T* end() const { return data_.data() + size_; }
30+
};
31+
32+
int main() {
33+
FixedVector<int, 8> v;
34+
for (int i = 1; i <= 5; ++i)
35+
v.push_back(i * 10);
36+
37+
std::cout << "size = " << v.size() << " capacity = " << decltype(v)::capacity_v << "\n";
38+
std::cout << "elements: ";
39+
for (auto x : v)
40+
std::cout << x << " ";
41+
std::cout << "\n";
42+
std::cout << "v[2] = " << v[2] << "\n";
43+
std::cout << "sizeof(FixedVector<int,8>) = " << sizeof(FixedVector<int, 8>) << "\n";
44+
std::cout << "sizeof(int*) = " << sizeof(int*) << " (动态 vector 至少含 3 个指针 + 堆分配)\n";
45+
return 0;
46+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// 手写 type traits:主模板 + 偏特化,看穿 <type_traits> 的实现原理
2+
// 对应文章:documents/vol4-advanced/vol1-basics-cpp11-14/04-specialization-partial.md
3+
// 编译:g++ -Wall -Wextra -std=c++20 type_traits_from_scratch.cpp -o type_traits && ./type_traits
4+
#include <iostream>
5+
6+
// is_pointer:主模板 false,指针偏特化 true
7+
template <typename T> struct is_pointer {
8+
static constexpr bool value = false;
9+
};
10+
template <typename T> struct is_pointer<T*> {
11+
static constexpr bool value = true;
12+
};
13+
14+
// is_const:主模板 false,const T 偏特化 true(注意 const T* 不算,得 T 本身是 const)
15+
template <typename T> struct is_const {
16+
static constexpr bool value = false;
17+
};
18+
template <typename T> struct is_const<const T> {
19+
static constexpr bool value = true;
20+
};
21+
22+
// is_reference:主模板 false,T& / T&& 偏特化 true
23+
template <typename T> struct is_reference {
24+
static constexpr bool value = false;
25+
};
26+
template <typename T> struct is_reference<T&> {
27+
static constexpr bool value = true;
28+
};
29+
template <typename T> struct is_reference<T&&> {
30+
static constexpr bool value = true;
31+
};
32+
33+
// C++14 变量模板简写(和标准库 _v 后缀同一思路)
34+
template <typename T> constexpr bool is_pointer_v = is_pointer<T>::value;
35+
36+
int main() {
37+
std::cout << std::boolalpha;
38+
std::cout << "is_pointer<int> = " << is_pointer<int>::value << "\n";
39+
std::cout << "is_pointer<int*> = " << is_pointer<int*>::value << "\n";
40+
std::cout << "is_pointer<int**> = " << is_pointer<int**>::value << "\n";
41+
std::cout << "is_const<const int> = " << is_const<const int>::value << "\n";
42+
std::cout << "is_const<int> = " << is_const<int>::value << "\n";
43+
std::cout << "is_const<const int*> = " << is_const<const int*>::value
44+
<< " (指针自身非 const,指向 const)\n";
45+
std::cout << "is_const<int* const> = " << is_const<int* const>::value << " (指针自身 const)\n";
46+
std::cout << "is_reference<int&> = " << is_reference<int&>::value << "\n";
47+
std::cout << "is_reference<int&&> = " << is_reference<int&&>::value << "\n";
48+
std::cout << "is_pointer_v<double> = " << is_pointer_v<double> << " (_v 简写)\n";
49+
return 0;
50+
}

0 commit comments

Comments
 (0)