deklarasikan pada variabel tipe referensi dengan tanda kurung kurawal
Perhatikan kode berikut :
#include <type_traits>
int main() {
const int& p = 42;
auto v1 = decltype(p){};
static_assert(std::is_same_v<decltype(v1), int>);
decltype(p) v2{};
static_assert(std::is_same_v<decltype(v2), const int&>);
// auto v3 = X(const int&)X {};
}
Jenis v1
disimpulkan sebagai int
. Pada saat yang sama jenis v2
diharapkan disimpulkan sebagai const int&
. Saya pikir langkah pertama untuk v1
bisa diperlakukan seperti menambahkan satu alias jenis lagi using T = decltype(p);
dan kemudian auto v4 = T{};
. Bagaimana ekspresi ( decltype(p){}
atau T{}
) ini diperlakukan oleh compiler? Saya tahu {}
bagian itu untuk instansiasi, tetapi bagaimana jenis yang dihasilkan v1
bukan merupakan jenis referensi?
Namun pertanyaan lain: apakah ada cara untuk mendeklarasikan v3
variabel dengan tipe yang sama seperti v1
menggunakan tipe yang dicatat secara eksplisit const int&
(bukan decltype(p)
)?
Setiap tautan ke standar akan dihargai.
Jawaban
(Untuk downvoter (s): jika Anda downvoted karena menurut Anda mengutip Scott Meyers tidak sama dengan mengutip standar, oh well ...)
Seperti yang dapat Anda baca dari Effective Modern C ++ (ditambah dengan bagian dari errata yang dapat Anda jangkau dengan mencari Case 2:
di tautan itu, dan itu hanya membuat pembacaan berikut lebih sederhana, tetapi tidak penting untuk pertanyaannya):
Jika
ParamType
non-referensi [...] jikaexpr
tipe adalah referensi, abaikan bagian referensi. Jika [...]expr
adalahconst
, ingatlah itu juga. Jika yavolatile
, abaikan juga itu.
di mana param
penentu deklarasi, yang dalam kasus Anda hanya auto
, yaitu non-referensi.
Dengan kata lain, Anda membuat v1
melalui polos auto
(bukan auto&
), yaitu dengan menyalin, jadi tidak masalah apakah Anda menginisialisasi dengan entitas yang referensi atau tidak, atau bahkan dengan const
atau tidak ( volatile
atau tidak, fwiw), karena Anda sedang menyalinnya.
Pikirkan tentang kasus yang lebih sederhana,
int i = 3;
int& p = i;
auto v1 = p;
Sejauh v1
yang diperhatikan, itu benar-benar tidak penting apakah itu diinitalisasi dengan satu ( i
) atau nama lain ( p
) yang dengannya entitas yang sama diketahui, karena itu akan mendapatkan salinan dari nilai apa pun yang dimiliki entitas.
auto
Pengurangan jenis berfungsi seperti pengurang jenis template (kecuali untuk perbedaan dalam cara mereka menangani penginisialisasi yang diperkuat, yang tidak relevan dalam kasus ini), dan untuk keduanya, Anda dapat merujuk ke Effective Modern C ++ dari Scott Meyers .