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 Foo
wygląda tak:
Foo(int&&)
Foo(2)
działa, ponieważ 2
jest prvalue.
Foo(x)
nie robi, ponieważ x
jest 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_t
powyż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 T
w 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 T
stać się po prostuint