à propos de std :: result_of en c ++ 11

Comme je le sais, une implémentation possible de std::result_of est

 template struct result_of { typedef decltype( std::declval()(std::declval()...) ) type; }; 

Mais lorsque j’utilise std::result_of j’ai quelques problèmes.

 int f(int x) { return 0; } template void Test(const T& t) { decltype(std::declval()(std::declval())) i1 = 1; // ok typename std::result_of::type i2 = 2; // comstack error: // function returning a function // I think this means the same thing just as above, right? } int main() { Test(f); return 0; } 

Quelles sont les différences entre ces deux formes?

std::result_of est déclaré en C ++ 11 [meta.trans.other] Tableau 57 sous la forme:

 template  struct result_of; 

et cela nécessite que:

Fn doit être un type appelable (20.8.1), une référence à une fonction ou une référence à un type appelable. L’expression

 decltype(INVOKE(declval(), declval()...)) 

doit être bien formé.

le type appelable est défini dans [func.def] / 3:

Un type appelable est un type d’object de fonction (20.8) ou un pointeur sur un membre.

Le type d’object de fonction est défini dans [function.objects] / 1:

Un type d’object de fonction est un type d’object (3.9) pouvant être le type de l’ expression postfixe dans un appel de fonction (5.2.2, 13.3.1.1). …

Dans votre programme, f est une référence à une fonction de type int(int) , donc T est déduit du type de fonction int(int) . Notez qu’un type de fonction n’est pas une des options valides pour le type Fn à transmettre à std::result_type . Une référence à function est un type acceptable, cependant: vous devez passer le type complet du paramètre Test s à result_of au lieu de T ( Demo at Coliru ):

 template void Test(const T&) { decltype(std::declval()(std::declval())) i1 = 1; typename std::result_of::type i2 = 2; } 

En ce qui concerne la différence entre les deux formes, rappelez-vous que std::declval renvoie toujours un type de référence; spécifiquement std::declval() retourne T&& . Alors

 decltype(std::declval()(std::declval())) 

demande quel type est renvoyé lorsqu’un T&& est appelé avec un argument int&& .

[basic.compound] décrit les types de fonction en C ++:

– les fonctions qui ont des parameters de types donnés et retournent des void ou des références ou des objects d’un type donné

Par conséquent, la partie type de retour d’un type de fonction ne doit pas être elle-même un type de fonction. T(int) n’est donc pas un type valide dans le système de types C ++ lorsque T = int(int) .

De plus, [dcl.fct] / 8 précise:

Les fonctions ne doivent pas avoir de type de retour de type tableau ou fonction

Notez également que l’analogue réel de votre ligne i1 est typename std::result_of::type i2 .