C++17新特性

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 字面字符

```c++
char c = u8'a';
```

枚举列表直接初始化

枚举现在能够使用列表进行初始化

```c++
enum byte: unsigned char{};
byte a = {0};
byte d = byte{256};
```

[[nodiscard]] [[fallthrough]] [[maybe_unused]] 属性

__has_include宏操作符

这个特性可以用来检查库是否可以被引入。

```c++
#ifdef __has_include
#if __has_include(<iostream>) // 如果能够引入,返回true
#include <iostream>
#define have_iostream 1
#else
#define have_iostream 0
#endif
```

类模板参数推导(CTAD)

这个特性,使类模板的参数也能够进行推导

```c++
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

提供一个以字节表示数据的标准方式,与charunsigned 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`并行非顺序

```c++
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)

最大公约数和最小公倍数,最小公倍数是基于最大公约数进行计算的

```c++
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()`
posted @   LemHou  阅读(66)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示