No outro dia, houve uma reunião do Comitê de Padronização da linguagem de programação C ++ em Belfast. Cerca de 400 comentários sobre C ++ 20 vieram dos representantes do país para o comitê, e metade deles conseguiu lidar com isso.
Abaixo do corte, você está aguardando os resultados das discussões dos comentários russos (sim, SEUS comentários sobre C ++ 20), alguns comentários de outros países e, claro, o novo C ++ 23 adequado (Executores!).
Todos os problemas com C ++ mencionados pelas pessoas no
stdcpp.ru , no chat
@ProCxx , no trabalho no Yandex.Taxi, ou pessoalmente nas conferências, escrevemos na forma de comentários no C ++ 20. E então o que aconteceu ...
std :: atômico <int> a {}; e std :: atomic <int> b;
Pode parecer estranho, mas as variáveis
aeb não
são inicializadas em 0. Para inicializar uma variável atômica em zero, foi necessário escrever std :: atomic <int> com {0};
Esse comportamento é completamente óbvio, e muitos desenvolvedores se queimaram. O comitê aceitou nossa observação sobre o padrão e, em C ++ 20, os construtores padrão para std :: atomic_flag e std :: atomic inicializarão as variáveis em
estado claro e T (), respectivamente.
std :: lavagem
Começando com o C ++ 17, o padrão tem uma função assustadora std :: lavagem. As pessoas do comitê pensaram que os desenvolvedores de bibliotecas padrão e os usuários comuns descobririam como lidar com isso.
Na prática, verificou-se que, em alguns casos, essa função não pode ser usada. É extremamente óbvio que é necessário em princípio:
struct C { const int c; }; std::vector<C> v = {C{1}}; v.pop_back(); v.push_back(C{2}); assert(v.back().c == 2);
Se você seguir rigorosamente a letra do padrão, dependendo da implementação da biblioteca padrão, os recursos do compilador e a fase da lua, a declaração poderá passar ou falhar.
Ao discutir o problema, descobriu-se que a otimização, para a qual o padrão descrevia um comportamento tão estranho, foi implementada apenas em um dos compiladores e não trouxe um aumento tangível no desempenho.
Portanto, a partir do C ++ 20, você pode armazenar com segurança estruturas com links e campos constantes em std :: optional, std :: variant, std :: vector, std :: deque, etc. Agora, o posicionamento new aplica automaticamente parte da lógica std: : lavagem.
* isso em construtores
Este é um dos comentários em que uma falha nos esperava:
struct C { C(C&& other) noexcept : initial_(other.initial_) , secondary_(other.initial_)
De acordo com as regras atuais, na linha com
O_O, o compilador tem o direito de assumir que & other == this e, consequentemente, uma linha acima, reescrevemos o valor de other.initial_ e ele precisa ser relido.
Em outras palavras, o compilador tem o direito de supor que uma classe que ainda não foi criada tenha um alias com o parâmetro a partir do qual o objeto é construído e, por isso, pode gerar código não ideal.
Alguns compiladores (por exemplo, GCC) acreditam que os usuários não escrevem essa desgraça e acreditam que o alias não é possível.
O comitê rejeitou nossa observação "Vamos supor que o aliasing não seja possível". Como se viu, algumas bases de código têm hacks assustadores onde & outros == isso, e as pessoas ainda não estão prontas para dizer adeus a elas.
operador <=> e programação incorporada
Para o operador da nave espacial funcionar, você precisa do arquivo de cabeçalho <comparar>. No entanto, ele não estava na lista de arquivos de cabeçalho disponíveis em nenhuma plataforma (nas chamadas
implementações independentes da biblioteca padrão que podem ser usadas em qualquer ferro).
Agora está na lista :)
O resto
De acordo com nossos outros comentários, o veredicto “Not in C ++ 20” foi emitido:
* Queríamos que __func__ fosse usado no constexpr.
* Queríamos que o conceito não usasse o tipo incompleto, porque, caso contrário, você recebe várias violações de ODR. Mas a observação teve um efeito positivo inesperado: os compiladores agora emitem um aviso se você usar o tipo incompleto requer.
* Queríamos corrigir o operador de atribuição para std :: string para que essa confusão não ocorresse:
basic_string::operator=(charT c): double d = 3.14; std::string s; s = d;
O comitê sugeriu a redação de um artigo separado e a correção após C ++ 20.
* Queríamos eliminar a atribuição de linhas temporárias em std :: string_view:
std::string foo(); std::string_view sv; sv = foo();
O resultado é o mesmo da observação anterior: o comitê sugeriu a redação de um artigo separado e a correção após C ++ 20.
* Solicitamos que o seguinte código seja compilado:
#include <type_traits> template <typename... Xs> auto f (Xs...) -> std::invoke_result_t<Xs...>;
Fomos informados de que tudo é complicado, praticamente não há chance de reparar o C ++ 20.
Comentários de outros países
De mudanças significativas: adicionar construtores para std :: span a partir de tipos que satisfazem o conceito de range :: contiguous_range. Portanto, agora o span pode ser criado implicitamente a partir de std :: vector e std :: string. Também adicionamos o construtor std :: string_view de dois iteradores que atendem ao conceito de range :: contiguous_iterator.
As edições divertidas esperavam <comparar>. Nos últimos três anos, o operador <=> mudou muito. Ele não está mais envolvido em comparações de igualdade e, portanto, um terço do conteúdo de <comparar> não é mais necessário. Vários países notaram isso - eles reduziram o padrão.
Uma grande mudança ocorreu nos parâmetros do modelo que não são do tipo. No C ++ 20, será possível passar
quase todas as classes (consulte P1907) com um destruidor constexpr e membros públicos como um parâmetro de modelo, mesmo que a classe contenha tipos ou links de ponto flutuante.
Também adicionamos a const ausente em diferentes partes do padrão, alteramos os nomes e a ordem dos argumentos de algumas funções novas para C ++ 20. Existem também inúmeras edições de conceitos e intervalos, abreviações do texto padrão e outras pequenas coisas.
Numbers TS
ZaMaZaN4iK e
eu fomos capazes de estimular o comitê com o documento Trabalho em andamento numérico do C ++. Agora, existem planos napoleônicos para o C ++ 23 oferecer aos usuários um conjunto de novos tipos de números (wide_integer, número inteiro, racional), juntamente com métodos auxiliares de baixo nível para trabalhar com estouros e aliases convenientes.
Disseram-me para preparar uma apresentação para a próxima reunião com uma introdução às idéias para todo o comitê.
Executores
Executors é uma das prioridades do C ++ 23. Eles são necessários para a programação reativa, para a programação assíncrona (rede, disco, processos ...), são a base para o cancelamento de regras e devem fornecer uma interface única para bibliotecas de terceiros.
Ao mesmo tempo, os executores devem otimizar os algoritmos para sua implementação interna. Por exemplo, para o código:
template <std::input_range Range> void MySort(Range& data) { namespace stdr = std::ranges; std::sort(GetGlobalExecutor(), stdr::begin(data), stdr::end(data), 42); }
a função GetGlobalExecutor () pode retornar:
* executor single-threaded - ele deve executar o usual std :: sort em seu thread;
* executor multithread - ele deve executar a classificação paralela;
* Executor GPU - ele deve mover os dados para a memória da placa de vídeo, classificá-los ali e retornar os dados;
* Executor NUMA - ...
* ...
Até agora, para implementar essa funcionalidade, você precisa fazer um CPO assustador, transformar cada algoritmo neles. O comitê não gostou ...
Mas pelo menos eles
pré-aprovaram o P0443 - a interface básica. Todas as sentenças subseqüentes para executores precisarão ser escritas na forma de patches para P0443.
Em vez de totais
Agora estamos separados do C ++ 20 por apenas uma reunião do comitê. Só um pouquinho ...
Bem, todo mundo que quiser conversar com representantes do comitê ao vivo - veja as conferências de mitaps e C ++
(*) :
*
Corehard em Minsk*
C ++ Sibéria 2020*
C ++ Rússia 2020*
St. Grupo de Usuários Petersburg C ++*
C ++ Meetup 2019 em Moscou(*) Life hack: você não precisa pagar por um ingresso para a conferência se for um orador.