Masalahnya di sini adalah, karena kelas digunakan T, pada konstruktor Foo(T&&)kita tidak melakukan deduksi tipe; Kami selalu memiliki referensi r-value. Artinya, konstruktor untuk Foobenar - benar terlihat seperti ini:
Foo(int&&)
Foo(2)berfungsi karena 2merupakan nilai awal.
Foo(x)tidak karena xmerupakan nilai yang tidak dapat mengikat int&&. Anda dapat melakukannya std::move(x)untuk melemparkannya ke jenis yang sesuai ( demo )
Foo<int&>(x)berfungsi dengan baik karena konstruktor menjadi Foo(int&)karena aturan runtuh referensi; awalnya ini Foo((int&)&&)yang runtuh Foo(int&)sesuai standar.
Sehubungan dengan panduan pengurangan "redundant" Anda: Awalnya ada panduan pengurangan template default untuk kode yang pada dasarnya bertindak seperti fungsi pembantu seperti:
template<typename T>
struct Foo {
Foo(T&&) {}
};
template<typename T>
Foo<T> MakeFoo(std::add_rvalue_reference_t<T> value)
{
return Foo<T>(std::move(value));
}
//...
auto f = MakeFoo(x);
Ini karena standar menyatakan bahwa metode templat (fiksi) ini memiliki parameter templat yang sama dengan kelas (Hanya T) diikuti oleh parameter templat apa pun sebagai konstruktor (tidak ada dalam kasus ini; konstruktor tidak templated). Kemudian, jenis parameter fungsi sama dengan yang ada di konstruktor. Dalam kasus kami, setelah instantiating Foo<int>, konstruktornya terlihat seperti Foo(int&&), referensi-nilai dengan kata lain. Karenanya penggunaan di add_rvalue_reference_tatas.
Jelas ini tidak berhasil.
Saat Anda menambahkan panduan deduksi "redundan" Anda:
template<typename T>
Foo(T&&) -> Foo<T>;
Anda diperbolehkan compiler untuk membedakan bahwa, meskipun setiap jenis referensi yang melekat Tdalam konstruktor ( int&, const int&, atau int&&dll), Anda bermaksud jenis disimpulkan untuk kelas menjadi tanpa referensi (hanya T). Ini karena kita tiba - tiba melakukan inferensi tipe.
Sekarang kita menghasilkan fungsi pembantu (fiksi) lain yang terlihat seperti ini:
template<class U>
Foo<U> MakeFoo(U&& u)
{
return Foo<U>(std::forward<U>(u));
}
// ...
auto f = MakeFoo(x);
(Panggilan kami untuk konstruktor diarahkan ke fungsi pembantu untuk keperluan kelas template argumen deduksi, sehingga Foo(x)menjadi MakeFoo(x)).
Ini memungkinkan U&&untuk menjadi int&dan Tmenjadi sederhanaint