wymaga, aby był to typ - ale nie tylko dowolny typ. T
musi być typu funkcja więc stosować częściowa specjalizacji result_of
:
template <class Fn, class... ArgTypes> struct result_of<Fn(ArgTypes...)>;
takie, że:
decltype(INVOKE(declval<Fn>(), declval<ArgTypes>()...))
jest sensowne (C++ 11 20.9.7.6) . (INVOKE jest zdefiniowane w 20.8.2.)
Przyczyna std::result_of<f(int)>
nie działa, ponieważ f
nie jest typem - jest instancją typu funkcji. Aby zadeklarować x
być typem powrotu f
stosowane do int
, wystarczy napisać to:
decltype(f(int{})) x;
lub jeśli wolisz hard-kodującą int
:
decltype(f(32)) x;
Jeśli typ z f
pożądane jest użycie:
using FuncPtr = decltype(f);
kod podany F
(to jest nie niższa przypadku f
), jednak to typ i tak F(int)
definiuje typ reprezentujący funkcję, która zwraca F
przyjmującą int
jako argument. Najwyraźniej to nie jest F! Typ F
to struktura, której instancje mogą korzystać z operatora wywołania funkcji. F
również nie ma jawnych lub niejawnych konstruktorów, biorąc również pod numer int
itd. Jak to działa? Krótka odpowiedź: Szablon "magia".
Zasadniczo definicja std::result_of
przyjmuje typ, F(int)
i oddziela typ zwracany od typów argumentów, dzięki czemu można określić, który przypadek INVOKE() pozwoliłby mu działać. Przypadki powołać są:
- F jest wskaźnik do funkcji składowej dla pewnej klasy T
- Jeśli jest tylko jeden argument, F jest wskaźnik do członka danych klasy T, lub
- instancja F może być stosowany, jako funkcję, tj
declval<F>()(declval<int>())
który może być wywołaniu funkcji lub jakiś rodzaj funktora (na przykład, jak swojej przykład).
Po ustaleniu tego, result_of
może następnie określić typ zwrotu poprawnego wyrażenia. To jest zwracane za pośrednictwem członka result_of
's.
Piękną rzeczą jest to, że użytkownik result_of
nie musi nic wiedzieć o tym, jak to działa. Trzeba tylko zrozumieć, że result_of
potrzebuje funkcji TYPE. Jeśli używa się nazw, które nie są typami w kodzie (np. f
), wówczas trzeba będzie użyć decltype
, aby uzyskać typ wyrażenia z takimi.
Wreszcie, powodem, dla którego f
nie można uznać za typ, jest to, że parametry szablonu pozwalają również na stałe wartości, a f
jest stałą wartością wskaźnika funkcji. Można to łatwo wykazać (stosując definicję Pytanie z dnia f
):
template <double Op(int)>
double invoke_op(int i)
{
return Op(i);
}
a później:
std::cout << invoke_op<f>(10) << std::endl;
Tak, aby uzyskać typ wartości zwracanej wyraz poprawnie powołuje f
z pewnym int
można by napisać:
decltype(f(int{}))
(Uwaga: f
nigdy nie nazywa się: kompilator po prostu używa wyrażenia wewnątrz decltype
celu określenia jego rezultat czyli jego wartość zwracana w tym przypadku).
Rozwiązaniem jest użycie tego 'std :: result_of :: typ x; '. Jeśli chcesz głębsze zrozumienie, sprawdź to pytanie na http://stackoverflow.com/q/2763824/893693 –
inf