Самый простой способ определения возвращаемого типа функции
Учитывая очень простую, но длительную функцию, такую как:
int foo(int a, int b, int c, int d) {
return 1;
}
// using ReturnTypeOfFoo = ???
Каков самый простой и сжатый способ определения возвращаемого типа функции (ReturnTypeOfFoo
, в этом примере: int
) во время компиляции без повторения типов параметров функции (только по имени, поскольку известно, что функция не имеет никаких дополнительных перегрузок )?
Ответы
Ответ 1
Здесь вы можете использовать std::function
, который даст вам псевдоним для типа возвращаемого значения функции. Для этого требуется поддержка С++ 17, поскольку он опирается на вычет аргументов шаблона класса, но он будет работать с любым вызываемым типом:
using ReturnTypeOfFoo = decltype(std::function{foo})::result_type;
Мы можем сделать это немного более общим, как
template<typename Callable>
using return_type_of_t =
typename decltype(std::function{std::declval<Callable>()})::result_type;
который затем позволяет использовать его как
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)>;
Ответ 2
Наиболее простым и лаконичным является, вероятно, следующее:
template <typename R, typename... Args>
R return_type_of(R(*)(Args...));
using ReturnTypeOfFoo = decltype(return_type_of(foo));
Обратите внимание, что это не будет работать для объектов функций или указателей на функции-члены. Просто функции, которые не перегружены или шаблоны, или noexcept
.
Но это может быть расширено для поддержки всех этих случаев, если это необходимо, путем добавления дополнительных перегрузок return_type_of
.
Ответ 3
Я не знаю, является ли самый простой способ (если вы можете использовать С++ 17, это, безусловно, не так: см. Ответ NathanOliver), но... как насчет объявления функции следующим образом:
template <typename R, typename ... Args>
R getRetType (R(*)(Args...));
и с помощью decltype()
?
using ReturnTypeOfFoo = decltype( getRetType(&foo) );
Обратите внимание, что getRetType()
объявлен и не определен, потому что вызывается только decltype()
, поэтому релевант только возвращаемый тип.