推导函数指针返回类型

问题描述 投票:0回答:2

我认为代码会更好地说明我的需求:

template <typename F>
struct return_type
{
  typedef ??? type;
};

这样:

return_type<int(*)()>::type -> int
return_type<void(*)(int,int)>::type -> void

我知道

decltype
result_of
但他们需要通过参数。我想从单个模板参数推断函数指针的返回类型。我无法将返回类型添加为参数,因为这正是我想在此处隐藏的内容...

我知道boost中有一个解决方案,但我无法使用它,并且尝试从boost中挖掘它导致了巨大的失败(就像经常发生的那样)。

欢迎使用 C++11 解决方案(只要 VS2012 支持)。

c++ c++11 function-pointers
2个回答
14
投票

如果您可以使用可变参数模板(12 年 11 月 CTP),这应该可以工作:

template <class F>
struct return_type;

template <class R, class... A>
struct return_type<R (*)(A...)>
{
  typedef R type;
};

实例.

如果您无法使用可变参数模板,则必须为 0、1、2、... 参数提供特定的专业化(手动或预处理器生成)。

编辑

正如评论中所指出的,如果您还想使用可变参数函数,则必须添加一个额外的部分专业化(或者在无可变参数模板情况下为每个参数计数一个):

template <class R, class... A>
struct return_type<R (*)(A..., ...)>
{
  typedef R type;
};

1
投票

提问已经有一段时间了。对于 C++17,有一个有趣的选项(使用关键字 auto)。然而,语法与最初要求的有点不同,但结果(类型)是相同的。

首先,我们需要一个辅助函数。正如您在此处看到的,该函数接受一个函数指针并返回一个 R 类型的对象。我们仅在 decltype 语句中需要它,因此该函数永远不会被调用,因此前向声明就足够了。

template<typename R, typename... ARGS>
static R return_type(R (*)(ARGS...));  // forward declaration only for decltype

技巧是提供函数指针作为模板自动参数,该参数被转发到 decltype 语句:

template<auto FUNCTION_POINTER>
using ReturnType = decltype(return_type(FUNCTION_POINTER));

现在很容易获取返回类型了:

#include <iostream>
#include <type_traits>

template<typename R, typename... ARGS>
static R return_type(R (*)(ARGS...));  // forward declaration only for decltype

template<typename R, typename... ARGS>
static R return_type(R (*)(ARGS..., ...));  // overloaded variant for functions with C-ellipsis

template<auto FUNCTION_POINTER>
using ReturnType = decltype(return_type(FUNCTION_POINTER));

int func1(char c, int i, long l);  // also here only forward declarations needed
void func2(unsigned u, float f);
double func3(bool b);
bool func4(int, ...);

int main()
{
    std::cout << std::is_same_v<int, ReturnType<func1>> << std::endl;
    std::cout << std::is_same_v<void, ReturnType<func2>> << std::endl;
    std::cout << std::is_same_v<double, ReturnType<func3>> << std::endl;
    std::cout << std::is_same_v<void, ReturnType<func1>> << std::endl;
    std::cout << std::is_same_v<void, ReturnType<func4>> << std::endl;
    std::cout << std::is_same_v<bool, ReturnType<func4>> << std::endl;
}

您可以在 Wandbox 中尝试完整的示例: https://wandbox.org/permlink/sKemxB44dgAVDlP6

示例中的更新:C 省略函数的重载助手。我将其用于多个 glibc 库函数。

© www.soinside.com 2019 - 2024. All rights reserved.