61 votes

Comment utiliser Boost pour obtenir des types de retour automatique de type C++14 ?

Supposons que j'ai une fonction qui additionne deux valeurs. Si je ne connais pas les types, je dois écrire ma fonction deux fois, une fois dans la valeur de retour réelle et une autre fois dans le spécificateur de type de retour :

template <typename A, typename B>
auto Add(const A& a, const B& b) ->std::decay<decltype(a + b)>::type
{
  return a + b;
}

Bien que cette méthode fonctionne, elle n'est pas souhaitable car elle est difficile à lire et à maintenir.

En C++14, ce ne sera plus un problème, car nous pouvons abandonner le spécificateur de type de retour (je ne suis pas sûr qu'il fera la décadence cependant...). Pour l'instant, je suis coincé avec C++11.

D'après mon expérience, chaque fois que je cherche une fonctionnalité en C++ qui n'a pas encore fait son chemin dans la norme, mais pour laquelle il existe un besoin évident, l'option Bibliothèque Boost a généralement une solution. J'ai cherché dans la documentation, mais je n'ai rien trouvé qui puisse m'aider. Le site BOOST_AUTO_RETURN y BOOST_TYPEOF_TPL semblent davantage destinées à fournir des fonctionnalités C++11 aux utilisateurs de C++03.

En gros, ce que je cherche, c'est quelque chose qui exécute la fonctionnalité suivante :

template <typename A, typename B>
auto Add(const A& a, const B& b)
{
  return a + b; // Deduce return type from this, like C++14 would
}

Existe-t-il une fonctionnalité de la bibliothèque Boost dont je ne suis pas au courant (ou une astuce dans C++11) qui me permettrait de renoncer à l'utilisation explicite de l'option -> decltype(...) après chaque type de retour automatique ? Comment cela pourrait-il être mis en œuvre ?

26voto

hvd Points 42125

Le seul type de retour de fonction déduit possible en C++11 est le type de retour d'une lambda. Le C++11 restreint cependant l'utilisation des lambdas. Cela fonctionne :

auto add = [](int a, int b) { return a + b; };

Ceci est valable, et définit add comme un lambda qui définit un operator() fonction membre qui renvoie int . Puisque le lambda ne capture rien, vous pouvez même écrire

auto add = +[](int a, int b) { return a + b; };

de faire add un pointeur vers une fonction ordinaire : il obtient le type int(*)(int, int) .

Cependant, C++11 ne permet pas de spécifier les types de paramètres en tant que auto ni de laisser add ne peut être défini comme une variable modèle, vous ne pouvez donc pas l'utiliser pour déduire de manière générique un type de retour. Une tentative de l'intégrer dans une classe modèle échoue :

template <typename A, typename B>
struct S { static auto add = [](A a, B b) { return a + b; }; }; // invalid

Il est invalide d'initialiser add en classe ici, et vous ne pouvez pas utiliser auto à moins que le membre soit initialisé en classe. De plus, même si cela fonctionnait, cela ne permettrait pas la déduction de A o B ce qui semble être plus ce que vous recherchez.

Compte tenu de ces limites, je ne vois pas d'autre solution que de répéter l'expression. Vous pourriez cependant cacher la répétition dans une macro triviale.

#define AUTO_RETURN(func, ...) auto func -> decltype(__VA_ARGS__) { return __VA_ARGS__; }

template <typename A, typename B>
AUTO_RETURN(add(A a, B b), a + b)

Ou la variante signalée par Marc Glisse,

#define RETURNS(...) noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }

template <typename A, typename B>
auto add(A a, B b) RETURNS(a + b)

qui semble un peu plus propre.

Il y a peut-être déjà quelque chose comme ça dans Boost, je ne sais pas. Quoi qu'il en soit, étant donné la trivialité, Boost semble exagéré ici.

5voto

Paul Points 4552

Il y a une bibliothèque Pythy qui tente d'émuler cette syntaxe. Cependant, il ne fonctionne que sur clang. Il ne fonctionne pas sur gcc en raison de ces bogues. aquí y aquí . Ils seront peut-être corrigés pour gcc 4.9, mais si vous utilisez gcc 4.9, vous pouvez utiliser les types de retour automatiques, de toute façon.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X