Dalam c ++ 14 decltype(auto)
idiom tersebut diperkenalkan.
Biasanya penggunaannya adalah untuk memungkinkan auto
deklarasi untuk menggunakan decltype
aturan pada ekspresi yang diberikan .
Mencari contoh penggunaan "baik" dari idiom saya hanya bisa memikirkan hal-hal seperti berikut (oleh Scott Meyers ), yaitu untuk pengurangan tipe pengembalian fungsi :
template<typename ContainerType, typename IndexType> // C++14
decltype(auto) grab(ContainerType&& container, IndexType&& index)
{
authenticateUser();
return std::forward<ContainerType>(container)[std::forward<IndexType>(index)];
}
Apakah ada contoh lain di mana fitur bahasa baru ini berguna?
decltype(auto)
sesuatu yang miriptemplate<class U, V> decltype(auto) first(std::pair<U, V>& p) { return p.first; }
, meskipun saya kemudian menyadari bahwa saya harus menggunakanreturn (p.first);
yang ternyata berfungsi (tapi IIRC ini bahkan dimaksudkan).decltype(auto)
dapat menyebabkan sesuatu disalin / dipindahkan ke objek yang dinyatakan, berlawanan dengan harapan.Jawaban:
Kembalikan jenis penerusan dalam kode generik
Untuk kode non-generik, seperti contoh awal yang Anda berikan, Anda dapat memilih secara manual untuk mendapatkan referensi sebagai tipe pengembalian:
tetapi dalam kode generik Anda ingin dapat meneruskan tipe pengembalian dengan sempurna tanpa mengetahui apakah Anda berurusan dengan referensi atau nilai.
decltype(auto)
memberi Anda kemampuan itu:Menunda pengurangan jenis pengembalian dalam templat rekursif
Dalam Tanya Jawab ini beberapa hari yang lalu, rekursi tak terbatas selama instantiasi templat ditemukan ketika jenis pengembalian templat ditentukan sebagai
decltype(iter(Int<i-1>{}))
gantidecltype(auto)
.decltype(auto)
digunakan di sini untuk menunda pengurangan tipe pengembalian setelah debu instantiation template telah menetap.Penggunaan lainnya
Anda juga dapat menggunakan
decltype(auto)
dalam konteks lain, misalnya konsep Standar N3936 juga menyatakan7.1.6.4 penentu otomatis [dcl.spec.auto]
Draf ini juga berisi contoh inisialisasi variabel ini:
sumber
(i)
vsi
hal baru di C ++ 14?decltype(expr)
dandecltype((expr))
sudah berbeda dalam C ++ 11, ini menggeneralisasi perilaku itu.auto
akan melakukan pekerjaan dengan baik, karena hasilnya tetap dikembalikan dengan nilai ... Atau apakah saya melewatkan sesuatu?Mengutip hal-hal dari sini :
decltype(auto)
ini sangat berguna untuk menyimpulkan tipe kembalinya fungsi penerusan dan pembungkus yang serupa , di mana Anda ingin tipe tersebut “melacak” beberapa ekspresi yang Anda panggil.Misalnya, mengingat fungsi di bawah ini:
Namun,
decltype(auto)
tidak dimaksudkan untuk menjadi fitur yang banyak digunakan di luar itu.Secara khusus, meskipun dapat digunakan untuk mendeklarasikan variabel lokal , melakukan hal itu mungkin hanya antipattern karena referensi variabel lokal seharusnya tidak bergantung pada ekspresi inisialisasi.
Juga, ini sensitif terhadap bagaimana Anda menulis pernyataan pengembalian.
Misalnya, dua fungsi di bawah ini memiliki tipe pengembalian yang berbeda:
string
, pengembalian keduastring&
, yang merupakan referensi ke variabel lokalstr
.Dari proposal Anda dapat melihat lebih banyak kegunaan yang dimaksudkan.
sumber
auto
untuk pengembalian?auto
kembali) juga tetapi OP meminta penggunaan khususdecltype(auto)
.auto lookup_a_string() { ... }
? Apakah selalu tipe non-referensi? Dan karenaauto lookup_a_string() ->decltype(auto) { ... }
itu diperlukan untuk memaksa untuk memungkinkan referensi (dalam beberapa kasus) dikembalikan?auto
didefinisikan sebagai templat nilai by pass, jadi ya tidak bisa menjadi referensi. Harap tungguauto
bisa apa saja termasuk referensi, tentu saja.std::vector
. Katakan sudahtemplate<typename T> struct S { auto & operator[](std::size_t i) { return v[i]; } std::vector<T> v; }
. KemudianS<bool>::operator[]
akan mengembalikan referensi yang menggantung karena spesialisasistd::vector<bool>
. Mengubah tipe pengembalian untukdecltype(auto)
menghindari masalah ini.