Kwestia jest taka, że, ponieważ klasa jest na matrycy T, w konstruktorze Foo(T&&)jesteśmy nie wykonującego typu odliczenie; Zawsze mamy referencję wartości r. Oznacza to, że konstruktor Foowygląda tak:
Foo(int&&)
Foo(2)działa, ponieważ 2jest prvalue.
Foo(x)nie robi, ponieważ xjest wartością, z którą nie można się powiązać int&&. Możesz zrobić, std::move(x)aby rzucić go na odpowiedni typ ( demo )
Foo<int&>(x)działa dobrze, ponieważ konstruktor staje się z Foo(int&)powodu reguł zwijania odniesienia; początkowo jest to, Foo((int&)&&)co spada Foo(int&)zgodnie ze standardem.
W odniesieniu do „nadmiarowego” przewodnika po dedukcji: Początkowo istnieje domyślny przewodnik po dedukcji szablonów dla kodu, który zasadniczo działa jak funkcja pomocnicza:
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);
Wynika to z faktu, że standard dyktuje, że ta (fikcyjna) metoda szablonu ma te same parametry szablonu co klasa (Just T ), po której następują dowolne parametry szablonu jako konstruktor (w tym przypadku żaden; konstruktor nie jest szablonowany). Następnie typy parametrów funkcji są takie same jak w konstruktorze. W naszym przypadku po utworzeniu instancji Foo<int>konstruktor wygląda jak Foo(int&&)odwołanie do wartości, innymi słowy. Stąd użycie add_rvalue_reference_tpowyższego.
Oczywiście to nie działa.
Po dodaniu „zbędnego” przewodnika dedukcyjnego:
template<typename T>
Foo(T&&) -> Foo<T>;
Pozwoliłeś kompilator do odróżnienia, że mimo wszelkiego rodzaju odniesienie do załączonego Tw konstruktorze ( int&, const int&lubint&& itp), zamierzony rodzaj wywieść dla klasy być bez odniesienia (tylko T). To dlatego, że nagle są wykonując typu wnioskowanie.
Teraz generujemy kolejną (fikcyjną) funkcję pomocniczą, która wygląda następująco:
template<class U>
Foo<U> MakeFoo(U&& u)
{
return Foo<U>(std::forward<U>(u));
}
// ...
auto f = MakeFoo(x);
(Nasze wywołania do konstruktora są przekierowywane do funkcji pomocnika w celu odliczenia argumentu szablonu klasy, więc Foo(x) staje się MakeFoo(x)).
To pozwala U&&stać się int&i Tstać się po prostuint