web-dev-qa-db-fra.com

Moyen le plus simple de déterminer le type de fonction de retour

Étant donné une fonction très simple mais longue, telle que:

int foo(int a, int b, int c, int d) {
    return 1;
}

// using ReturnTypeOfFoo = ???

Quel est le moyen le plus simple et le plus concis de déterminer le type de retour de la fonction (ReturnTypeOfFoo, dans cet exemple: int) lors de la compilation sans répéter les types de paramètres de la fonction ( par nom uniquement, puisqu'il est connu que la fonction n'a pas de surcharge supplémentaire)?

47
Cybran

Vous pouvez tirer parti de std::function ici qui vous donnera un typedef pour le type de retour des fonctions. Cela nécessite la prise en charge de C++ 17, car il repose sur déduction d'argument de modèle de classe , mais cela fonctionnera avec n'importe quel type appelable:

using ReturnTypeOfFoo = decltype(std::function{foo})::result_type;

Nous pouvons rendre cela un peu plus générique comme

template<typename Callable>
using return_type_of_t = 
    typename decltype(std::function{std::declval<Callable>()})::result_type;

qui vous permet ensuite de l'utiliser comme

int foo(int a, int b, int c, int d) {
    return 1;
}

auto bar = [](){ return 1; };

struct baz_ 
{ 
    double operator()(){ return 0; } 
} baz;

using ReturnTypeOfFoo = return_type_of_t<decltype(foo)>;
using ReturnTypeOfBar = return_type_of_t<decltype(bar)>;
using ReturnTypeOfBaz = return_type_of_t<decltype(baz)>;
54
NathanOliver

Le plus simple et concis est probablement:

template <typename R, typename... Args>
R return_type_of(R(*)(Args...));

using ReturnTypeOfFoo = decltype(return_type_of(foo));

Notez que cela ne fonctionnera pas pour les objets de fonction ou les pointeurs vers les fonctions membres. Juste des fonctions, qui ne sont pas surchargées ou des modèles, ou noexcept.

Mais cela peut être étendu pour supporter tous ces cas, si vous le souhaitez, en ajoutant plus de surcharges de return_type_of.

22
Barry

Je ne sais pas si la manière la plus simple (si vous pouvez utiliser C++ 17 n'est certainement pas: voir la réponse de NathanOliver) mais ... qu'en est-il de la déclaration d'une fonction comme suit:

template <typename R, typename ... Args>
R getRetType (R(*)(Args...));

et en utilisant decltype()?

using ReturnTypeOfFoo = decltype( getRetType(&foo) );

Observez que getRetType() est uniquement déclaré et non défini car il est appelé uniquement un decltype(), de sorte que seul le type renvoyé est pertinent.

15
max66