Bugs C ++ 20. Results of the meeting in Belfast

The other day there was a meeting of the Committee for Standardization of the C ++ programming language in Belfast. About 400 comments on C ++ 20 flew in from the country representatives to the committee, and half of them managed to deal with it.



Under the cut you are waiting for the results of discussions of Russian comments (yes, YOUR comments on C ++ 20), some comments from other countries, and of course the suitable new C ++ 23 (Executors!).



All those problems with C ++ that people mentioned on the site stdcpp.ru , in chat @ProCxx , at work at Yandex.Taxi, or in person at conferences, we designed in the form of comments on C ++ 20. And so what came of it ...



std :: atomic <int> a {}; and std :: atomic <int> b;



It may seem strange, but the variables a and b are not initialized to 0. To initialize the atomic variable to zero, it was necessary to write std :: atomic <int> with {0};



This behavior is completely unobvious, and many developers burned themselves. The committee accepted our remark on the standard, and in C ++ 20, the default constructors for std :: atomic_flag and std :: atomic will initialize the variables in clear state and T (), respectively.



std :: launder



Starting with C ++ 17, the standard has a scary function std :: launder. People from the committee thought that standard library developers and ordinary users would figure out how to deal with it.



In practice, it turned out that in some cases this function cannot be used. It is extremely unobvious that it is needed in principle:



struct C { const int c; }; std::vector<C> v = {C{1}}; v.pop_back(); v.push_back(C{2}); assert(v.back().c == 2); // ]:->
      
      





If you strictly follow the letter of the standard, then depending on the implementation of the standard library, the features of the compiler and the moon phase, assert may pass or fail.



When discussing the problem, it turned out that optimization, for the sake of which the standard described such strange behavior, was implemented only in one of the compilers and did not bring a tangible performance boost.



So starting from C ++ 20, you can safely store structures with links and constant fields in std :: optional, std :: variant, std :: vector, std :: deque, etc. Now placement new automatically applies part of the std logic: : launder.



* this in constructors



This is one of the comments where a failure awaited us:



 struct C { C(C&& other) noexcept : initial_(other.initial_) , secondary_(other.initial_) // O_O {} int initial_; int secondary_; };
      
      





According to current rules, in the line with O_O, the compiler has the right to assume that & other == this and, accordingly, one line above, we rewrote the value of other.initial_ and it needs to be re-read.



In other words, the compiler has the right to assume that a class that has not yet been created is aliased with the parameter from which the object is constructed, and because of this it can generate non-optimal code.



Some compilers (for example, GCC), believe that users do not write such a disgrace, and believe that aliasing is not possible.



The committee rejected our remark “Let's assume that aliasing is not possible”. As it turned out, some codebases have scary hacks where & other == this, and people are not yet ready to say goodbye to them.



operator <=> and embedded programming



For the spaceship operator to work, you need the <compare> header file. However, it was not in the list of header files that are available on any platforms (on the so-called freestanding implementations of the standard library that can be used on any iron).



Now it is on the list :)



Rest



According to our other comments, the verdict “Not in C ++ 20” was issued:

* We wanted __func__ to be used in constexpr.

* We wanted the concept to not use the incomplete type, because otherwise you get multiple ODR violations. But the remark had an unexpected positive effect: compilers now issue a warning if you use the incomplete type in requires.

* We wanted to correct the assignment operator for std :: string so that such a mess would not occur:



 basic_string::operator=(charT c): double d = 3.14; std::string s; s = d; // Compiles
      
      





The committee suggested writing a separate paper and correcting this after C ++ 20.

* We wanted to kill the assignment of temporary lines in std :: string_view:

 std::string foo(); std::string_view sv; sv = foo(); // Compiles... dangling reference
      
      





The outcome is the same as the previous remark: the committee suggested writing a separate paper and correcting this after C ++ 20.

* We requested that the following code compile:



 #include <type_traits> template <typename... Xs> auto f (Xs...) -> std::invoke_result_t<Xs...>;
      
      





We were told that everything is complicated, there is practically no chance to repair C ++ 20.



Comments from other countries



Of the significant changes: adding constructors for std :: span from types that satisfy the concept of ranges :: contiguous_range. So now span can be implicitly created from std :: vector and std :: string. We also added the constructor std :: string_view from two iterators that satisfy the concept of ranges :: contiguous_iterator.



Fun edits were expecting <compare>. Over the past three years, operator <=> has changed a lot. He is no longer involved in comparisons for equality, and, accordingly, a third of the contents of <compare> is no longer needed. Several countries have noticed this - they have reduced the standard.



A great change sneaked into non-type template parameters. In C ++ 20, it will be possible to pass almost any class (see P1907) with a constexpr destructor and public members as a template parameter, even if the class contains floating-point types or links.



We also added the missing const to different parts of the standard, changed the names and order of the arguments of some functions new to C ++ 20. There are also numerous edits for concepts and ranges, abbreviations of the standard text and other little things.



Numbers TS



ZaMaZaN4iK and I were able to stir up the committee with the C ++ Numerics Work In Progress document. Now there are Napoleonic plans for C ++ 23 to give users a set of new types of numbers (wide_integer, integer, rational), along with auxiliary low-level methods for working with overflows and convenient aliases.



I was told to prepare a presentation with an introduction to the ideas for the entire committee for the next meeting.



Executors



Executors is one of the priorities of C ++ 23. They are necessary for reactive programming, for asynchronous programming (network, disk, processes ...), they are the basis for coroutine sheduling and should provide a single interface for third-party libraries.



At the same time, executors should optimize the algorithms for their internal implementation. For example, for code:



 template <std::input_range Range> void MySort(Range& data) { namespace stdr = std::ranges; std::sort(GetGlobalExecutor(), stdr::begin(data), stdr::end(data), 42); }
      
      





the GetGlobalExecutor () function can return:

* single-threaded executor - it should execute the usual std :: sort on its thread;

* multithreaded executor - it should perform parallel sorting;

* GPU executor - it must move the data to the memory of the video card, sort it there and return the data back;

* NUMA executor - ...

* ...



So far, to implement such functionality, you need to do scary Customization Point Objects (CPO), turn each algorithm into them. The committee didn’t like it ...



But at least they pre-approved the P0443 - the basic interface. All subsequent sentences for executors will need to be written in the form of patches for P0443.



Instead of totals



Now we are separated from C ++ 20 by just one committee meeting. Left just a little bit…



Well, everyone who wants to chat with representatives of the committee live - look at the mitaps and C ++ conferences (*) :

* Corehard in Minsk

* C ++ Siberia 2020

* C ++ Russia 2020

* St. Petersburg C ++ User Group

* C ++ Meetup 2019 in Moscow



(*) Life hack: you do not have to pay for a conference ticket if you are a speaker.



All Articles