Czy będziemy w stanie konstruować kontenery z widokami w C ++ 20?

10

Do C ++ zbliżają się nowe wersje ze standardową wersją C ++ 20.

Moje pytanie: Czy będziemy w stanie zbudować (istniejące) kontenery biblioteki standardowej o dowolnym zakresie? A co ważniejsze, z widokami zasięgu?

Na przykład czy to:

#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;
}

być poprawnym programem, który drukuje 9 16 25?

To kompiluje się z biblioteką zakresów-v3 , co jest tego warte.

einpoklum
źródło
Związane z? stackoverflow.com/questions/55950955/…
StoryTeller - Unslander Monica,
Według StoryTeller: pozorny duplikat Dlaczego nadchodząca biblioteka Ranges nie obsługuje inicjalizacji kontenera z zakresu? - ale zauważ, że rozdzielczość głosowania może jeszcze zmienić odpowiedź!
Davis Herring
@DavisHerring Co może się zmienić? P1206 nie był brany pod uwagę na początku 20 i nie sądzę, żeby zostały tu jakieś komentarze NB? P1391 został przyjęty bez konstruktora zasięgu (pomimo wprowadzającego w błąd przykładu).
Barry
@Barry: LEWG przesłał to w Kona, ale chyba źle zinterpretowałem ostatni ruch reflektorów na ten temat.
Davis Herring
@ DavisHerring Och, tęskniłem za tym, że zostało to omówione dwukrotnie - przewinąłem do ankiety 4-7 i pomyślałem, że to było to.
Barry

Odpowiedzi:

8

Moje pytanie: Czy będziemy w stanie zbudować (istniejące) kontenery biblioteki standardowej o dowolnym zakresie? A co ważniejsze, z widokami zasięgu?

Nie. Jedynym standardowym składnikiem biblioteki, który można zbudować z dowolnego zakresu, który spełnia poprawne kryteria, jest std::span<T>.

Kierunek, w którym prawdopodobnie pójdzie standardowa biblioteka, to ten, w którym zmierza również zakres v3 (zauważ, że połączony przykład z zakresu v3 kompiluje się, ale ostrzega przed przestarzałą konwersją) - używając pomocnika do wykonania konwersji dla Ciebie:

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

Jednym z powodów, dla których nie należy iść w kierunku konstruktorów zasięgu, jest sam przykład, którego używasz:

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

Zastanów się, jak różni się ta deklaracja od tych dwóch:

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

vbyłoby koniecznie vector<transform_view<...>>zawierać singiel transform_view, podczas gdy wbyłoby vector<int>.

Co więcej, dodanie większej liczby starannie skonstruowanych konstruktorów kontenerów do standardowej biblioteki i tak nie pomoże żadnym innym typom kontenerów - podczas gdy takie obiekty ranges::todziałają doskonale doskonale we wszystkich przypadkach.

Barry
źródło
Inicjowanie instrukcji vi wdla mnie wyglądają tak samo. Być może chciałeś zadeklarować wjako vector<int>. W przeciwnym razie jest to poprawna odpowiedź.
Eric Niebler,
5
@EricNiebler Dokładnie :-) Oni wyglądają tak samo. One nie są takie same.
Barry
Tak więc mój program się kompiluje, ale nie robi tego, co myślę, że działa. Ok.
einpoklum
1
Dzięki, CTAD ...
TC
Czy możesz wyjaśnić, dlaczego vi czym wsię różnią? Czy ma to coś wspólnego z tym, jak działa dedukcja argumentów z szablonu konstruktora?
Johannes Schaub - litb