Apakah kami dapat membuat wadah dengan tampilan di C ++ 20?

10

Kisaran datang ke C ++ dengan versi standar C ++ 20.

Pertanyaan saya: Apakah kami dapat membuat wadah perpustakaan standar (yang ada) dengan jangkauan apa pun? Dan yang lebih penting, dengan berbagai tampilan?

Misalnya, apakah ini:

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

menjadi program yang valid yang mencetak 9 16 25?

Ini mengkompilasi dengan perpustakaan rentang-v3 , untuk apa itu layak.

einpoklum
sumber
Terkait? stackoverflow.com/questions/55950955/…
StoryTeller - Unslander Monica
Per StoryTeller: duplikat nyata Mengapa perpustakaan Ranges yang akan datang tidak mendukung inisialisasi wadah dari suatu rentang? —Tapi perhatikan bahwa resolusi surat suara mungkin belum mengubah jawabannya!
Davis Herring
@ Davidviser Apa yang bisa berubah? P1206 tidak dipertimbangkan untuk 20 untuk memulai dan saya tidak berpikir ada komentar NB terbuka di sini? P1391 diadopsi tanpa konstruktor rentang (meskipun contoh yang menyesatkan).
Barry
@ Barry: LEWG jadi meneruskannya di Kona, tapi saya kira saya salah mengartikan lalu lintas reflektor tentang hal itu.
Davis Herring
@ Davidviser Oh, saya merindukan bahwa itu dibahas dua kali - saya menggulir ke bawah ke jajak pendapat 4-7 dan berpikir itu adalah itu.
Barry

Jawaban:

8

Pertanyaan saya: Apakah kami dapat membuat wadah perpustakaan standar (yang ada) dengan jangkauan apa pun? Dan yang lebih penting, dengan berbagai tampilan?

Tidak. Satu-satunya komponen perpustakaan standar yang dapat dibangun dari rentang arbitrer yang memenuhi kriteria yang benar adalah std::span<T>.

Arah pustaka standar kemungkinan akan mengarah ke rentang-v3 juga menuju (perhatikan bahwa contoh terkait dari rentang-v3 mengkompilasi tetapi memperingatkan tentang konversi yang ditinggalkan) - menggunakan penolong untuk melakukan konversi untuk Anda:

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

Salah satu alasan untuk tidak menggunakan arahan konstruktor dapat dilihat dari contoh yang Anda gunakan:

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

Pertimbangkan betapa berbedanya deklarasi itu dari keduanya:

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

vtentu akan menjadi yang vector<transform_view<...>>mengandung tunggal transform_view, sementara wakan menjadi vector<int>.

Selain itu, menambahkan lebih banyak, konstruktor kontainer yang dibatasi dengan hati-hati ke perpustakaan standar tidak akan membantu jenis kontainer pihak ketiga - sementara fasilitas seperti ranges::toberfungsi dengan sangat baik dalam semua kasus.

Barry
sumber
Pernyataan yang diinisialisasi vdan wterlihat sama bagi saya. Mungkin Anda bermaksud menyatakan wsebagai vector<int>. Kalau tidak, ini jawaban yang benar.
Eric Niebler
5
@EricNiebler Persis :-) Mereka memang terlihat sama. Mereka tidak sama.
Barry
Jadi, program saya mengkompilasi tetapi tidak akan melakukan apa yang saya pikirkan. Baik.
einpoklum
1
Terima kasih, CTAD ...
TC
Bisakah Anda jelaskan mengapa vdan wberbeda? Apakah ada hubungannya dengan cara deduksi argumen template konstruktor bekerja?
Johannes Schaub - litb