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)?
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)>;
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.
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.