C++17 折叠表达式

一元折叠表达式 ( pack op ... ) : 一元右折叠 (E op ...) 展开后: (E1 op (... op (EN-1 op EN))) ( ... op pack ) :一元左折叠 (... op E) 展开后: (((E1 op E2) op ...) op EN) 二元折叠表达式 ( pack op ... op init ) :二元右折叠 (E op ... op I) 展开后: (E1 op (... op (EN−1 op (EN op I)))) ( init op ....

April 13, 2022 · 3 min · Rick Cui

C++17 变长参数模板

任意个数、任意类别的模板参数 template<typename... Ts> class Magic; // 计算参数的个数 template<typename... Ts> void magic(Ts... args) { std::cout << sizeof...(args) << std::endl; } 递归解包: C++17 之前 template<typename T0> void my_printf(T0 value) { std::cout << value << std::endl; } template<typename T, typename... Ts> void my_printf(T value, Ts... args) { std::cout << value << std::endl; my_printf(args...); } int main() { my_printf(1, 2.2, "abc", 'a'); return 0; } C++17 变参模板展开: template<typename T, typename....

April 13, 2022 · 1 min · Rick Cui

C++17 使用结构化绑定来解包绑定的返回值

注意:使用结构化绑定时,就不能再使用 std::tie 创建虚拟变量了,所以我们不得不绑定所有值到命名过的变量上。对部分成员进行绑定的做法是高效的,因为编译器可以很容易的对未绑定的变量进行优化 std::pair<int,int> divide_remainder(int dividend, int divisor){ int f = dividend / divisor; int s = dividend % divisor; return {f, s}; } int main() { auto [dividend, remainder] = divide_remainder(16, 3); std::cout << "16 / 3 is " << dividend << " with a remainder of " << remainder << '\n'; // 之前的写法 int remainder1; std::tie(std::ignore, remainder1) = divide_remainder(16, 5); std::cout << "16 % 5 is " << remainder1 << '\n'; return 0; }

April 12, 2022 · 1 min · Rick Cui

C++17 大括号初始化

( expression-list ):优先调用非聚合初始化,且会存在隐式转换 = expression: { initializer-list }:如果有聚合初始化(initializer_list<>),就调用聚合初始化,没有的话就调用符合条件的非聚合初始化 = { initializer-list }:同上 使用 auto 声明的变量括号初始化,只允许一个参数的情况 {} 与 () 调用构造函数初始化的方式,不同点在于 {} 没有类型的隐式转换,比如 int x(1.2); 和 int x = 1.2; 通过隐式的对浮点值进行向下取整,然后将其转换为整型,从而将 x 的值初始化为 1。相反的, int x{1.2}; 将会遇到编译错误,初始化列表中的初始值,需要与变量声明的类型完全匹配。 测试代码一: // #define AGGREGATE_INIT class Test{ public: Test(int a, float b, char* c){ cout << "int float char* initialize..." << endl; } Test(int a, int b, int c){ cout << "int int int initialize....

April 12, 2022 · 2 min · Rick Cui

C++17 constexpr-if 简化编译

它能处理不同模板类型的特化,因为它可以在完全不同的代码中,选取相应的片段,依据这些片段的类型对模板进行特化 比如我们有一个简单的类,它的成员函数 add ,支持对 U 类型值与 T 类型值的加法 template <typename T> class addable { T val; public: addable(T v) : val{v} {} template <typename U> T add(U x) const { return val + x; } }; 假设类型 T 是 std::vector<something> ,而类型 U 是 int。这里就有问题了,为整个 vector 添加整数是为 了什么呢?应该是对 vector 中的每个元素加上一个整型数。实现这个功能就需要在循环中进行 template <typename U> T add(U x) { auto copy (val); // Get a copy of the vector member for (auto &n : copy) { n += x; } return copy; } 把两种情况结合在一起:...

April 12, 2022 · 2 min · Rick Cui