考虑一个非常简单但冗长的函数,例如:
int foo(int a, int b, int c, int d) {
return 1;
}
// using ReturnTypeOfFoo = ???
如何在编译时最简单、最简洁地确定函数的返回类型(在此示例中为int
,名称为ReturnTypeOfFoo
),而不需要重复函数的参数类型(仅通过名称,因为已知该函数没有任何其他重载)?
考虑一个非常简单但冗长的函数,例如:
int foo(int a, int b, int c, int d) {
return 1;
}
// using ReturnTypeOfFoo = ???
如何在编译时最简单、最简洁地确定函数的返回类型(在此示例中为int
,名称为ReturnTypeOfFoo
),而不需要重复函数的参数类型(仅通过名称,因为已知该函数没有任何其他重载)?
在这里,您可以利用std::function
,它将为函数返回类型提供一个别名。这需要C++17支持,因为它依赖于class template argument deduction,但它将适用于任何可调用类型:
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)>;
这种技术只适用于函数没有被重载或者函数没有被定义多个operator()
的情况下。
using ReturnType = std::invoke_result_t<decltype(foo)>;
意思是:定义一个名为ReturnType的类型别名,它使用std::invoke_result_t模板来获取调用foo函数后的返回值类型。 - tjklemz最简单和简明的可能是:
template <typename R, typename... Args>
R return_type_of(R(*)(Args...));
using ReturnTypeOfFoo = decltype(return_type_of(foo));
请注意,这对于函数对象或成员函数指针不起作用。仅适用于未经过载或模板化的函数或noexcept
函数。
但是,如果需要支持所有这些情况,可以通过添加更多的return_type_of
重载来实现。
我不知道是否这是最简单的方法(如果你可以使用C++17,肯定不是:参见NathanOliver的答案),但是... 声明一个函数如下:
template <typename R, typename ... Args>
R getRetType (R(*)(Args...));
而且使用 decltype()
?
using ReturnTypeOfFoo = decltype( getRetType(&foo) );
注意,getRetType()
只被声明而不被定义,因为它只在decltype()
中被调用,因此只有返回的类型是相关的。
#include "TypeTraits.h"
using namespace StdExt; // Everything's in this namespace
using ReturnTypeOfFoo = ReturnType_t<decltype(foo)>;
decltype(foo)::result_type
? - Thomas Langdecltype(foo)
是一个没有result_type
成员的函数,还是我漏掉了什么? - 463035818_is_not_a_numberstd::function
类型的result_type
成员。 - Thomas Lang