2016-06-21 20 views
1

Ich habe den folgenden Code als ein Experiment bekam:C++ 11 wendet result_of auf Elementfunktion an, fehlgeschlagen, warum?

int f1() { return 0; } 

struct Bar { 
    Bar() = delete; 
    int f() { return 0; } 
    int operator()() { return 1; } 
}; 

int main() 
{ 
    decltype(f1()) x = 3;//f1() is expression 
    result_of<decltype(&f1)()>::type x1 = 3;//type+param 
    result_of<Bar()>::type x3 = 3;//type+param 
    decltype(declval<Bar>().f()) y = 4;//expression 
    decltype((((Bar*)nullptr)->*(&Bar::f))()) z = 5;//expression 

    result_of<decltype(std::mem_fn(&Bar::f))()>::type y2 = 3;//error!!!!!! 
} 

Alles ist in Ordnung mit Ausnahme der letzten result_of: Ich habe versucht, den Rückgabetyp von Bar::f zu bekommen, result_of verwenden.

Warum es fehlgeschlagen ist, und wie man es korrigiert?

+2

es ist eine Elementfunktion, erfordert es einen impliziten Objektparameter, dh 'result_of :: Typen y2' –

+0

Danke, es funktioniert, aber scheint "result_of :: type y2 = 3;" kann auch Kompilation übergeben. Was ist richtig, warum BAR * kann noch zu diesem mem_fn gegeben werden? –

+0

Es macht keinen Unterschied, ob Sie einen Zeiger oder einen Referenztyp verwenden. Hier kommt es auf die Wertkategorie und die KV-Qualifikation an –

Antwort

0

Die unspezifiziert Rückgabetyp mem_fn:

Returns:: Ein einfacher Anruf wrapper ([func.def]) fn solche

 
template <class R, class T> 
unspecified mem_fn(R T::* pm) noexcept; 

hinsichtlich INVOKE[func.memfn]/p1 definiert ist dass der Ausdruck fn(t, a2, ..., aN) gleichist([func.require]).

wo die Definition von INVOKE die folgenden zwei Kugeln [func.require]/p1 umfasst:

definieren INVOKE(f, t1, t2, ..., tN) wie folgt:

- (t1.*f)(t2, ..., tN) wenn f ist ein Zeiger auf eine Elementfunktion einer Klasse T und is_base_of<T, decay_t<decltype(t1)>>::value ist true;

- ((*t1).*f)(t2, ..., tN)f wenn ein Zeiger auf eine Elementfunktion einer Klasse ist Tt1 und nicht die vorhergehenden beiden Elemente entsprechen;

Das heißt, das erste Argument von dem, was mem_fn gibt den Typ des impliziten Objektparameter sein muss (t1) entweder eine Referenz oder einen Zeiger, zum Beispiel:

std::result_of<decltype(std::mem_fn(&Bar::f))(Bar&)>::type y2; 
//           ~~~^ 

std::result_of<decltype(std::mem_fn(&Bar::f))(Bar*)>::type y2; 
//           ~~~^ 

Sie auch std::mem_fn entfernen könnte insgesamt:

std::result_of<decltype(&Bar::f)(Bar*)>::type y2;