C++20 has been released!

With the end of 2020, C++20 was finally released at the end of the year. The following is the new content (intercepted part, incomplete)

 

1, Constraints and concepts (constraints and concepts)

In class template and function template programming, it is mainly used to end and limit template parameters. Such constraints and restrictions occur during compilation, and compilation errors are no longer so obscure.
In template programming, you can restrict the type of template parameters or have certain characteristics, such as: can be restricted to integer, numeric, bool, or must support hash characteristics, or a derived type of a class, etc.

Concepts is a very important concept in C++20, and template programming has finally been qualitatively improved.

Concepts

Concepts is a named set of requirements . Concepts need to be declared in the namespace. The syntax is as follows:

template < template-parameter-list >concept concept-name = constraint-expression;

As follows:

template<typename T>
concept Hashable = requires(T a) 
{
    { std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
};//声明了一个名为Hashable的concept

struct meow {};

template<Hashable T>
void f(T); // 约束这个T必须满足Hashable concept,否则无法编译通过。

int main() 
{
  f("abc"s); // OK,string是可hash的
  f(meow{}); // Error: meow结构体不是可hash的,当然可以让其支持hash。
}

//
template<typename T>
concept C=sizeof(T)>10;

template<C T>
class test{};
template<C T>
void func(T t);

Constraints

Constraints are sequences of logical operations and operands, which are used to specify the requirements for the actual parameters of the template . It can appear in the requirements expression or directly as the subject of the concept.

There are three types of constraints:

  • Conjunction

  • Disjunction

  • Atomic constraint

As follows:

template<Incrementable T>
void f(T) requires Decrementable<T>;

template<Incrementable T>
void f(T) requires Decrementable<T>; // OK:重声明

Requires

requires is used to constrain template parameters or specific parameters.

requires clause

As follows:

template<typename T>
void f(T&&) requires Eq<T>; // 可作为函数声明符的最末元素出现

template<typename T> 
requires Addable<T> // 或在模板形参列表的右边
T add(T a, T b) 
{ 
    return a + b; 
}

The keyword requires  must be followed by a constant expression (so it can be written as requires true), but its intention is to use a named concept (as in the example above), or a conjunction/disjunction of named concepts, or a requirements expression .

The expression must have one of the following forms:

  • Elementary expressions, such as Swappable, std::is_integral::value, (std::is_object_v && …) or any parenthesized expression

  • A sequence of elementary expressions connected by the operator &&

  • A sequence of the preceding expressions connected with the operator ||

requires expression

The syntax is as follows:

requires { requirement-seq }    
requires ( parameter-list(optional) ) { requirement-seq }

parameter-list-a comma-separated list of formal parameters similar to those in the function declaration, but default actual parameters are not allowed and cannot end with an ellipsis (not expanded by the specified package) . These formal parameters have no storage period, connection or lifetime, and they are only used to assist in the formulation of various requirements. These formal parameters are in scope before the closing of the required sequence.
requirement-seq-the sequence of requirements, described below (each requirement ends with a semicolon).

Each requirement in requirement-seq must be one of the following four items:

  • Simple requirement

  • Type requirement

  • Compound requirement

  • Nested requirement

As follows:

template<typename T>
concept Addable = requires (T x) { x + x; }; // requires 表达式

template<typename T> requires Addable<T> // requires 子句,非 requires 表达式
T add(T a, T b) { return a + b; }

template<typename T>
    requires requires (T x) { x + x; } // 随即的约束,注意关键字被使用两次
T add(T a, T b) { return a + b; }

 

2. Modules (modules)

Used to logically divide the code, can speed up the compilation speed, and has nothing to do with the import order (remember the previous compilation errors caused by the #include order?)
There are three main keywords:

  • module: used to declare a module

  • export: used to export modules, functions or classes

  • import: used to import modules

As shown below:
A hello world module is defined and the hello function is exported

//helloworld.cpp
export module helloworld;  // module declaration
import <iostream>;         // import declaration 
export void hello() 
{      
    // export declaration
    std::cout << "Hello world!\n";
}
//main.cpp
import helloworld;

int main()
{
    hello();
}

 

3. Coroutines (coroutines)

A coroutine is a function that can suspend execution and then resume execution at a later point in time . The coroutine in C++ is stack less. Using coroutines can easily write asynchronous code (similar to writing synchronous code).

Three keywords are mainly involved:

(1) co_await
co_await suspends the execution of the current coroutine and continues execution after the waiting operation is completed.

task<> tcp_echo_server() 
{
    char data[1024];
    for (;;) 
    {
        std::size_t n = co_await socket.async_read_some(buffer(data)); #与 Python 中的 await 类似
        co_await async_write(socket, buffer(data, n));
    }
}

The above code, after the completion of async_read_some(), continue to execute the following statement and execute it in async_read_some()

(2) co_yield
co_yield suspends execution and returns a value. The difference from return is that although co_yield returns a value, the current function does not terminate.

generator<int> iota(int n = 0) 
{
    while(true)
    {
        co_yield n++;  //与 Python 中的 yield 类似
    }
}

(3)co_return

co_return is used to end the execution of the current coroutine and return a value

lazy<int> f()
{
  co_return 7;
}

Of course, the coroutine also has some limitations:

  1. Cannot use variable length arguments;

  2. Do not use ordinary return statements, or placeholder return types (auto or Concept);

  3. constexpr functions, constructors, destructors, and main functions cannot be coroutines.

 

4. Ranges (range)

Provides components and various adapters for processing range-based elements (which can be simply understood as containers), as well as some new algorithms.
There are mainly the following categories:

  • Range-based accessor

  • Range-based primitives

  • Scope-based concept

  • view

  • factory

  • adapter

See the header file for details:

A simple example:

#include <vector>
#include <ranges>
#include <iostream>
 
int main()
{
    std::vector<int> ints{0,1,2,3,4,5};
    auto even = [](int i){ return 0 == i % 2; };
    auto square = [](int i) { return i * i; };
 
    for (int i : ints | std::views::filter(even) | std::views::transform(square)) 
    {
        std::cout << i << ' ';
    }
}

 

5. Designated Initializers (designated initialization)

Use {} to initialize members of arrays, classes, structures or unions.

struct A{int a;int b;int c;};
A a{.a=10,.b=100,.c=20};

operator<=>

Three-way comparison operator, like:

lhs <=> rhs

Its behavior is as follows:

(a <=> b) < 0 if lhs < rhs
(a <=> b) > 0 if lhs > rhs
(a <=> b) == 0 if lhs equal rhs

Examples are as follows:

#include <compare>
#include <iostream>
int main() 
{
    double foo = -0.0;
    double bar = 0.0;
    auto res = foo <=> bar;
    if (res < 0)
        std::cout << "-0 is less than 0";
    else if (res == 0)
        std::cout << "-0 and 0 are equal";
    else if (res > 0)
        std::cout << "-0 is greater than 0";
}


6. Attributes

  1. [[nodiscard( string-literal )]]: Warn when ignoring the return value.

  2. [[likely]] and [[unlikely]]: Instruct the compiler to optimize situations or branches that are more likely to occur. It is a kind of prediction of the possibility of variable value.

int f(int i)
{
    if (i < 0) [[unlikely]] 
    {
        return 0;
    }
 
    return 1;
}

    3. [[no_unique_address]]: Used to optimize storage space, when the member is empty, it does not occupy storage space

 

7、Others

(1) constexpr adds support for virtual functions.

(2) char8_t is used to store utf-8 strings.

(3) constinit

Force constant initialization, not dynamic initialization

const char * g() { return "dynamic initialization"; }
constexpr const char * f(bool p) { return p ? "constant initializer" : g(); }
constinit const char * c = f(true); // OK
constinit const char * d = f(false); // error

(4) labmda

No longer supports default capture parameters
in the form of values ; allows display to capture this in the form of values;
supports templates and supports variable parameters;

template <typename... Args>
void foo(Args... args) 
{
  [...xs=args]{bar(xs...); // xs is an init-capture pack};
}

(5)std::format

Use {} to format the string, and no longer need to splice the disgusting stream. I have used the boost format before, which is also easy to use.

#include <iostream>
#include <format>
 
int main() 
{
    std::cout << std::format("Hello {}!\n", "world");
}

(6)std::span

A span is a view of the container (that is, it does not own), and provides boundary checking access to groups of consecutive elements. Because the view does not have its own elements, the cost of construction and copying is very low;

(7)std::jthread

The new thread class, similar to std::thread, but with more powerful functions, supports stop, automatic join, etc.

(8)Calendar 和 time zone

(9) Endian is used to determine the size of the enumeration

(10) std::make_shared supports arrays

(11) Atomic supports floating point numbers and smart ptr

(12)std::basic_syncbuf 和 std::basic_osyncstream

(13) String adds starts_with and end_with functions

(14) std::atomic_ref atomic reference

(15) std::to_array converts xxx to std::array

(16)inline namespace

 

The content is excerpted from Lian Shaohua's "C++ 20 that was once "dismissed" is officially released! ", this article is for reference and study only. Recently, some good articles have been deleted inexplicably. For the purpose of learning and sharing, I hope to keep a backup. If the original author needs the copyright, please contact to delete it, thank you!

 

 

Guess you like

Origin blog.csdn.net/qq_38915078/article/details/113109240