deklarasikan pada variabel tipe referensi dengan tanda kurung kurawal

Dec 15 2020

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 v1disimpulkan sebagai int. Pada saat yang sama jenis v2diharapkan disimpulkan sebagai const int&. Saya pikir langkah pertama untuk v1bisa 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 v1bukan merupakan jenis referensi?

Namun pertanyaan lain: apakah ada cara untuk mendeklarasikan v3variabel dengan tipe yang sama seperti v1menggunakan tipe yang dicatat secara eksplisit const int&(bukan decltype(p))?

Setiap tautan ke standar akan dihargai.

Jawaban

1 Enlico Dec 15 2020 at 00:48

(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 ParamTypenon-referensi [...] jika exprtipe adalah referensi, abaikan bagian referensi. Jika [...] expradalah const, ingatlah itu juga. Jika ya volatile, abaikan juga itu.

di mana parampenentu deklarasi, yang dalam kasus Anda hanya auto, yaitu non-referensi.

Dengan kata lain, Anda membuat v1melalui polos auto(bukan auto&), yaitu dengan menyalin, jadi tidak masalah apakah Anda menginisialisasi dengan entitas yang referensi atau tidak, atau bahkan dengan constatau tidak ( volatileatau tidak, fwiw), karena Anda sedang menyalinnya.

Pikirkan tentang kasus yang lebih sederhana,

int i = 3;
int& p = i;
auto v1 = p;

Sejauh v1yang 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.

autoPengurangan 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 .