Différence entre les std::result_of et decltype
J'ai du mal à comprendre le besoin de std::result_of
dans C++0x. Si j'ai bien compris, result_of
est utilisé pour obtenir le type résultant de l'appel d'une fonction de l'objet avec certains types de paramètres. Par exemple:
template <typename F, typename Arg>
typename std::result_of<F(Arg)>::type
invoke(F f, Arg a)
{
return f(a);
}
Je ne vois pas vraiment la différence avec le code suivant:
template <typename F, typename Arg>
auto invoke(F f, Arg a) -> decltype(f(a)) //uses the f parameter
{
return f(a);
}
ou
template <typename F, typename Arg>
auto invoke(F f, Arg a) -> decltype(F()(a)); //"constructs" an F
{
return f(a);
}
Le seul problème que je peux voir avec ces deux solutions, c'est que nous avons besoin de:
- avons une instance de functor pour l'utiliser dans l'expression passée à decltype.
- savoir un constructeur défini pour le foncteur.
Suis-je en droit de penser que la seule différence entre decltype
et result_of
c'est que le premier a besoin d'une expression, alors que le second ne l'est pas?
Vous devez vous connecter pour publier un commentaire.
result_of
était introduit en Boost, puis inclus dans TR1, et enfin dans C++0x. Doncresult_of
a un avantage qui est rétro-compatible (adapté de la bibliothèque).decltype
est une toute nouvelle chose dans C++0x, ne restreint pas uniquement pour le type de retour d'une fonction, et est une fonctionnalité du langage.De toute façon, sur gcc 4.5,
result_of
est mis en œuvre en termes dedecltype
:decltype
est plus laid mais aussi de plus en plus puissants.result_of
ne peut être utilisé pour les types qui sont disponibles et il exige types d'arguments. Par exemple, vous ne pouvez pas utiliserresult_of
ici:template <typename T, typename U> auto sum( T t, U u ) -> decltype( t + u );
si les arguments peuvent être arithmétique types (il n'y a pas de fonctionF
de telle sorte que vous pouvez définirF(T,U)
pour représentert+u
. Pour les types définis par l'utilisateur vous pourriez. De la même façon (je n'ai pas vraiment joué avec elle) j'imagine que les appels aux méthodes membres pourrait être difficile à faire avecresult_of
sans l'aide de liants ou des lambdasstd::declval
, comme le code que j'ai montré ci-dessus. Bien sûr, c'est moche 🙂result_of
et de ses auxiliaires de typeresult_of_t
est déprécié que de C++17 en faveur deinvoke_result
etinvoke_result_t
, alléger certaines restrictions de l'ancien. Ces sont listés sur le bas de la en.cppreference.com/w/cpp/types/result_of.Si vous avez besoin du type de quelque chose qui n'est pas quelque chose comme un appel de fonction,
std::result_of
juste ne s'applique pas.decltype()
peut vous donner le type d'une expression.Si nous nous limitons simplement les différentes façons de déterminer le type de retour d'un appel de fonction (entre
std::result_of_t<F(Args...)>
etdecltype(std::declval<F>()(std::declval<Args>()...)
), alors il y a une différence.std::result_of<F(Args...)
est défini comme:La différence entre
result_of<F(Args..)>::type
etdecltype(std::declval<F>()(std::declval<Args>()...)
est tout au sujet de quiINVOKE
. À l'aide dedeclval
/decltype
directement, en plus d'être tout à fait un peu plus de temps pour type, n'est valable que siF
est directement remboursables (une fonction du type d'objet ou d'une fonction ou d'un pointeur de fonction).result_of
supporte en outre des pointeurs vers les membres les fonctions et les pointeurs vers les données des membres.D'abord, à l'aide de
declval
/decltype
la garantie d'un SFINAE-friendly expression, tandis questd::result_of
pourrait vous donner une erreur de disque dur au lieu d'une déduction de l'échec. Qui a été corrigé en C++14:std::result_of
est maintenant nécessaire pour être SFINAE-convivial (merci à ce document).De manière conforme C++14 compilateur,
std::result_of_t<F(Args...)>
est strictement supérieure. C'est plus clair, plus courte, et correctement† prend en charge plus deF
s‡ .†, à Moins que vous l'utilisez dans un contexte où vous ne souhaitez pas autoriser les pointeurs vers les membres, de sorte
std::result_of_t
serait de réussir dans les cas où vous pouvez être amené à échouer.‡ Avec des exceptions. Alors qu'il prend en charge les pointeurs vers les membres,
result_of
ne fonctionnera pas si vous essayez à instancier un invalide type-id. Elles comprennent une fonction retournant une fonction ou de prendre résumé types par valeur. Ex.:L'utilisation correcte aurait été
result_of_t<F&()>
, mais c'est un détail que vous n'avez pas à mémoriser avecdecltype
.T
et une fonctiontemplate<class F> result_of_t<F&&(T&&)> call(F&& f, T&& arg) { return std::forward<F>(f)(std::move(arg)); }
, est l'utilisation deresult_of_t
correct?f
est unconst T
, devrions-nous utiliserresult_of_t<F&&(const T&)>
?