Mengapa remove_reference tidak berfungsi pada fungsi?

38

Berlari ke sesuatu yang aneh ketika melakukan beberapa metaprogramming pemrograman tempo hari. Ini pada dasarnya datang ke pernyataan ini tidak (seperti yang saya harapkan) lewat.

static_assert(std::is_same_v<void(), std::remove_reference_t<void()&>>);

Pada awalnya saya pikir saya membuat kesalahan sintaksis mendefinisikan referensi fungsi, tetapi pernyataan ini berlalu, menunjukkan itu tidak terjadi.

static_assert(std::is_same_v<void()&, void()&>);

Saya juga mencoba menerapkan remove_referencesendiri menyalin sumber dari cppreference tetapi itu tidak berhasil. Apa yang terjadi disini?

Artikash berkata Reinstate Monica
sumber

Jawaban:

42

Selamat datang di dunia Jenis Fungsi yang Membenci.

void() &adalah tidak referensi ke void(). Cara mengeja yang akan void(&)()(yang jika Anda remove_reference_t, Anda akan mendapatkan kembali void()- yang remove_reference_t tidak bekerja pada referensi fungsi, jika apa yang Anda berikan itu sebenarnya referensi ke tipe fungsi).

Apa yang void() &sebenarnya merujuk pada adalah jenis fungsi anggota yang memenuhi syarat referensi setelah Anda melepas kelas. Itu adalah:

struct C {
    void f() &;
};

Jenisnya &C::fadalah void (C::*)() &. Tapi semua pointer ke anggota dapat ditulis sebagai T C::*untuk beberapa jenis T, dan dalam hal ini jenis Takan void() &.

Lihat juga P0172 .

Barry
sumber
3
Seseorang harus membuat pertanyaan kanonik untuk tipe fungsi yang menjijikkan.
Brian
Wow, C ++ tidak pernah gagal mengejutkan saya bahkan jika saya telah belajar dan menggunakannya selama hampir 10 tahun.
Kelvin Hu
13

Jenis yang Anda miliki bukan referensi ke fungsi, tetapi fungsi dengan kualifikasi referensi .

static_assert(std::is_same_v<void()&, void()&>);
static_assert(!std::is_same_v<void()&, void(&)()>);
static_assert(std::is_same_v<void(&)(), void(&)()>);
static_assert(std::is_same_v<void(), std::remove_reference_t<void(&)()>>);
0x5453
sumber