Seremos capazes de construir contêineres com visualizações em C ++ 20?

10

As faixas estão chegando ao C ++ com a versão padrão do C ++ 20.

Minha pergunta: Seremos capazes de construir contêineres de biblioteca padrão (existentes) com qualquer intervalo? E mais importante, com vistas de alcance?

Por exemplo, isso será:

#include <vector>
#include <iostream>
#include <ranges>

int main() {
    auto sq = [](int x) { return x * x; };
    std::vector<int> vec { 3, 4, 5 };
    std::vector<int> squares { std::ranges::views::transform(vec, sq) };
    for(auto i : squares) { std::cout << i << ' '; }
    std::cout << std::endl;
}

ser um programa válido que imprime 9 16 25?

Isso compila com a biblioteca de range-v3 , pelo que vale a pena.

einpoklum
fonte
Relacionado? stackoverflow.com/questions/55950955/…
StoryTeller - Unslander Monica
Por StoryTeller: duplicata aparente de Por que a próxima biblioteca Ranges não suporta a inicialização de contêineres a partir de um intervalo? - mas observe que a resolução da votação ainda pode mudar a resposta!
Davis Herring
@DavisHerring O que poderia mudar? O P1206 não foi considerado por 20, para começar, e não acho que haja comentários do NB deixados em aberto aqui? P1391 foi adotado sem o construtor de intervalo (apesar do exemplo enganoso).
Barry
@ Barry: O LEWG o encaminhou em Kona, mas acho que interpretei mal o tráfego recente dos refletores.
Davis Herring
@DavisHerring Ah, eu senti falta de que isso fosse discutido duas vezes - rolei até a enquete 4-7 e achei que era isso.
Barry

Respostas:

8

Minha pergunta: Seremos capazes de construir contêineres de biblioteca padrão (existentes) com qualquer intervalo? E mais importante, com vistas de alcance?

Não. O único componente da biblioteca padrão que é construtível a partir de um intervalo arbitrário que atende aos critérios corretos é std::span<T>.

A direção que a biblioteca padrão provavelmente seguirá é a que o range-v3 também está seguindo (observe que o exemplo vinculado do range-v3 é compilado, mas avisa sobre uma conversão obsoleta) - usando um auxiliar para fazer conversões para você:

std::vector<int> squares =
    std::ranges::views::transform(vec, sq) | std::ranges::to<std::vector>;

Um dos motivos para não seguir a direção dos construtores de intervalo pode ser visto no próprio exemplo que você está usando:

std::vector<int> squares { std::ranges::views::transform(vec, sq) };

Considere o quão diferente é essa declaração dessas duas:

std::vector v { std::ranges::views::transform(vec, sq) };
std::vector w ( std::ranges::views::transform(vec, sq) );

vseria necessariamente um vector<transform_view<...>>contendo um único transform_view, enquanto wseria um vector<int>.

Além disso, adicionar mais construtores de contêineres cuidadosamente restritos à biblioteca padrão não ajudará de qualquer maneira os tipos de contêineres de terceiros - enquanto uma instalação como ranges::tofunciona perfeitamente bem em todos os casos.

Barry
fonte
As instruções são inicializadas ve wtêm a mesma aparência para mim. Talvez você pretenda declarar wcomo vector<int>. Caso contrário, esta é a resposta correta.
Eric Niebler
5
@EricNiebler Exatamente :-) Eles parecem iguais. Eles não são os mesmos.
Barry
Portanto, meu programa compila, mas não faz o que acho que faz. Está bem.
einpoklum
11
Obrigado, CTAD ...
TC
Você pode explicar por que ve wé diferente? Tem algo a ver com como funciona a dedução de argumento do modelo de construtor?
Johannes Schaub - litb