To nie ma nic wspólnego z szablonów, można uzyskać ten sam rezultat jeśli T
jest po prostu typedef dla std::string&
raczej niż wyprowadzona parametru szablonu:
#include <string>
typedef std::string& T;
T Foo(int & i)
{
return T(i);
}
int main()
{
int a = 1;
std::string & s = Foo(a);
}
odpowiedź Dietmar za uświadomił mi, to może być jeszcze bardziej uproszczone do:
#include <string>
typedef std::string& T;
int main()
{
int a = 1;
std::string & s = T(a);
}
gdzie T(a)
jest taka sama jak obsady (T)a
tj (std::string&)a
które (zgodnie z zasadami 5,4 [expr.cast]) zrobi const_cast
jeśli to ważne (co nie jest) lub static_cast
jeśli to ważne (co nie jest) lub static_cast
następnie const_cast
jeśli to ważne (co nie jest) lub reinterpret_cast
jeśli to ważny (które jest) lub reinterpret_cast
następnie const_cast
jeśli to ważne, inaczej ekspresja jest źle sformułowana.
Więc jak Dietmar powiedział, to to samo, co robi reinterpret_cast
, tj
std::string & s = reinterpret_cast<std::string&>(a);
Uważam to dość zaskakujące, że oryginalny kod kompiluje, ale jak to jest taka sama jak tej linii powyżej, to wolno kompilować . Używanie wyniku rzutowania jest jednak niezdefiniowanym zachowaniem.
Aby uniknąć zaskoczenia, gdy T(a)
jest odpowiednikiem rzutowania, użyj nowej, jednolitej składni inicjalizacji C++ 11, T{a}
, która jest zawsze inicjalizacją, a nie wyrażeniem rzutowania.
Świetne pytanie, badanie i udzielenie odpowiedzi pokazało mi nowe poczucie, o którym wcześniej nie wiedziałem, dzięki JaredC i Dietmarowi za nową wiedzę!
Niezwykle szokująca twoja specjalizacja nie jest wywoływana, jeśli wywołujesz 'Foo(a);' i oczekujesz, że specjalizacja 'Foo ()' zostanie wyrzucona. –
WhozCraig
@WhozCraig Zgadzam się, byłem zdesperowany, ponieważ to nie miało sensu. – JaredC
Oczywiście uruchamia się, jeśli bezpośrednio wywołasz 'Foo()', ale to nie jest to, czego ostatecznie szukasz, bez wątpienia. –
WhozCraig