【问题标题】:Deducing a function pointer return type推导函数指针返回类型
【发布时间】:2023-02-04 10:59:31
【问题描述】:

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

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

以便:

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

我知道 decltyperesult_of 但他们需要传递参数。我想从单个模板参数中推断出函数指针的返回类型。我不能将返回类型添加为参数,因为这正是我想在这里隐藏的内容......

我知道在 boost 中有一个解决方案,但我不能使用它,并且试图从 boost 中挖掘它导致了一个惊人的失败(正如它经常发生的那样)。

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

【问题讨论】:

  • 在编写函数绑定器时,需要区别对待“void”返回类型,因此我有一个专门针对void 的模板。要使用它,我需要返回类型,而且我不想再次重新输入所有参数计数。

标签: c++ c++11 function-pointers


【解决方案1】:

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

template <class F>
struct return_type;

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

Live example

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

编辑

正如在 cmets 中指出的那样,如果您还想使用可变参数函数,则必须添加一个额外的偏特化(或者在无可变参数模板的情况下为每个参数计数添加一个):

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

【讨论】:

  • 我不会使用 CTP,我希望我能以某种方式避免自己编写所有这些类型的痛苦。我不敢相信没有标准的解决方案......
  • @KornelKisielewicz:如果您在 boost 中查看 function_traits.hpp,它会完全按照答案中的内容进行操作,但会全部写出来。您可以从那里复制并粘贴。
  • 正式地,给定该模板适用的 N 函数类型,这会遗漏 (3 * N) * (2 * N) * N 您的模板不适用于的其他函数类型。例如,给定void(),您的模板不适用于void()constvoid() volatilevoid() const volatilevoid(...)void(...)const、...、void() &amp;void()&amp;&amp;、... , void(...)const volatile&amp;&amp; 等等。
  • @JohannesSchaub-litb 如何创建指向函数的指针 (不是指向成员函数的指针)可以指向 const-qualified 或 ref-qualified 函数?
  • @Angew 好的,这是一个好点:)所以你只会错过N函数类型:)
【解决方案2】:

自问这个问题以来已经有一段时间了。对于 C++17,有一个有趣的选项。但是,语法与最初要求的有点不同,但结果(类型)是相同的。

首先,我们需要一个辅助函数。正如您在此处看到的,该函数接受一个函数指针并返回一个 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<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);

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;
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-04
    • 1970-01-01
    • 2021-06-22
    • 1970-01-01
    • 2021-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多