有没有办法确定成员函数指针的返回类型?
代码示例:
///// 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
也可以)。
您可以使用部分模板特化来确定
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;
}
您可以编写一个函数来推导成员函数指针的类型,并返回推导的返回类型。注意,只需要声明,不需要定义
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;
这是一个演示
这是我想出的方法,它似乎适用于大多数情况。
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);