重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
cpp-modern-features by thebushidocollective/han
npx skills add https://github.com/thebushidocollective/han --skill cpp-modern-features掌握从 C++11 到 C++23 的现代 C++ 特性,包括 lambda 表达式、移动语义、范围、概念和编译时求值。此技能使您能够编写高效、表达力强且可维护的现代 C++ 代码。
auto 关键字支持自动类型推断,减少冗长并提高可维护性:
// 传统方式
std::vector<int>::iterator it = vec.begin();
std::map<std::string, std::vector<int>>::const_iterator map_it = mymap.find("key");
// 现代 C++11
auto it = vec.begin();
auto map_it = mymap.find("key");
// 带初始化的 auto
auto value = 42; // int
auto pi = 3.14; // double
auto name = std::string("Alice"); // std::string
auto lambda = [](int x) { return x * 2; }; // lambda 类型
简化容器和数组的迭代:
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 传统循环
for (std::vector<int>::iterator it = numbers.begin(); it != numbers.end(); ++it) {
std::cout << *it << " ";
}
// 基于范围的 for 循环 (C++11)
for (int num : numbers) {
std::cout << num << " ";
}
// 使用引用修改元素
for (int& num : numbers) {
num *= 2;
}
// 使用常量引用以提高效率
for (const auto& str : string_vector) {
process(str);
}
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
具有捕获能力的匿名函数:
// 基本 lambda
auto add = [](int a, int b) { return a + b; };
int result = add(3, 4); // 7
// 带捕获的 lambda
int multiplier = 10;
auto multiply = [multiplier](int x) { return x * multiplier; };
// 通过引用捕获
int counter = 0;
auto increment = [&counter]() { counter++; };
// 通过值捕获所有
auto func1 = [=]() { return x + y + z; };
// 通过引用捕获所有
auto func2 = [&]() { x++; y++; };
// 混合捕获
auto func3 = [&sum, multiplier](int x) { sum += x * multiplier; };
// 可变 lambda (可以修改捕获的值)
auto mutable_func = [counter]() mutable { return counter++; };
使用 RAII 进行自动内存管理:
#include <memory>
// unique_ptr - 独占所有权
std::unique_ptr<int> ptr1 = std::make_unique<int>(42);
std::unique_ptr<MyClass> obj = std::make_unique<MyClass>(arg1, arg2);
// shared_ptr - 具有引用计数的共享所有权
std::shared_ptr<int> ptr2 = std::make_shared<int>(100);
std::shared_ptr<int> ptr3 = ptr2; // 引用计数 = 2
// weak_ptr - 非拥有引用
std::weak_ptr<int> weak = ptr2;
if (auto locked = weak.lock()) {
// 安全地使用锁定的指针
std::cout << *locked << std::endl;
}
// 自定义删除器
auto deleter = [](FILE* fp) { fclose(fp); };
std::unique_ptr<FILE, decltype(deleter)> file(fopen("data.txt", "r"), deleter);
类型安全的空指针常量:
// 旧方式 (歧义)
void func(int x);
void func(char* ptr);
func(NULL); // 调用哪个重载?取决于 NULL 的定义
// 现代方式 (明确)
func(nullptr); // 明确调用 func(char*)
// 智能指针初始化
std::unique_ptr<int> ptr = nullptr;
if (ptr != nullptr) {
// 使用 ptr
}
带有 auto 参数的 Lambda:
// 泛型 lambda (C++14)
auto generic_add = [](auto a, auto b) { return a + b; };
int sum1 = generic_add(3, 4); // 适用于 int
double sum2 = generic_add(3.14, 2.71); // 适用于 double
std::string concat = generic_add(std::string("Hello"), std::string(" World"));
// 多个 auto 参数
auto compare = [](auto a, auto b) { return a < b; };
// 在算法中使用
std::vector<int> vec = {5, 2, 8, 1, 9};
std::sort(vec.begin(), vec.end(), [](auto a, auto b) { return a > b; });
函数的自动返回类型:
// C++14: auto 返回类型推导
auto multiply(int a, int b) {
return a * b; // 返回类型推导为 int
}
auto get_vector() {
return std::vector<int>{1, 2, 3}; // 推导为 std::vector<int>
}
// 多个 return 语句必须具有相同类型
auto conditional(bool flag) {
if (flag)
return 42; // int
else
return 100; // int - 正确
// return 3.14; // 错误:类型不同
}
unique_ptr 的工厂函数:
// C++11 需要手动构造
std::unique_ptr<MyClass> ptr1(new MyClass(arg1, arg2));
// C++14 提供 std::make_unique
auto ptr2 = std::make_unique<MyClass>(arg1, arg2);
// 异常安全性优势
func(std::unique_ptr<int>(new int(1)), std::unique_ptr<int>(new int(2))); // 有风险
func(std::make_unique<int>(1), std::make_unique<int>(2)); // 安全
将对象分解为单独的变量:
// 对和元组
std::pair<int, std::string> get_data() {
return {42, "Answer"};
}
auto [id, name] = get_data();
std::cout << id << ": " << name << std::endl;
// 映射
std::map<std::string, int> scores = {{"Alice", 95}, {"Bob", 87}};
for (const auto& [name, score] : scores) {
std::cout << name << " scored " << score << std::endl;
}
// 数组
int arr[3] = {1, 2, 3};
auto [a, b, c] = arr;
// 结构体
struct Point { int x, y; };
Point p{10, 20};
auto [x, y] = p;
编译时条件语句:
template<typename T>
auto process(T value) {
if constexpr (std::is_integral_v<T>) {
return value * 2;
} else if constexpr (std::is_floating_point_v<T>) {
return value * 3.14;
} else {
return value;
}
}
int result1 = process(10); // 返回 20
double result2 = process(2.0); // 返回 6.28
可变参数模板操作:
// 对所有参数求和
template<typename... Args>
auto sum(Args... args) {
return (args + ...);
}
int total = sum(1, 2, 3, 4, 5); // 15
// 打印所有参数
template<typename... Args>
void print(Args... args) {
(std::cout << ... << args) << std::endl;
}
print("Value: ", 42, " ", 3.14); // Value: 42 3.14
// 逻辑运算
template<typename... Args>
bool all_true(Args... args) {
return (... && args);
}
bool result = all_true(true, true, false); // false
类型安全的可选值:
#include <optional>
std::optional<int> find_value(const std::vector<int>& vec, int target) {
auto it = std::find(vec.begin(), vec.end(), target);
if (it != vec.end()) {
return *it;
}
return std::nullopt;
}
// 用法
std::vector<int> numbers = {1, 2, 3, 4, 5};
if (auto result = find_value(numbers, 3)) {
std::cout << "Found: " << *result << std::endl;
} else {
std::cout << "Not found" << std::endl;
}
// 使用 value_or 提供默认值
int value = find_value(numbers, 10).value_or(-1);
类型安全的联合体:
#include <variant>
std::variant<int, double, std::string> data;
data = 42;
data = 3.14;
data = std::string("Hello");
// 访问模式
std::visit([](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int>) {
std::cout << "int: " << arg << std::endl;
} else if constexpr (std::is_same_v<T, double>) {
std::cout << "double: " << arg << std::endl;
} else {
std::cout << "string: " << arg << std::endl;
}
}, data);
// 获取值
if (auto* str = std::get_if<std::string>(&data)) {
std::cout << *str << std::endl;
}
约束模板参数:
#include <concepts>
// 定义一个概念
template<typename T>
concept Numeric = std::is_arithmetic_v<T>;
// 使用概念约束模板
template<Numeric T>
T add(T a, T b) {
return a + b;
}
// 带有 requires 子句的概念
template<typename T>
concept Hashable = requires(T a) {
{ std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
};
// 多个约束
template<typename T>
concept Sortable = std::copyable<T> && requires(T a, T b) {
{ a < b } -> std::convertible_to<bool>;
};
// 在函数中使用
template<Sortable T>
void sort_data(std::vector<T>& vec) {
std::sort(vec.begin(), vec.end());
}
可组合的算法和视图:
#include <ranges>
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 使用视图进行过滤和转换
auto result = numbers
| std::views::filter([](int n) { return n % 2 == 0; })
| std::views::transform([](int n) { return n * n; });
for (int n : result) {
std::cout << n << " "; // 4 16 36 64 100
}
// 取前 N 个元素
auto first_five = numbers | std::views::take(5);
// 反转视图
auto reversed = numbers | std::views::reverse;
// 链接多个操作
auto complex_view = numbers
| std::views::filter([](int n) { return n > 3; })
| std::views::transform([](int n) { return n * 2; })
| std::views::take(3);
协作式多任务:
#include <coroutine>
#include <iostream>
// 简单生成器
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::coroutine_handle<promise_type> handle;
Generator(std::coroutine_handle<promise_type> h) : handle(h) {}
~Generator() { if (handle) handle.destroy(); }
int value() { return handle.promise().current_value; }
bool next() {
handle.resume();
return !handle.done();
}
};
Generator counter(int start, int end) {
for (int i = start; i < end; ++i) {
co_yield i;
}
}
// 用法
auto gen = counter(0, 5);
while (gen.next()) {
std::cout << gen.value() << " ";
}
简化的比较运算符:
#include <compare>
struct Point {
int x, y;
// 单个运算符生成所有六个比较运算符
auto operator<=>(const Point& other) const = default;
};
Point p1{1, 2};
Point p2{1, 3};
bool eq = (p1 == p2); // false
bool lt = (p1 < p2); // true
bool gt = (p1 > p2); // false
// 自定义飞船操作符
struct Person {
std::string name;
int age;
auto operator<=>(const Person& other) const {
if (auto cmp = name <=> other.name; cmp != 0)
return cmp;
return age <=> other.age;
}
};
无需异常的错误处理:
#include <expected>
std::expected<int, std::string> divide(int a, int b) {
if (b == 0) {
return std::unexpected("Division by zero");
}
return a / b;
}
// 用法
auto result = divide(10, 2);
if (result) {
std::cout << "Result: " << *result << std::endl;
} else {
std::cout << "Error: " << result.error() << std::endl;
}
// 转换和错误处理
auto transformed = divide(20, 4)
.transform([](int x) { return x * 2; })
.or_else([](auto error) {
std::cout << "Error: " << error << std::endl;
return std::expected<int, std::string>(0);
});
// C++23: 带有模式匹配改进的 if 语句
std::map<int, std::string> map = {{1, "one"}, {2, "two"}};
if (auto [it, inserted] = map.insert({3, "three"}); inserted) {
std::cout << "Inserted: " << it->second << std::endl;
}
// 增强的静态 constexpr if
template<typename T>
void process(T value) {
if constexpr (requires { value.size(); }) {
std::cout << "Size: " << value.size() << std::endl;
}
}
class Buffer {
char* data;
size_t size;
public:
// 构造函数
Buffer(size_t s) : size(s), data(new char[s]) {}
// 拷贝构造函数
Buffer(const Buffer& other) : size(other.size), data(new char[size]) {
std::copy(other.data, other.data + size, data);
}
// 移动构造函数
Buffer(Buffer&& other) noexcept : size(other.size), data(other.data) {
other.data = nullptr;
other.size = 0;
}
// 拷贝赋值
Buffer& operator=(const Buffer& other) {
if (this != &other) {
delete[] data;
size = other.size;
data = new char[size];
std::copy(other.data, other.data + size, data);
}
return *this;
}
// 移动赋值
Buffer& operator=(Buffer&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
size = other.size;
other.data = nullptr;
other.size = 0;
}
return *this;
}
~Buffer() { delete[] data; }
};
#include <utility>
// 使用 std::move
std::vector<int> vec1 = {1, 2, 3, 4, 5};
std::vector<int> vec2 = std::move(vec1); // vec1 现在为空
// 完美转发
template<typename T>
void wrapper(T&& arg) {
// 转发 arg 并保留其值类别
process(std::forward<T>(arg));
}
// 带有完美转发的工厂函数
template<typename T, typename... Args>
std::unique_ptr<T> make_unique_custom(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
// Emplace 方法使用完美转发
std::vector<std::pair<int, std::string>> vec;
vec.emplace_back(1, "one"); // 原地构造
// C++14 及更高版本
auto fibonacci = [](int n) {
auto impl = [](int n, auto& self) -> int {
if (n <= 1) return n;
return self(n-1, self) + self(n-2, self);
};
return impl(n, impl);
};
// C++23: 推导 this
auto fibonacci_cpp23 = [](this auto self, int n) -> int {
if (n <= 1) return n;
return self(n-1) + self(n-2);
};
// 仅移动类型在捕获中
auto ptr = std::make_unique<int>(42);
auto lambda = [p = std::move(ptr)]() {
std::cout << *p << std::endl;
};
// 在捕获中初始化新变量
auto lambda2 = [value = computeExpensiveValue()]() {
return value * 2;
};
// 多个初始化捕获
auto lambda3 = [x = getValue(), y = getOtherValue()]() {
return x + y;
};
// C++11 constexpr (受限)
constexpr int factorial_cpp11(int n) {
return (n <= 1) ? 1 : n * factorial_cpp11(n - 1);
}
// C++14 constexpr (更强大)
constexpr int factorial(int n) {
int result = 1;
for (int i = 2; i <= n; ++i) {
result *= i;
}
return result;
}
constexpr int value = factorial(5); // 在编译时计算
// C++20 constexpr 与 std::vector
constexpr auto compute_primes(int max) {
std::vector<int> primes;
for (int i = 2; i < max; ++i) {
bool is_prime = true;
for (int p : primes) {
if (i % p == 0) {
is_prime = false;
break;
}
}
if (is_prime) primes.push_back(i);
}
return primes;
}
必须在编译时求值的函数:
consteval int square(int n) {
return n * n;
}
constexpr int value1 = square(5); // 正确:编译时
// int x = 5;
// int value2 = square(x); // 错误:必须是编译时
// Consteval 与 constexpr
constexpr int maybe_compile_time(int n) {
if (std::is_constant_evaluated()) {
return n * n;
} else {
return n + n;
}
}
auto 避免冗长的类型声明,特别是对于迭代器和 lambdastd::transform 和 std::for_eachunique_ptr 和 shared_ptr 而非原始指针std::optional 替代哨兵值,如 -1 或 nullptrauto& 可能创建对临时对象的悬垂引用std::move 实际上不会移动has_value() 就使用 * 或 value()std::get 在类型错误时抛出异常;使用 get_if 或访问者在以下情况下使用此技能:
每周安装数
49
仓库
GitHub 星标数
122
首次出现
2026年1月22日
安全审计
安装于
opencode44
codex44
gemini-cli42
cursor41
github-copilot40
amp37
Master modern C++ features from C++11 through C++23, including lambdas, move semantics, ranges, concepts, and compile-time evaluation. This skill enables you to write efficient, expressive, and maintainable modern C++ code.
The auto keyword enables automatic type inference, reducing verbosity and improving maintainability:
// Traditional
std::vector<int>::iterator it = vec.begin();
std::map<std::string, std::vector<int>>::const_iterator map_it = mymap.find("key");
// Modern C++11
auto it = vec.begin();
auto map_it = mymap.find("key");
// Auto with initialization
auto value = 42; // int
auto pi = 3.14; // double
auto name = std::string("Alice"); // std::string
auto lambda = [](int x) { return x * 2; }; // lambda type
Simplified iteration over containers and arrays:
std::vector<int> numbers = {1, 2, 3, 4, 5};
// Traditional loop
for (std::vector<int>::iterator it = numbers.begin(); it != numbers.end(); ++it) {
std::cout << *it << " ";
}
// Range-based for (C++11)
for (int num : numbers) {
std::cout << num << " ";
}
// With references to modify elements
for (int& num : numbers) {
num *= 2;
}
// With const references for efficiency
for (const auto& str : string_vector) {
process(str);
}
Anonymous functions with capture capabilities:
// Basic lambda
auto add = [](int a, int b) { return a + b; };
int result = add(3, 4); // 7
// Lambda with captures
int multiplier = 10;
auto multiply = [multiplier](int x) { return x * multiplier; };
// Capture by reference
int counter = 0;
auto increment = [&counter]() { counter++; };
// Capture all by value
auto func1 = [=]() { return x + y + z; };
// Capture all by reference
auto func2 = [&]() { x++; y++; };
// Mixed captures
auto func3 = [&sum, multiplier](int x) { sum += x * multiplier; };
// Mutable lambda (can modify captured values)
auto mutable_func = [counter]() mutable { return counter++; };
Automatic memory management with RAII:
#include <memory>
// unique_ptr - exclusive ownership
std::unique_ptr<int> ptr1 = std::make_unique<int>(42);
std::unique_ptr<MyClass> obj = std::make_unique<MyClass>(arg1, arg2);
// shared_ptr - shared ownership with reference counting
std::shared_ptr<int> ptr2 = std::make_shared<int>(100);
std::shared_ptr<int> ptr3 = ptr2; // Reference count = 2
// weak_ptr - non-owning reference
std::weak_ptr<int> weak = ptr2;
if (auto locked = weak.lock()) {
// Use locked pointer safely
std::cout << *locked << std::endl;
}
// Custom deleter
auto deleter = [](FILE* fp) { fclose(fp); };
std::unique_ptr<FILE, decltype(deleter)> file(fopen("data.txt", "r"), deleter);
Type-safe null pointer constant:
// Old way (ambiguous)
void func(int x);
void func(char* ptr);
func(NULL); // Which overload? Depends on NULL definition
// Modern way (unambiguous)
func(nullptr); // Clearly calls func(char*)
// Smart pointer initialization
std::unique_ptr<int> ptr = nullptr;
if (ptr != nullptr) {
// Use ptr
}
Lambdas with auto parameters:
// Generic lambda (C++14)
auto generic_add = [](auto a, auto b) { return a + b; };
int sum1 = generic_add(3, 4); // Works with int
double sum2 = generic_add(3.14, 2.71); // Works with double
std::string concat = generic_add(std::string("Hello"), std::string(" World"));
// Multiple auto parameters
auto compare = [](auto a, auto b) { return a < b; };
// Use in algorithms
std::vector<int> vec = {5, 2, 8, 1, 9};
std::sort(vec.begin(), vec.end(), [](auto a, auto b) { return a > b; });
Automatic return type for functions:
// C++14: auto return type deduction
auto multiply(int a, int b) {
return a * b; // Return type deduced as int
}
auto get_vector() {
return std::vector<int>{1, 2, 3}; // Deduced as std::vector<int>
}
// Multiple return statements must have same type
auto conditional(bool flag) {
if (flag)
return 42; // int
else
return 100; // int - OK
// return 3.14; // ERROR: different type
}
Factory function for unique_ptr:
// C++11 required manual construction
std::unique_ptr<MyClass> ptr1(new MyClass(arg1, arg2));
// C++14 provides std::make_unique
auto ptr2 = std::make_unique<MyClass>(arg1, arg2);
// Exception safety benefit
func(std::unique_ptr<int>(new int(1)), std::unique_ptr<int>(new int(2))); // Risky
func(std::make_unique<int>(1), std::make_unique<int>(2)); // Safe
Decompose objects into individual variables:
// Pairs and tuples
std::pair<int, std::string> get_data() {
return {42, "Answer"};
}
auto [id, name] = get_data();
std::cout << id << ": " << name << std::endl;
// Maps
std::map<std::string, int> scores = {{"Alice", 95}, {"Bob", 87}};
for (const auto& [name, score] : scores) {
std::cout << name << " scored " << score << std::endl;
}
// Arrays
int arr[3] = {1, 2, 3};
auto [a, b, c] = arr;
// Structs
struct Point { int x, y; };
Point p{10, 20};
auto [x, y] = p;
Compile-time conditional statements:
template<typename T>
auto process(T value) {
if constexpr (std::is_integral_v<T>) {
return value * 2;
} else if constexpr (std::is_floating_point_v<T>) {
return value * 3.14;
} else {
return value;
}
}
int result1 = process(10); // Returns 20
double result2 = process(2.0); // Returns 6.28
Variadic template operations:
// Sum all arguments
template<typename... Args>
auto sum(Args... args) {
return (args + ...);
}
int total = sum(1, 2, 3, 4, 5); // 15
// Print all arguments
template<typename... Args>
void print(Args... args) {
(std::cout << ... << args) << std::endl;
}
print("Value: ", 42, " ", 3.14); // Value: 42 3.14
// Logical operations
template<typename... Args>
bool all_true(Args... args) {
return (... && args);
}
bool result = all_true(true, true, false); // false
Type-safe optional values:
#include <optional>
std::optional<int> find_value(const std::vector<int>& vec, int target) {
auto it = std::find(vec.begin(), vec.end(), target);
if (it != vec.end()) {
return *it;
}
return std::nullopt;
}
// Usage
std::vector<int> numbers = {1, 2, 3, 4, 5};
if (auto result = find_value(numbers, 3)) {
std::cout << "Found: " << *result << std::endl;
} else {
std::cout << "Not found" << std::endl;
}
// Value_or for default
int value = find_value(numbers, 10).value_or(-1);
Type-safe union:
#include <variant>
std::variant<int, double, std::string> data;
data = 42;
data = 3.14;
data = std::string("Hello");
// Visit pattern
std::visit([](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int>) {
std::cout << "int: " << arg << std::endl;
} else if constexpr (std::is_same_v<T, double>) {
std::cout << "double: " << arg << std::endl;
} else {
std::cout << "string: " << arg << std::endl;
}
}, data);
// Get value
if (auto* str = std::get_if<std::string>(&data)) {
std::cout << *str << std::endl;
}
Constrain template parameters:
#include <concepts>
// Define a concept
template<typename T>
concept Numeric = std::is_arithmetic_v<T>;
// Use concept to constrain template
template<Numeric T>
T add(T a, T b) {
return a + b;
}
// Concept with requires clause
template<typename T>
concept Hashable = requires(T a) {
{ std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
};
// Multiple constraints
template<typename T>
concept Sortable = std::copyable<T> && requires(T a, T b) {
{ a < b } -> std::convertible_to<bool>;
};
// Use in function
template<Sortable T>
void sort_data(std::vector<T>& vec) {
std::sort(vec.begin(), vec.end());
}
Composable algorithms and views:
#include <ranges>
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// Filter and transform using views
auto result = numbers
| std::views::filter([](int n) { return n % 2 == 0; })
| std::views::transform([](int n) { return n * n; });
for (int n : result) {
std::cout << n << " "; // 4 16 36 64 100
}
// Take first N elements
auto first_five = numbers | std::views::take(5);
// Reverse view
auto reversed = numbers | std::views::reverse;
// Chaining multiple operations
auto complex_view = numbers
| std::views::filter([](int n) { return n > 3; })
| std::views::transform([](int n) { return n * 2; })
| std::views::take(3);
Cooperative multitasking:
#include <coroutine>
#include <iostream>
// Simple generator
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::coroutine_handle<promise_type> handle;
Generator(std::coroutine_handle<promise_type> h) : handle(h) {}
~Generator() { if (handle) handle.destroy(); }
int value() { return handle.promise().current_value; }
bool next() {
handle.resume();
return !handle.done();
}
};
Generator counter(int start, int end) {
for (int i = start; i < end; ++i) {
co_yield i;
}
}
// Usage
auto gen = counter(0, 5);
while (gen.next()) {
std::cout << gen.value() << " ";
}
Simplified comparison operators:
#include <compare>
struct Point {
int x, y;
// Single operator generates all six comparison operators
auto operator<=>(const Point& other) const = default;
};
Point p1{1, 2};
Point p2{1, 3};
bool eq = (p1 == p2); // false
bool lt = (p1 < p2); // true
bool gt = (p1 > p2); // false
// Custom spaceship operator
struct Person {
std::string name;
int age;
auto operator<=>(const Person& other) const {
if (auto cmp = name <=> other.name; cmp != 0)
return cmp;
return age <=> other.age;
}
};
Error handling without exceptions:
#include <expected>
std::expected<int, std::string> divide(int a, int b) {
if (b == 0) {
return std::unexpected("Division by zero");
}
return a / b;
}
// Usage
auto result = divide(10, 2);
if (result) {
std::cout << "Result: " << *result << std::endl;
} else {
std::cout << "Error: " << result.error() << std::endl;
}
// Transform and error handling
auto transformed = divide(20, 4)
.transform([](int x) { return x * 2; })
.or_else([](auto error) {
std::cout << "Error: " << error << std::endl;
return std::expected<int, std::string>(0);
});
// C++23: if with pattern matching improvements
std::map<int, std::string> map = {{1, "one"}, {2, "two"}};
if (auto [it, inserted] = map.insert({3, "three"}); inserted) {
std::cout << "Inserted: " << it->second << std::endl;
}
// Enhanced static constexpr if
template<typename T>
void process(T value) {
if constexpr (requires { value.size(); }) {
std::cout << "Size: " << value.size() << std::endl;
}
}
class Buffer {
char* data;
size_t size;
public:
// Constructor
Buffer(size_t s) : size(s), data(new char[s]) {}
// Copy constructor
Buffer(const Buffer& other) : size(other.size), data(new char[size]) {
std::copy(other.data, other.data + size, data);
}
// Move constructor
Buffer(Buffer&& other) noexcept : size(other.size), data(other.data) {
other.data = nullptr;
other.size = 0;
}
// Copy assignment
Buffer& operator=(const Buffer& other) {
if (this != &other) {
delete[] data;
size = other.size;
data = new char[size];
std::copy(other.data, other.data + size, data);
}
return *this;
}
// Move assignment
Buffer& operator=(Buffer&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
size = other.size;
other.data = nullptr;
other.size = 0;
}
return *this;
}
~Buffer() { delete[] data; }
};
#include <utility>
// Using std::move
std::vector<int> vec1 = {1, 2, 3, 4, 5};
std::vector<int> vec2 = std::move(vec1); // vec1 is now empty
// Perfect forwarding
template<typename T>
void wrapper(T&& arg) {
// Forward arg preserving its value category
process(std::forward<T>(arg));
}
// Factory function with perfect forwarding
template<typename T, typename... Args>
std::unique_ptr<T> make_unique_custom(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
// Emplace methods use perfect forwarding
std::vector<std::pair<int, std::string>> vec;
vec.emplace_back(1, "one"); // Constructs in-place
// C++14 and later
auto fibonacci = [](int n) {
auto impl = [](int n, auto& self) -> int {
if (n <= 1) return n;
return self(n-1, self) + self(n-2, self);
};
return impl(n, impl);
};
// C++23: Deducing this
auto fibonacci_cpp23 = [](this auto self, int n) -> int {
if (n <= 1) return n;
return self(n-1) + self(n-2);
};
// Move-only types in captures
auto ptr = std::make_unique<int>(42);
auto lambda = [p = std::move(ptr)]() {
std::cout << *p << std::endl;
};
// Initialize new variable in capture
auto lambda2 = [value = computeExpensiveValue()]() {
return value * 2;
};
// Multiple init captures
auto lambda3 = [x = getValue(), y = getOtherValue()]() {
return x + y;
};
// C++11 constexpr (limited)
constexpr int factorial_cpp11(int n) {
return (n <= 1) ? 1 : n * factorial_cpp11(n - 1);
}
// C++14 constexpr (more powerful)
constexpr int factorial(int n) {
int result = 1;
for (int i = 2; i <= n; ++i) {
result *= i;
}
return result;
}
constexpr int value = factorial(5); // Computed at compile time
// C++20 constexpr with std::vector
constexpr auto compute_primes(int max) {
std::vector<int> primes;
for (int i = 2; i < max; ++i) {
bool is_prime = true;
for (int p : primes) {
if (i % p == 0) {
is_prime = false;
break;
}
}
if (is_prime) primes.push_back(i);
}
return primes;
}
Functions that must be evaluated at compile time:
consteval int square(int n) {
return n * n;
}
constexpr int value1 = square(5); // OK: compile-time
// int x = 5;
// int value2 = square(x); // ERROR: must be compile-time
// Consteval with constexpr
constexpr int maybe_compile_time(int n) {
if (std::is_constant_evaluated()) {
return n * n;
} else {
return n + n;
}
}
auto to avoid verbose type declarations, especially with iterators and lambdasstd::transform and std::for_eachunique_ptr and shared_ptr over raw pointers for owned resourcesstd::optional instead of sentinel values like -1 or nullptrauto& can create dangling references to temporariesstd::move on const objects doesn't actually move* or value() without verifying has_value()std::get throws if wrong type; use or visitorUse this skill when:
Weekly Installs
49
Repository
GitHub Stars
122
First Seen
Jan 22, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode44
codex44
gemini-cli42
cursor41
github-copilot40
amp37
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
127,000 周安装
get_if