Mengapa inisialisasi tanda kurung bulat standar lebih disukai untuk `membuat_‹sesuatu›`?

Fungsi std::make_ dalam standar, seperti:

  • std::make_unique dan std::make_shared
  • std::make_tuple
  • std::make_from_tuple

semuanya menggunakan inisialisasi tanda kurung bulat secara internal, bukan tanda kurung kurawal.

Misalnya, make_from_tuple seperti yang disajikan oleh standar memilih untuk mengembalikan T(params...) daripada dari T{params...}.

Hasilnya adalah hal-hal berikut ini ilegal:

auto vec = std::make_from_tuple<std::vector<int>>(std::make_tuple());
auto arr = std::make_from_tuple<std::array<int, 2>>(std::make_tuple(9, 8));

^pembuatan std::array dari tuple, seperti di atas, adalah ilegal juga dengan C++20, seperti p0960 - memungkinkan inisialisasi agregat dari daftar nilai yang diberi tanda kurung menjadi bagian dari spesifikasi C++20 tidak mengizinkan inisialisasi untuk std::array, karena tipe dalamnya adalah T[size] yang tidak dapat diinisialisasi dari daftar nilai (tanda kurung telah dihapus oleh inisialisasi std::array).


Jika ini berhasil, pemilihan inisialisasi tanda kurung vs. tanda kurung kurawal memiliki arti:

auto vec2 = std::make_from_tuple<std::vector<int>>(std::make_tuple(2, 3));
// a vector with the values: {3, 3} surprise? :-)

(Di atas tentu saja adalah contoh mainan. Tupel yang disediakan mungkin disediakan secara eksternal).

Dengan curly_make_from_tuple suka:

template<typename T, typename tuple_t>
constexpr auto curly_make_from_tuple(tuple_t&& tuple) {
    constexpr auto get_T = [](auto&& ... x){ return T{std::forward<decltype(x)>(x) ... }; };
    return std::apply(get_T, std::forward<tuple_t>(tuple));
}

semua kasus di atas akan berhasil, dengan cara yang mungkin dianggap lebih alami:

auto arr = curly_make_from_tuple<std::array<int, 2>>(std::make_tuple(9, 8)); // {9, 8}
auto vec = curly_make_from_tuple<std::vector<int>>(std::make_tuple());       // {}
auto vec2 = curly_make_from_tuple<std::vector<int>>(std::make_tuple(2, 3));  // {2, 3}

Pertanyaannya adalah: mengapa standar memilih inisialisasi tanda kurung bulat dibandingkan tanda kurung kurawal?


Tautan terkait:

Pertanyaan serupa, dari sudut pandang efisiensi: Mengapa apakah implementasi make_tuple tidak kembali melalui inisialisasi kurung kurawal?

diskusi dan saran yang bagus untuk menambahkan inisialisasi tanda kurung kurawal opsi untuk utilitas `make_`.

Makalah asli yang mengusulkan make_from_tuple, P0209r2, sepertinya tidak membahas dua alternatif T(params...) dan T{params...}, mungkin karena semua metode utilitas make_ serupa telah menggunakan inisialisasi tanda kurung bulat.


person Amir Kirsh    schedule 26.05.2020    source sumber
comment
Pemanggilan fungsi selalu menggunakan tanda kurung bulat. Itulah sintaks bahasanya. Tanda kurung kurawal adalah untuk daftar penginisialisasi.   -  person sanitizedUser    schedule 26.05.2020
comment
Apakah Anda bertanya mengapa mereka menggunakan T(std::forward<decltype(x)>(x) ... ) bukannya T{std::forward<decltype(x)>(x) ... }?   -  person NathanOliver    schedule 26.05.2020
comment
@NathanOliver ya, mengabaikan opsi mewah untuk mendukung keduanya (seperti yang dibahas di tautan ke-2 yang disediakan di akhir) jika ada yang harus didukung, mengapa tanda kurung bulat?   -  person Amir Kirsh    schedule 26.05.2020
comment
Ini bukan inisialisasi, ini pemanggilan fungsi std::make_unique, std::make_shared, std::make_tuple, dll. jangan menginisialisasi sesuatu, mereka mengembalikan objek dan kelebihannya adalah keamanan thread, kesederhanaan, dll.   -  person asmmo    schedule 26.05.2020
comment
@asmmo pertanyaannya adalah tentang implementasi internal dari fungsi-fungsi ini.   -  person Amir Kirsh    schedule 26.05.2020
comment
Pertanyaan terkait lainnya, dengan beberapa jawaban menarik, dapat ditemukan di sini: stackoverflow.com/questions/55141594/   -  person Yehezkel B.    schedule 26.05.2020


Jawaban (1)


Karena tidak mungkin menginisialisasi struktur menggunakan braced-init-list di C++98.

Jadi untuk konsistensi fitur perpustakaan standar baru telah menggunakan bentuk inisialisasi yang sama seperti yang digunakan di STL.

Terlebih lagi, ini tidak pernah diubah menjadi inisialisasi daftar karena alasan kompatibilitas: inisialisasi daftar belum tentu memiliki arti yang sama dengan bentuk inisialisasi dalam tanda kurung yang setara.

person Oliv    schedule 26.05.2020
comment
Fungsi perpustakaan manakah sebelum C++11 yang membuat objek seperti itu? Mungkin tidak ada, karena bergantung pada template variadik. Jadi jika semua fungsi seperti itu baru muncul di C++11 atau setelahnya, mungkin saja menggunakan inisialisasi kurung kurawal. Tentu saja harus dipilih salah satu jika tidak menggunakan pendekatan mewah untuk mendukung keduanya, tapi apakah panitia mempertimbangkan keduanya? Apakah ini keputusan yang disengaja? - person Amir Kirsh; 27.05.2020
comment
@AmirKirsh Misalnya pengalokasi STL, untuk konstruksi salinan. - person Oliv; 27.05.2020