C++17新特性
语言特性
-
使用
auto
声明非类型模板参量 -
折叠表达式
提供模板参数包的折叠
template <typename... Args> bool logicalAnd(Args... args) { // 二元折叠 return (true && ... && args); } bool b = false; bool& b2 = b; logicalAnd(b, b2, true); // == false template <typename... Args> auto sum(Args... args) { // 一元折叠 return (... + args); } sum(5, 5.0, 7); // == 17
-
内联变量
-
constexpr lambda
使用
constexpr
完成编译时的lambda
表达式 -
列表初始化推导新规则
auto x = {1, 2, 3}; // deduct to std::initializer_list<int> before ,now deduct to int
-
嵌套命名空间
这个特性使命名空间嵌套更加简洁:
// before c++17 namespace A{ namespace B{ namespace C{ int i; } } } // c++17 namespace A::B::C{ int i; }
-
结构绑定
这个特性可以用于解结构初始化,使用方式为
auto [x,y,z] = expr;
当expr
为类元组对象时,其中的元素将对应绑定到x
,y
,z
。类元组对象包括std::pair
,std::turple
,std::array
等。// first example using Pair = std::pair<int, int>; Pair init(){ return Pair{0, 0}; } const auto [x, y] = init(); x; // x == 0 y; // y == 0 // second example using u_map = std::unordered_map<std::string, int>; u_name mapping{ {"a", 1}, {"b", 2}, {"c", 3} }; // destructure by reference for (const auto [key, value] : mapping){ cout << key << ":" << value << endl; }
-
选择语句初始化器
-
if initializer
// before c++17 std::mutex mtx; { std::lock_guard<std::mutex> lk(mtx); if (v.empty()) v.push(val); } // c++17 std::mutex mtx; { if (std::lock_guard<std::mutex> lk(mtx); v.empty()){ v.push(val); } }
-
switch initializer
// before c++17 A apple(args); switch(auto s = apple.stat()){ // body } // c++17 switch(A apple(args); auto s = apple.stat()){ // body }
-
-
constexpr if
用于编写依赖于编译时条件实例化的代码
-
UTF-8 字面字符
char c = u8'a';
-
枚举列表直接初始化
枚举现在能够使用列表进行初始化
enum byte: unsigned char{}; byte a = {0}; byte d = byte{256};
-
[[nodiscard]]
[[fallthrough]]
[[maybe_unused]]
属性 -
__has_include
宏操作符这个特性可以用来检查库是否可以被引入。
#ifdef __has_include #if __has_include(<iostream>) // 如果能够引入,返回true #include <iostream> #define have_iostream 1 #else #define have_iostream 0 #endif
-
类模板参数推导(
CTAD
)这个特性,使类模板的参数也能够进行推导
std::vector nums{1, 2, 3}; // deduct to std::vector<int> std::mutex mtx; auto lk = std::lock_guard{mtx}; // deduct to std::lock_guard<std::mutex> auto p = std::pair{0.2, 0.3}; // deduct to std::pair<int, int>
库特性
-
std::variants
相当于类型安全的
union
,同时只能存在一个值std::variant<int, int, double> v{1.20}; std::get<double>(v); // 1.20 std::get<2>(v); // 1.20
-
std::optional
std::optional<std::string> create(bool b) { if (b) { return "cts"; } else { return {}; } } create(false).value_or("mx"); // == "mx" create(true).value(); // == "cts"
-
std::any
类型安全的容器,存放任意类型的单值。
std::any x{1}; any_cast<int>(x); std::any_cast<int&>(x) = 10; // x==10 int s = any_cast<int>(x); // 这一步会将x存储的值转换为一个左值。
-
std::string_view
非所有权字符串引用
-
std::invoke
唤醒一个有参数的可调用对象
-
std::apply
唤醒一个有参数元组的可调用对象
-
std::filesystem
提供操作文件系统目录、文件和路径的标准方式。
-
std::byte
提供一个以字节表示数据的标准方式,与
char
和unsigned char
相比的优点是byte
对象非字符类型和算术类型,只能够使用位操作。std::byte x {0}; std::byte y {0xAA}; std::byte z = x & y; int i = std::to_integer<int>(z); // 0
-
map
和set
的分片 -
并行算法
增加了
find
,copy
,sort
的并行执行操作par
并行,seq
顺序,par_unseq
并行非顺序std::vector v; std::find(std::execution::par, v.begin(), v.end(), 2);
-
std::sample
sample
给定学列中的若干个元素,每个元素都有一个均等的被挑选的机会。 -
std::clamp
clamp
的作用是获取一个在由高值、低值范围限定的给定值。 -
std::reduce
与
std::accmulate
类似,在<numeric>
中。 -
prefix sum algorithms
inclusive_scan
和exclusive_scan
-
GCD (great common divisor)
和LCM (least common multiple)
最大公约数和最小公倍数,最小公倍数是基于最大公约数进行计算的
const int a = 9; const int b = 3; std::gcd(a, b); // 3 std::lcm(a, b); //
-
std::not_fn
返回给定函数结果的否定值
-
字符串转换
to/from
数字to_chars()
from_chars()