第24章:现代C++特性(C++17/20)核心概念
24.1 C++17核心特性基础概念
24.1.1 结构化绑定核心概念
结构化绑定的核心思想 :
结构化绑定就像快递拆包,一个大包裹(聚合类型)里面有多件商品,你可以一次性把它们都取出来并分别命名:
现实类比:
- 结构化绑定 = 快递拆包,一次性取出所有商品
- auto [x, y, z] = 分别命名,给每个商品贴标签
- 数组绑定 = 整箱商品,按顺序取出
- tuple绑定 = 组合商品,自动解包分配
cpp
// 结构化绑定的通用形式
auto [x, y, z] = expression;
绑定类型的推导规则:
cpp
template<typename T>
void analyze_structured_binding() {
T value{};
auto& [a, b, c] = value; // 引用绑定
auto [d, e, f] = value; // 拷贝绑定
const auto [g, h, i] = value; // const拷贝绑定
}
// 数组绑定
template<typename T, size_t N>
void bind_array(T (&arr)[N]) {
auto [first, second, ...rest] = arr; // C++23扩展
}
// 结构化绑定与std::tuple
template<typename... Args>
auto create_tuple(Args&&... args) {
auto tuple = std::make_tuple(std::forward<Args>(args)...);
auto [x, y, z] = tuple; // 自动解包
return std::make_tuple(x, y, z);
}
24.1.2 if constexpr编译期分支
编译期分支选择的核心概念 :
if constexpr就像编译期的智能分流器,在程序编译时就决定走哪条路径,避免了运行期的判断开销:
现实类比:
- if constexpr = 智能分流器,编译期就决定路径
- 普通if = 现场判断,运行时才选择路径
- 编译期选择 = 预制方案,提前准备好所有可能
- 运行期优化 = 避免不必要的代码生成
cpp
template<typename T>
constexpr auto type_based_operation(T&& value) {
if constexpr (std::is_integral_v<std::decay_t<T>>) {
return value * 2; // 整数运算
} else if constexpr (std::is_floating_point_v<std::decay_t<T>>) {
return value * 1.5; // 浮点运算
} else if constexpr (std::is_same_v<std::decay_t<T>, std::string>) {
return value + "_processed"; // 字符串运算
} else {
static_assert(always_false<T>::value, "Unsupported type");
return value;
}
}
// 辅助模板用于static_assert
template<typename>
struct always_false : std::false_type {};
// 编译期斐波那契数列计算
template<size_t N>
constexpr size_t fibonacci() {
if constexpr (N <= 1) {
return N;
} else {
return fibonacci<N-1>() + fibonacci<N-2>();
}
}
24.1.3 折叠表达式理论
折叠表达式的核心概念 :
折叠表达式就像流水线装配,把多个零件依次组装起来,最终得到一个完整的产品:
现实类比:
- 一元折叠 = 单向装配,从左到右或从右到左依次组装
- 二元折叠 = 双向装配,可以指定起始零件
- 逻辑折叠 = 质量检查,逐个检查直到发现问题
- 参数包 = 零件箱,包含所有待装配的零件
cpp
// 一元折叠
template<typename... Args>
constexpr auto sum_left(Args... args) {
return (... + args); // ((a + b) + c) + d
}
template<typename... Args>
constexpr auto sum_right(Args... args) {
return (args + ...); // a + (b + (c + d))
}
// 二元折叠
template<typename... Args>
constexpr auto custom_fold(Args... args) {
return (args + ... + 0); // 指定初始值
}
// 逻辑折叠
template<typename... Args>
constexpr bool all_true(Args... args) {
return (args && ...); // args1 && args2 && ... && argsN
}
template<typename... Args>
constexpr bool any_true(Args... args) {
return (args || ...); // args1 || args2 || ... || argsN
}
// 逗号折叠(执行副作用)
template<typename... Funcs>
void execute_all(Funcs... funcs) {
(funcs(), ...); // 按顺序执行所有函数
}
24.2 C++17高级类型系统
24.2.1 std::optional核心概念
可选类型的核心思想 :
std::optional就像可能中奖的彩票,要么有具体的奖金金额(有值),要么是"谢谢参与"(无值),避免了使用特殊值表示"无值"的尴尬:
现实类比:
- std::optional = 可能中奖的彩票
- 有值 = 中奖了,有具体金额
- 无值 = 谢谢参与,没有奖金
- value() = 兑奖,但可能发现没中奖(抛异常)
- value_or() = 保底兑奖,没中奖给默认值
cpp
template<typename T>
class Optional {
union {
T value;
char dummy;
};
bool has_value;
public:
Optional() : has_value(false) {}
Optional(T val) : has_value(true) {
new (&value) T(std::move(val));
}
~Optional() {
if (has_value) {
value.~T();
}
}
bool is_valid() const { return has_value; }
T& get() {
if (!has_value) throw std::runtime_error("No value");
return value;
}
// monadic操作
template<typename F>
auto and_then(F&& f) -> Optional<decltype(f(value))> {
if (has_value) {
return f(value);
}
return {};
}
template<typename F>
auto transform(F&& f) -> Optional<decltype(f(value))> {
if (has_value) {
return f(value);
}
return {};
}
T value_or(T&& default_value) const {
return has_value ? value : std::forward<T>(default_value);
}
};
24.2.2 std::variant核心概念
变体类型的核心思想 :
std::variant就像多功能工具箱,里面只能放一件工具,但可以是不同类型的工具(锤子、螺丝刀、扳手等),而且你能安全地知道当前是哪件工具:
现实类比:
- std::variant = 多功能工具箱,只能放一件工具
- 类型安全 = 工具识别,确保不会把锤子当螺丝刀用
- 当前索引 = 工具标签,知道当前是哪件工具
- 访问器 = 工具使用,安全地取出当前工具
- 异常安全 = 错误处理,用错工具时给出明确提示
cpp
template<typename... Types>
class Variant {
union {
char dummy;
Types... values; // 概念性表示
};
size_t current_index;
public:
template<size_t I>
using alternative_t = std::variant_alternative_t<I, std::variant<Types...>>;
// 访问操作
template<typename Visitor>
auto visit(Visitor&& vis) {
return std::visit(std::forward<Visitor>(vis), *this);
}
// 类型安全的获取
template<typename T>
T* get_if() {
return std::get_if<T>(this);
}
// 编译期索引获取
template<size_t I>
auto& get() {
return std::get<I>(*this);
}
};
// 使用示例
using Value = std::variant<int, double, std::string>;
class Calculator {
Value value;
public:
template<typename T>
void set_value(T val) {
value = std::move(val);
}
double get_numeric_value() const {
return std::visit([](auto&& v) -> double {
using T = std::decay_t<decltype(v)>;
if constexpr (std::is_arithmetic_v<T>) {
return static_cast<double>(v);
} else {
return 0.0;
}
}, value);
}
};
24.2.3 std::any核心概念
类型擦除的核心思想 :
std::any就像万能收纳盒,可以装任何类型的物品,但装进去后你会忘记具体是什么,需要特殊方法才能取出来:
现实类比:
- std::any = 万能收纳盒,什么都能装
- 类型擦除 = 标签移除,装进去后忘记类型
- 存储 = 收纳过程,把物品装进盒子
- 取出 = 识别过程,需要知道原来类型才能取出
- 类型安全 = 防错机制,防止把苹果当成橙子取出
cpp
class Any {
struct Base {
virtual ~Base() = default;
virtual std::unique_ptr<Base> clone() const = 0;
};
template<typename T>
struct Derived : Base {
T value;
explicit Derived(T val) : value(std::move(val)) {}
std::unique_ptr<Base> clone() const override {
return std::make_unique<Derived<T>>(value);
}
};
std::unique_ptr<Base> storage;
public:
Any() = default;
template<typename T>
Any(T value) : storage(std::make_unique<Derived<std::decay_t<T>>>(std::move(value))) {}
Any(const Any& other) : storage(other.storage ? other.storage->clone() : nullptr) {}
template<typename T>
T& cast() {
auto* derived = dynamic_cast<Derived<T>*>(storage.get());
if (!derived) {
throw std::bad_any_cast();
}
return derived->value;
}
template<typename T>
bool is() const {
return dynamic_cast<Derived<T>*>(storage.get()) != nullptr;
}
bool has_value() const {
return storage != nullptr;
}
void reset() {
storage.reset();
}
};
24.3 C++17并行算法理论
24.3.1 执行策略基础
并行执行的理论模型 :
C++17引入了执行策略,允许算法以不同方式执行:
cpp
// 执行策略类型
namespace std::execution {
inline constexpr sequenced_policy seq{}; // 顺序执行
inline constexpr parallel_policy par{}; // 并行执行
inline constexpr parallel_unsequenced_policy par_unseq{}; // 并行+向量化
}
// 并行算法的实现原理
template<typename ExecutionPolicy, typename ForwardIt, typename UnaryOp>
void parallel_for_each(ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, UnaryOp op) {
if constexpr (std::is_same_v<std::decay_t<ExecutionPolicy>, std::execution::sequenced_policy>) {
std::for_each(first, last, op);
} else {
// 并行实现
auto size = std::distance(first, last);
auto num_threads = std::thread::hardware_concurrency();
auto chunk_size = (size + num_threads - 1) / num_threads;
std::vector<std::thread> threads;
for (auto i = 0; i < num_threads; ++i) {
auto start = first + i * chunk_size;
auto end = (i == num_threads - 1) ? last : start + chunk_size;
if (start < end) {
threads.emplace_back([start, end, op]() {
std::for_each(start, end, op);
});
}
}
for (auto& thread : threads) {
thread.join();
}
}
}
24.3.2 并行归约算法
并行归约的数学原理:
cpp
template<typename ExecutionPolicy, typename ForwardIt, typename T, typename BinaryOp>
T parallel_reduce(ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, T init, BinaryOp op) {
auto size = std::distance(first, last);
if (size == 0) return init;
if (size == 1) return op(init, *first);
auto num_threads = std::thread::hardware_concurrency();
auto chunk_size = (size + num_threads - 1) / num_threads;
std::vector<T> partial_results(num_threads);
std::vector<std::thread> threads;
for (auto i = 0; i < num_threads; ++i) {
auto start = first + i * chunk_size;
auto end = (i == num_threads - 1) ? last : start + chunk_size;
threads.emplace_back([start, end, &partial_results, i, op]() {
T local_result{};
if (start < end) {
local_result = *start;
for (auto it = start + 1; it < end; ++it) {
local_result = op(local_result, *it);
}
}
partial_results[i] = local_result;
});
}
for (auto& thread : threads) {
thread.join();
}
T result = init;
for (const auto& partial : partial_results) {
result = op(result, partial);
}
return result;
}
24.4 C++20概念系统理论
24.4.1 概念的定义与使用
概念(Concepts)的核心思想 :
概念系统就像类型世界的"门禁卡",只有符合特定条件的类型才能进入特定的函数或类,就像只有员工卡才能进入办公区域:
现实类比:
- 概念(Concepts) = 门禁卡系统,控制类型访问权限
- Integral = 整数门禁,只有整数类型能通过
- requires = 门禁检查,验证类型是否符合条件
- 概念组合 = 多级门禁,需要同时满足多个条件
- 模板特化 = 特殊通道,为特定类型提供专门处理
cpp
// 基本概念的语法
template<typename T>
concept Integral = std::is_integral_v<T>;
template<typename T>
concept SignedIntegral = Integral<T> && std::is_signed_v<T>;
template<typename T>
concept UnsignedIntegral = Integral<T> && !SignedIntegral<T>;
// 复杂概念定义
template<typename T>
concept EqualityComparable = requires(T a, T b) {
{ a == b } -> std::convertible_to<bool>;
{ a != b } -> std::convertible_to<bool>;
};
template<typename T>
concept LessThanComparable = requires(T a, T b) {
{ a < b } -> std::convertible_to<bool>;
};
template<typename T>
concept TotallyOrdered = EqualityComparable<T> && LessThanComparable<T>;
// 概念的组合
template<typename T>
concept Numeric = std::is_arithmetic_v<T>;
template<typename T>
concept Container = requires(T t) {
typename T::value_type;
typename T::iterator;
{ t.begin() } -> std::same_as<typename T::iterator>;
{ t.end() } -> std::same_as<typename T::iterator>;
{ t.size() } -> std::convertible_to<std::size_t>;
};
24.4.2 约束与特化
约束表达式的理论:
cpp
// requires子句
template<typename T>
requires Integral<T>
T absolute_value(T value) {
return value < 0 ? -value : value;
}
// 约束的合取与析取
template<typename T>
requires Integral<T> && std::is_signed_v<T>
T signed_operation(T value) {
return -value;
}
template<typename T>
requires Integral<T> || std::is_floating_point_v<T>
auto numeric_operation(T value) {
return value * 2;
}
// 模板特化与概念
template<typename T>
class Processor {
// 通用实现
};
template<Integral T>
class Processor<T> {
// 整数特化
T process(T value) { return value << 1; }
};
template<std::floating_point T>
class Processor<T> {
// 浮点特化
T process(T value) { return value * 2.0; }
};
24.5 C++20协程核心概念
24.5.1 协程基础概念
协程的核心思想 :
协程就像可以暂停的DVD播放器,你可以随时暂停(co_yield)、继续播放(恢复执行),甚至快进到特定位置(co_await),而普通函数就像老式磁带,只能从头播放到尾:
现实类比:
- 协程 = 可暂停的DVD播放器,随时暂停继续
- 普通函数 = 老式磁带,只能一次性播放
- co_yield = 暂停按钮,暂时交出控制权
- co_await = 等待按钮,等待特定条件继续
- promise_type = 播放器控制面板,管理播放状态
cpp
// 协程的基本结构
struct Generator {
struct promise_type {
int current_value;
Generator get_return_object() {
return Generator{std::coroutine_handle<promise_type>::from_promise(*this)};
}
std::suspend_always initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
std::suspend_always yield_value(int value) {
current_value = value;
return {};
}
void return_void() {}
void unhandled_exception() { std::terminate(); }
};
std::coroutine_handle<promise_type> handle;
Generator(std::coroutine_handle<promise_type> h) : handle(h) {}
~Generator() {
if (handle) {
handle.destroy();
}
}
int next() {
handle.resume();
return handle.promise().current_value;
}
bool done() const {
return handle.done();
}
};
// 协程函数实现
Generator fibonacci() {
int a = 0, b = 1;
while (true) {
co_yield a;
auto temp = a;
a = b;
b = temp + b;
}
}
24.5.2 异步任务模型
异步协程的核心概念 :
异步协程就像餐厅的点餐系统,顾客(调用者)下单后不需要在厨房等待,服务员(协程)会在餐点准备好后主动通知顾客:
现实类比:
- 异步协程 = 餐厅点餐系统,下单后无需等待
- co_await = 等待通知,餐点准备好后自动通知
- promise_type = 服务员,负责协调厨房和顾客
- 异步任务 = 订单处理,后台准备餐点
- 结果获取 = 取餐,餐点准备好后领取
cpp
// 异步任务的promise类型
template<typename T>
struct AsyncTask {
struct promise_type {
T result;
std::exception_ptr exception;
AsyncTask get_return_object() {
return AsyncTask{std::coroutine_handle<promise_type>::from_promise(*this)};
}
std::suspend_never initial_suspend() { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
void return_value(T value) {
result = std::move(value);
}
void unhandled_exception() {
exception = std::current_exception();
}
};
std::coroutine_handle<promise_type> handle;
AsyncTask(std::coroutine_handle<promise_type> h) : handle(h) {}
~AsyncTask() {
if (handle) {
handle.destroy();
}
}
T get_result() {
if (handle.promise().exception) {
std::rethrow_exception(handle.promise().exception);
}
return std::move(handle.promise().result);
}
};
// 异步协程函数
template<typename T>
AsyncTask<T> async_operation(T value) {
// 模拟异步操作
co_return value * 2;
}
// 生成器协程
template<typename T>
struct AsyncGenerator {
struct promise_type {
std::optional<T> current_value;
AsyncGenerator get_return_object() {
return AsyncGenerator{std::coroutine_handle<promise_type>::from_promise(*this)};
}
std::suspend_always initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
std::suspend_always yield_value(T value) {
current_value = std::move(value);
return {};
}
void return_void() {}
void unhandled_exception() { std::terminate(); }
};
std::coroutine_handle<promise_type> handle;
AsyncGenerator(std::coroutine_handle<promise_type> h) : handle(h) {}
~AsyncGenerator() {
if (handle) {
handle.destroy();
}
}
std::optional<T> next() {
handle.resume();
return handle.promise().current_value;
}
};
24.6 C++20模块系统理论
24.6.1 模块的基本理论
模块系统的编译理论 :
模块系统提供了比传统头文件更好的封装和编译性能:
cpp
// 模块接口单元 (math.ixx)
export module math;
export template<typename T>
constexpr T add(T a, T b) {
return a + b;
}
export template<typename T>
constexpr T multiply(T a, T b) {
return a * b;
}
export class Calculator {
double result;
public:
Calculator() : result(0.0) {}
void add(double value) { result += value; }
void multiply(double value) { result *= value; }
double get_result() const { return result; }
void reset() { result = 0.0; }
};
// 模块实现单元 (math_impl.cpp)
module;
#include <algorithm>
#include <numeric>
module math;
export template<typename Container>
auto sum(const Container& container) {
return std::accumulate(container.begin(), container.end(),
typename Container::value_type{});
}
export template<typename Container>
auto product(const Container& container) {
return std::accumulate(container.begin(), container.end(),
typename Container::value_type{1},
std::multiides<>{});
}
24.6.2 模块分区与接口
模块分区理论:
cpp
// 主模块文件 (std_math.ixx)
export module std_math;
export import :core;
export import :advanced;
export import :constants;
// 核心分区 (std_math_core.ixx)
export module std_math:core;
export template<typename T>
constexpr T pi = T(3.14159265358979323846);
export template<typename T>
constexpr T e = T(2.71828182845904523536);
// 高级分区 (std_math_advanced.ixx)
export module std_math:advanced;
import :core;
export template<typename T>
constexpr T power(T base, int exponent) {
T result = T(1);
for (int i = 0; i < exponent; ++i) {
result *= base;
}
return result;
}
export template<typename T>
constexpr T factorial(int n) {
T result = T(1);
for (int i = 2; i <= n; ++i) {
result *= T(i);
}
return result;
}
24.7 C++20范围库理论
24.7.1 范围的基本概念
范围(Ranges)的数学理论 :
范围是对序列操作的抽象,提供了更现代的算法接口:
cpp
// 范围的基本概念
template<typename T>
concept Range = requires(T& t) {
std::ranges::begin(t);
std::ranges::end(t);
};
// 视图(View)的概念
template<typename T>
concept View = Range<T> && std::movable<T> && requires {
typename std::ranges::enable_borrowed_range<std::remove_cv_t<T>>;
};
// 自定义范围实现
template<typename T>
class CircularRange {
std::vector<T> data;
size_t start;
size_t count;
public:
CircularRange(std::vector<T> vec, size_t s, size_t c)
: data(std::move(vec)), start(s), count(c) {}
class Iterator {
const std::vector<T>* data;
size_t index;
size_t remaining;
public:
using iterator_category = std::forward_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = const T*;
using reference = const T&;
Iterator(const std::vector<T>* d, size_t idx, size_t rem)
: data(d), index(idx), remaining(rem) {}
reference operator*() const { return (*data)[index]; }
pointer operator->() const { return &(*data)[index]; }
Iterator& operator++() {
index = (index + 1) % data->size();
--remaining;
return *this;
}
Iterator operator++(int) {
Iterator tmp = *this;
++(*this);
return tmp;
}
bool operator==(const Iterator& other) const {
return remaining == other.remaining;
}
bool operator!=(const Iterator& other) const {
return !(*this == other);
}
};
Iterator begin() const {
return Iterator(&data, start, count);
}
Iterator end() const {
return Iterator(&data, (start + count) % data.size(), 0);
}
};
24.7.2 范围适配器
范围适配器的组合理论:
cpp
// 自定义范围适配器
template<typename Range>
class FilteredRange {
Range base;
std::function<bool(const std::ranges::range_value_t<Range>&)> predicate;
public:
FilteredRange(Range r, std::function<bool(const std::ranges::range_value_t<Range>&)> p)
: base(std::move(r)), predicate(std::move(p)) {}
class Iterator {
std::ranges::iterator_t<Range> current;
std::ranges::sentinel_t<Range> end;
std::function<bool(const std::ranges::range_value_t<Range>&)> predicate;
void skip_filtered() {
while (current != end && !predicate(*current)) {
++current;
}
}
public:
using iterator_category = std::input_iterator_tag;
using value_type = std::ranges::range_value_t<Range>;
using difference_type = std::ptrdiff_t;
using pointer = const value_type*;
using reference = const value_type&;
Iterator(std::ranges::iterator_t<Range> cur,
std::ranges::sentinel_t<Range> e,
std::function<bool(const value_type&)> pred)
: current(cur), end(e), predicate(std::move(pred)) {
skip_filtered();
}
reference operator*() const { return *current; }
pointer operator->() const { return &*current; }
Iterator& operator++() {
++current;
skip_filtered();
return *this;
}
bool operator==(const Iterator& other) const {
return current == other.current;
}
bool operator!=(const Iterator& other) const {
return !(*this == other);
}
};
Iterator begin() const {
return Iterator(std::ranges::begin(base), std::ranges::end(base), predicate);
}
Iterator end() const {
return Iterator(std::ranges::end(base), std::ranges::end(base), predicate);
}
};
// 范围适配器的组合使用
template<typename Range, typename Predicate>
auto filter(Range&& range, Predicate pred) {
return FilteredRange<std::views::all_t<Range>>{
std::forward<Range>(range), std::move(pred)
};
}
template<typename Range, typename Transform>
auto transform(Range&& range, Transform trans) {
return std::views::transform(std::forward<Range>(range), std::move(trans));
}
24.8 理论与实践练习
24.8.1 C++17特性实践
练习1:实现编译期字符串格式化器
cpp
template<size_t N>
struct CompileTimeString {
char data[N];
constexpr CompileTimeString(const char (&str)[N]) {
std::copy_n(str, N, data);
}
constexpr size_t size() const { return N - 1; }
constexpr char operator[](size_t i) const { return data[i]; }
};
template<typename... Args>
class CompileTimeFormatter {
std::string format_string;
std::tuple<Args...> args;
public:
CompileTimeFormatter(const std::string& fmt, Args... arguments)
: format_string(fmt), args(std::forward<Args>(arguments)...) {}
std::string format() const {
std::string result;
size_t arg_index = 0;
for (size_t i = 0; i < format_string.size(); ++i) {
if (format_string[i] == '{' && i + 1 < format_string.size() && format_string[i + 1] == '}') {
std::visit([&result](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_arithmetic_v<T>) {
result += std::to_string(arg);
} else if constexpr (std::is_same_v<T, std::string>) {
result += arg;
}
}, get_arg(arg_index++));
++i; // 跳过'}'
} else {
result += format_string[i];
}
}
return result;
}
private:
std::variant<Args...> get_arg(size_t index) const {
return std::apply([index](auto... args) -> std::variant<Args...> {
std::variant<Args...> result;
size_t current = 0;
((current++ == index ? (result = args, true) : false), ...);
return result;
}, args);
}
};
练习2:实现概念约束的运算库
cpp
// 数值概念
template<typename T>
concept Numeric = std::is_arithmetic_v<T>;
// 可加减概念
template<typename T>
concept Addable = requires(T a, T b) {
{ a + b } -> std::convertible_to<T>;
};
template<typename T>
concept Subtractable = requires(T a, T b) {
{ a - b } -> std::convertible_to<T>;
};
// 数学向量模板
template<typename T, size_t N>
requires Numeric<T> && Addable<T> && Subtractable<T>
class MathVector {
std::array<T, N> data;
public:
MathVector() = default;
template<typename... Args>
requires (sizeof...(Args) == N) && (std::convertible_to<Args, T> && ...)
MathVector(Args... args) : data{static_cast<T>(args)...} {}
MathVector operator+(const MathVector& other) const {
MathVector result;
for (size_t i = 0; i < N; ++i) {
result.data[i] = data[i] + other.data[i];
}
return result;
}
MathVector operator-(const MathVector& other) const {
MathVector result;
for (size_t i = 0; i < N; ++i) {
result.data[i] = data[i] - other.data[i];
}
return result;
}
T dot_product(const MathVector& other) const {
T result{};
for (size_t i = 0; i < N; ++i) {
result += data[i] * other.data[i];
}
return result;
}
double magnitude() const {
double sum = 0.0;
for (size_t i = 0; i < N; ++i) {
sum += static_cast<double>(data[i] * data[i]);
}
return std::sqrt(sum);
}
void normalize() {
double mag = magnitude();
if (mag > 0) {
for (size_t i = 0; i < N; ++i) {
data[i] = static_cast<T>(data[i] / mag);
}
}
}
};
// 特化常见向量类型
using Vec2f = MathVector<float, 2>;
using Vec3f = MathVector<float, 3>;
using Vec4f = MathVector<float, 4>;
using Vec2d = MathVector<double, 2>;
using Vec3d = MathVector<double, 3>;
24.8.2 C++20协程实践
练习3:实现异步任务调度器
cpp
#include <coroutine>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
// 异步任务类型
template<typename T = void>
class AsyncTask {
public:
struct promise_type {
std::optional<T> value;
std::exception_ptr exception;
AsyncTask get_return_object() {
return AsyncTask{std::coroutine_handle<promise_type>::from_promise(*this)};
}
std::suspend_never initial_suspend() { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
void return_value(T val) {
value = std::move(val);
}
void unhandled_exception() {
exception = std::current_exception();
}
};
using handle_type = std::coroutine_handle<promise_type>;
private:
handle_type coro;
public:
AsyncTask(handle_type h) : coro(h) {}
~AsyncTask() {
if (coro) {
coro.destroy();
}
}
T get_result() {
if (coro.promise().exception) {
std::rethrow_exception(coro.promise().exception);
}
return std::move(coro.promise().value.value());
}
bool done() const {
return coro.done();
}
};
// 任务调度器
class TaskScheduler {
std::queue<std::function<void()>> tasks;
std::mutex mutex;
std::condition_variable cv;
std::vector<std::thread> workers;
std::atomic<bool> stop{false};
void worker_thread() {
while (true) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(mutex);
cv.wait(lock, [this] { return stop || !tasks.empty(); });
if (stop && tasks.empty()) {
return;
}
task = std::move(tasks.front());
tasks.pop();
}
task();
}
}
public:
TaskScheduler(size_t num_threads = std::thread::hardware_concurrency()) {
for (size_t i = 0; i < num_threads; ++i) {
workers.emplace_back(&TaskScheduler::worker_thread, this);
}
}
~TaskScheduler() {
stop = true;
cv.notify_all();
for (auto& worker : workers) {
worker.join();
}
}
template<typename Func>
auto schedule(Func func) -> AsyncTask<decltype(func())> {
using return_type = decltype(func());
auto promise = std::make_shared<std::promise<return_type>>();
auto future = promise->get_future();
{
std::lock_guard<std::mutex> lock(mutex);
tasks.emplace([promise, func]() {
try {
if constexpr (std::is_void_v<return_type>) {
func();
promise->set_value();
} else {
promise->set_value(func());
}
} catch (...) {
promise->set_exception(std::current_exception());
}
});
}
cv.notify_one();
// 创建协程返回结果
co_return co_await std::move(future);
}
};
// 使用示例
AsyncTask<int> async_computation(TaskScheduler& scheduler, int value) {
auto result = co_await scheduler.schedule([value]() {
// 模拟耗时计算
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return value * value;
});
co_return result + 1;
}
24.9 进阶研究方向
24.9.1 C++20高级特性研究
- 约束与概念的形式化验证:概念系统的数学基础和形式化证明
- 协程的语义模型:协程状态机的形式化语义和正确性证明
- 模块系统的类型理论:模块系统的类型安全性和封装理论
- 范围库的代数结构:范围操作符的代数性质和组合理论
24.9.2 现代C++编译器优化
- 概念实例化的优化策略:概念约束的编译期优化技术
- 协程状态机的代码生成:协程的优化代码生成策略
- 模块接口的优化编译:模块边界的优化和代码生成
- 并行算法的运行时优化:执行策略的自适应优化算法
24.9.3 C++23/26前瞻研究
- 静态反射的形式化理论:反射机制的语义模型和类型理论
- 网络库的设计理论:异步I/O和网络编程的理论基础
- 执行器的统一模型:执行器接口的抽象理论和统一模型
- 契约编程的语义:契约断言的形式化语义和验证理论
24.10 小结
C++17/20代表了现代C++编程范式的重大飞跃,引入了结构化绑定、if constexpr、概念系统、协程、模块等革命性特性。本章系统阐述了:
- C++17编译期编程:if constexpr、折叠表达式、结构化绑定等编译期特性
- 现代类型系统:std::optional、std::variant、std::any等类型安全组件
- 并行算法框架:执行策略、并行归约、并发算法优化理论
- 概念系统理论:类型约束、概念定义、模板特化的形式化基础
- 协程编程模型:异步编程、生成器、状态机的理论模型
- 模块系统架构:接口封装、编译优化、依赖管理的理论基础
- 范围库设计:函数式编程、惰性求值、组合操作的代数理论
这些特性共同构建了现代C++的理论基础,为大型系统开发提供了更强的类型安全、编译期优化和并发编程能力。掌握这些理论知识对于编写高效、安全、可维护的现代C++系统至关重要。