如何获取成员函数指针的返回类型

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

有没有办法确定成员函数指针的返回类型?

代码示例:

///// my library
void my_func(auto mptr) { // have to use `auto`
  // some logic based on a return type of mptr: int, string, A, etc.
}

///// client code
struct A {
  int foo();
  std::string bar(int);
};

class B{
public:
  A func(int, double);
};
// ... and many other classes

my_func(&A::foo);
my_func(&A::bar);
my_func(&B::func);
// ... many other calls of my_func()

我需要“填写”

my_func()

编辑: 我无法使用

std::result_of
/
std::invoke_result
,因为我不知道
mptr
的完整参数列表。使用哪个参数来调用方法并不重要,因为我没有调用它。我想避免创建
mptr
基类的对象,即使我能够确定它(使用
declval
也可以)。

c++ type-traits pointer-to-member decltype
3个回答
6
投票

您可以使用部分模板特化来确定

mptr
的返回类型:

template <typename T>
struct ReturnType;

template <typename Object, typename Return, typename... Args>
struct ReturnType<Return (Object::*)(Args...)>
{
    using Type = Return;
};

void my_func(auto mptr) {
  typename ReturnType<decltype(mptr)>::Type obj;
}

现场演示


1
投票

您可以编写一个函数来推导成员函数指针的类型,并返回推导的返回类型。注意,只需要声明,不需要定义

template <typename C, typename Ret, typename... Args>
auto ret_type(Ret (C::*)(Args...)) -> Ret;

void my_func(auto mptr) 
{ 
  using type = decltype(ret_type(mptr));
}

在我看来,这也比专业化解决方案更容易阅读。

这是一个演示

您还可以通过添加重载来解释 cv 限定符。例如

template <typename C, typename Ret, typename... Args>
auto ret_type(Ret (C::*)(Args...) const) -> Ret;

这是一个演示


0
投票

这是我想出的方法,它似乎适用于大多数情况。

template <typename TYPE, typename FUNCPTR, typename...ARGS>
using mfunc_return_t = decltype((std::declval<TYPE>().*std::declval<FUNCPTR>())(std::declval<ARGS&>()...));

然后我在调用提供的成员函数的函数中使用它。

template <typename FUNCPTR, typename TYPE, typename...ARGS>
mfunc_return_t<TYPE, FUNCPTR, ARGS...> SafeCall(TYPE* ptr, FUNCPTR func, ARGS&...args)
{
    if (ptr != nullptr)
        return (ptr->*func)(args...);
    using ReturnType = mfunc_return_t<TYPE, FUNCPTR, ARGS...>;
    return DefaultValue<ReturnType>();
}

我有几个用于处理类型的 DefaultValue 实现,包括算术类型、指针、void 和其他默认可构造类型。

然后我可以做类似的事情

return SafeCall(pointer, &MyClass::FunctionName, arg1, arg2);
© www.soinside.com 2019 - 2024. All rights reserved.