【问题标题】:How get the class (object type) from pointer to method如何从指向方法的指针获取类(对象类型)
【发布时间】:2017-06-29 17:46:47
【问题描述】:

我有一个指向方法的指针:

struct A { int method() { return 0; } };
auto fn = &A::method;

我可以通过 std::result_of 获得返回类型,但是我如何从 fn 获得方法的类所有者?

【问题讨论】:

  • 你不能,标准中没有这样的特征。编译器会知道它,所以它应该是可能的,但根本没有办法获得这些信息。
  • 模板 ClassType foo(ReturnType (ClassType::*)(Args...));应该工作
  • @felix 你应该把它写成答案。
  • 在我的手机上编辑。很难提供一个格式良好的答案.. : |
  • this question相关p0172r0 paper;它提到了一种从指向成员函数的指针中拆分类类型的奇怪方法。

标签: c++ c++14 metaprogramming


【解决方案1】:

试试这个:

template<class T>
struct MethodInfo;

template<class C, class R, class... A>
struct MethodInfo<R(C::*)(A...)> //method pointer
{
    typedef C ClassType;
    typedef R ReturnType;
    typedef std::tuple<A...> ArgsTuple;
};

template<class C, class R, class... A>
struct MethodInfo<R(C::*)(A...) const> : MethodInfo<R(C::*)(A...)> {}; //const method pointer

template<class C, class R, class... A>
struct MethodInfo<R(C::*)(A...) volatile> : MethodInfo<R(C::*)(A...)> {}; //volatile method pointer

【讨论】:

  • 您可能需要一个单独的const volatile
【解决方案2】:

您可以使用 class-template-specialization 匹配它:

//Primary template
template<typename T> struct ClassOf {};

//Thanks T.C for suggesting leaving out the funtion /^argument
template<typename Return, typename Class>
struct ClassOf<Return (Class::*)>{   using type = Class;    };

//An alias
template< typename T> using ClassOf_t = typename ClassOf<T>::type;

因此给出:

struct A { int method() { return 0; } };
auto fn = &A::method;

我们可以像这样检索类:

ClassOf_t<decltype(fn)> a;

完整示例Here

【讨论】:

  • ...或者只专注于F C::*,而不是为每种可能的函数类型提供 48 个专业化。
  • @T.C.我错过了。谢谢!!。立即编辑
【解决方案3】:

Boost callable traits answer,我更喜欢这里的简短答案,因为它对我来说更具可读性,但意见可能会有所不同...

#include<string>
#include<type_traits>
#include<tuple>
#include <boost/callable_traits/args.hpp>

struct S{
    int val=46;
    int get(){
        return val;
    }
    void method(const std::string ){
    }
};

int main(){
    using Ts1 = boost::callable_traits::args_t<decltype(&S::val)>;
    using Ts2 = boost::callable_traits::args_t<decltype(&S::get)>;
    using Ts3 = boost::callable_traits::args_t<decltype(&S::method)>;
    std::remove_cvref_t<std::tuple_element<0,Ts1>::type> s1;
    s1.val++;
    std::remove_cvref_t<std::tuple_element<0,Ts2>::type> s2;
    s2.val++;
    std::remove_cvref_t<std::tuple_element<0,Ts3>::type> s3;
    s3.val++;
}

s1s2s3都是S型。

显然你只需要执行一次逻辑,我做了 3 次以表明它对于指向成员的指针、指向带 0 个参数的函数的指针、指向带 1 个参数的函数的指针都可以正常工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-09
    • 2017-01-01
    • 2014-06-16
    • 2013-07-08
    • 1970-01-01
    • 2012-03-27
    • 2017-04-18
    • 1970-01-01
    相关资源
    最近更新 更多