wake-up-neo.com

Einfachste Methode zur Bestimmung des Rückgabetyps der Funktion

Angesichts einer sehr einfachen, aber langwierigen Funktion wie:

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

// using ReturnTypeOfFoo = ???

Was ist die einfachste und übersichtlichste Methode, um den Rückgabetyp der Funktion (ReturnTypeOfFoo, in diesem Beispiel: int) zur Kompilierungszeit zu bestimmen ohne die Parametertypen der Funktion zu wiederholen ( nur mit dem Namen, da bekannt ist, dass die Funktion keine zusätzlichen Überladungen aufweist)?

47
Cybran

Sie können std::function Hier wird ein typedef für den Rückgabetyp der Funktionen angegeben. Dies erfordert C++ 17-Unterstützung, da es sich auf Argumentabzug für Klassenvorlagen stützt, aber es funktioniert mit jedem aufrufbaren Typ:

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

Wir können das etwas allgemeiner gestalten

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

mit dem kannst du es dann gerne benutzen

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

Am einfachsten und prägnantesten ist wahrscheinlich:

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

using ReturnTypeOfFoo = decltype(return_type_of(foo));

Beachten Sie, dass dies für Funktionsobjekte oder Zeiger auf Mitgliedsfunktionen nicht funktioniert. Nur Funktionen, die nicht überladen sind oder Vorlagen oder noexcept.

Dies kann jedoch erweitert werden, um alle diese Fälle zu unterstützen, wenn dies gewünscht wird, indem weitere Überladungen von return_type_of Hinzugefügt werden.

22
Barry

Ich weiß nicht, ob dies der einfachste Weg ist (wenn Sie C++ 17 verwenden können, ist dies sicherlich nicht der Fall: siehe NathanOlivers Antwort), aber ... wie wäre es, wenn Sie eine Funktion wie folgt deklarieren:

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

und mit decltype()?

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

Beachten Sie, dass getRetType() nur deklariert und nicht definiert wird, weil nur eine decltype() aufgerufen wird, sodass nur der zurückgegebene Typ relevant ist.

15
max66