C++ Xpress 5 C++17 new features that are easier to use (1) Features that make the code concise

        This part generally includes syntactic sugar (encapsulating optimized library functions or modules), and some functions and libraries that make the code more concise and more readable.

1. Structured Binding

        Before C++ 17, when using the for loop to traverse the map / unordered_map, you need to declare an intermediate variable (usually meaningless), and access the key and value through the intermediate variable and the first and second keywords.

        C++17 introduces structured binding , which binds members of an array, tuple, or struct to a set of variables*

// 1.构建一个描述人的结构体
struct Person {
  int age = 0;
  std::string name;
};

// 2. 获得一个结构体对象,姓名:”ABC“,年龄:99
Person getPerson() {
  return Person{99, "ABC"};
};

// 3. 结构化绑定
auto [age, name] = getStruct();
// C++ 17 以前遍历 map,声明无意义引用elem
for(const auto& elem : map){
  const auto& key = elem.first;
  const auto& value = elem.second;
  std::cout << elem.first << ": "  << elem.second << std::endl;
}

// C++ 17 
for(const auto& [key, value]: map){
  std::cout << key << ": " << val << std::endl;
}

        * : Strictly speaking, the result of structured binding is not a variable, that is, key and value are not variables, and the C++ standard calls them "aliases", so they cannot be captured by lambda expressions, but gcc does not follow the C++ standard, so The following code can be compiled under gcc, but clang cannot.

for(const auto& [key, value]: map){
    [&key, &value]{
        std::cout << key << ": " << value << std::endl;
    }();
}

        If you use Clang as the compilation front end, you can explicitly introduce a reference variable when capturing lambda expressions to pass compilation.

for(const auto& [key, value]: map){
    [&key = key, &value = value]{
        std::cout << key << ": " << value << std::endl;
    }();
}

        but! This restriction has been removed in C++20, so both gcc and Clang can capture structured binding objects in the C++20 standard.

2. Implicit derivation of std::tuple

Deduction Guide for std::tuple - cppreference.com

        Before C++ 17, when constructing std::pair / std::tuple, you must specify the data type or use std::make_pair/std::make_tuplea function. C++ 17 has std::pair/std::tupleadded deduction rules, and the specified type can no longer be displayed.

// C++ 17 以前
std::pair<int, std::string> p1{99, "ABC"s};
auto p1 = std::make_pair(99, "ABC"s);

// C++ 17 pair的具体类型隐式声明
std::pair p3{99, "ABC"s};

3. if constexpr

        The if constexpr statement is an if judgment statement in the compilation period. It can compile the corresponding paragraph according to the value of the template parameter in the compilation phase, so it can be used in "paradigm programming"; if the if judgment is placed in the runtime, it may cause performance loss. The conditional judgment during C++17 compilation needs to be realized through the SFINAE  mechanism or template overloading;

// C++ 17 使用变长参数模板 和 if constexpr 实现数字求和
template <int N, int... Ns>
auto sum()
{
    if constexpr (0 == sizeof...(Ns))
        return N;
    else
        return N + sum<Ns...>();
}

// 调用
sum<1, 2, 3>(); // returns 6

         Before if constexpr, the ordinary if - else is used for conditional judgment during execution, so it cannot be used in generic programming. In this example of summation, if - else cannot be used to determine the length of the current variable-length parameter, so it is necessary to write an additional function template to handle the case of a single template parameter.

// 一个模板参数时的函数模板?拗口
template<int N>
int sum()
{
    return N;
}

// 模板参数 > 2 个时调用此模板
template <int N1, int N2, int... Ns>
int sum()
{
    return N1 + sum<N2, Ns...>();
}

// 调用
sum<1, 2, 3>(); // returns 6

4. Support initialization in if / switch statement 

        C++ 17 supports adding an initialization statement before the conditional judgment in the if statement, and declares the variables used only in the if statement here to improve the readability of the code.

        can contain

if (初始化语句; 条件) 语句 else 语句
switch (初始化语句; 条件) 语句
std::map<int, std::string> m;
std::mutex mx;
extern bool shared_flag; // guarded by mx
 
int demo()
{
    if (auto it = m.find(10); it != m.end()) { return it->second.size(); }
    if (char buf[10]; std::fgets(buf, 10, stdin)) { m[0] += buf; }
    if (std::lock_guard lock(mx); shared_flag) { unsafe_ping(); shared_flag = false; }
    if (int s; int count = ReadBytesWithSignal(&s)) { publish(count); raise(s); }
    if (const auto keywords = {"if", "for", "while"};
        std::ranges::any_of(keywords, [&tok](const char* kw) { return tok == kw; }))
    {
        std::cerr << "Token must not be a keyword\n";
    }
}

Guess you like

Origin blog.csdn.net/xiao_ling_yun/article/details/127263272