简体   繁体   English

我如何从其地址获取成员函数的组成部分?

[英]How can i get constituents of a member function from its address?

Is it possible to get the constituents of a member function such as class type or return type just from its address (not from member function type) ? 是否可以仅从其地址(而不是从成员函数类型)获取成员函数的组成,例如类类型或返回类型?

For eg given 对于例如给定

 class foo
 {
    int bar()
    {
        return 5;
    }
 };

i like to have 我喜欢

is_same< function_types<&foo::bar>::class_type, foo>::value == true; 

I also know additionally that the member function has a signature like R (C::*)() ie no arguments and no cv-qualification. 我还另外知道,成员函数具有类似R (C::*)()的签名,即没有参数且没有cv限定。

Thank you. 谢谢。

You can capture the type in a template function: 您可以在模板函数中捕获类型:

#include <iostream>

struct foo {
    foo() { std::cout << "OK\n"; }
    int bar() {return 0;}
};

template<typename C, typename R>
bool thing(R (C::*)()) {
    C x;
}

int main() {
    thing(&foo::bar);
}

prints "OK", so you could put your is_same check in there. 打印“ OK”,因此您可以将is_same支票放入其中。 I'm really not sure what the question is, though - obviously here we are using the type of the member function for template argument deduction. 我真的不知道问题是什么,但-显然,我们这里使用模板参数推导的成员函数的类型。

If you've somehow invalidly reinterpret_cast a member function pointer to something else, so as to discard its type, then no you can't recover it. 如果你已经在某种程度上被无效reinterpret_cast一个成员函数指针到别的东西,从而放弃它的类型,那么没有你不能恢复。

If you've converted your member function pointer to a compatible member function pointer type, for example R (B::*)() -> R (D::*)() , where B is a base class of D, then I think you can use dynamic_cast to test whether it really is a B function after all. 如果您已将成员函数指针转换为兼容的成员函数指针类型,例如R (B::*)() -> R (D::*)() ,其中B是D的基类,则我认为您毕竟可以使用dynamic_cast来测试它是否真的是B函数。 You can't recover the type that way, just the typeid of the member function pointer, because it's a runtime operation. 您不能以这种方式恢复类型,只能恢复成员函数指针的typeid ,因为它是运行时操作。 Types really only exist at compile-time in C++, so there's no way to "get" the dynamic type of a value, whether that value is a member function pointer or anything else. 类型实际上仅在C ++中存在,因此无法“获取”值的动态类型,无论该值是成员函数指针还是其他任何值。 The compiler either knows it, or it doesn't, and if it does then there's various template trickery to actually use the constituents of that type. 编译器要么知道,要么不知道,如果知道,则存在各种模板技巧来实际使用该类型的成分。

Nope. 不。 This is part of what is called run-time reflection and is not possible in such low-level language as C++. 这是所谓的运行时反射的一部分,在像C ++这样的低级语言中是不可能的。 You cannot get this data from only the address. 您不能仅从地址获得此数据。

Whatever you're doing, in C++ you're likely to be able to do this with a metaprogramming approach, using template magic or preprocessor magic. 无论您在做什么,在C ++中,您都可以使用模板魔术或预处理魔术来通过元编程方法来做到这一点。 For example, Boost libraries rely on such approach. 例如,Boost库依赖于这种方法。

In C++ pre-0x, you can't do this very easily. 在C ++ pre-0x中,您很难做到这一点。 In C++0x, you can use a combination of template functions and decltype to do this: 在C ++ 0x中,可以结合使用模板函数和decltype来执行此操作:

template <typename R> struct unary_function_info { typedef R result_type; typedef void class_type; };
template <typename R> unary_function_info get_function_info(R (*)());

template <typename C, typename R> struct unary_member_function_info { typedef R result_type; typedef C class_type; };
template <typename C, typename R> unary_member_function_info get_function_info(R (C::*)());

is_same<decltype(get_function_info(&foo::bar))::class_type, foo>::value == true;

And then expand the above out for as high an arity as you need. 然后根据需要扩展上述范围。

You could use overloading: 您可以使用重载:

void F(int);
void F(bool);


F(foo.bar());

You can use template functions and partial specialisation for a more generic solution. 您可以使用模板函数和部分专业化的解决方案。

struct char2_t { char xxx[2]; };

template <bool flag, typename T, typename U> struct select   { typedef T type; }; 
template <typename T, typename U> struct select<false, T, U> { typedef U type; }; 

template<class Foo, class C, class R>
typename select<boost::is_same<Foo, C>::value, char, char2_t>::type test(R (C::*)());


void check_in_this_function() {
 char check_arr1[ sizeof(test<foo>(&foo::bar))==1 ? 1 : -1]; 
 char check_arr2[ sizeof(test<int>(&foo::bar))==1 ? 1 : -1];  // error: negative subscript
}

If for some reason you are passing around a member function pointer as a simple type, you can get the constituent parts with something like the following. 如果出于某种原因要以简单的类型传递成员函数指针,则可以使用以下内容获取组成部分。 (This requires C++0x, in current C++ making it support arbitrary arities would take a lot more work.) (这需要C ++ 0x,在当前的C ++中,使其支持任意Arities会花费很多工作。)

#include <tuple>

template <class T>
struct method_traits;

template <class ReturnType, class ObjectType, class... ArgTypes>
struct method_traits<ReturnType (ObjectType::*)(ArgTypes...)>
{
    typedef ReturnType result_type;
    typedef ObjectType object_type;
    template <unsigned N>
    struct argument
    {
        typedef typename std::tuple_element<N - 1, std::tuple<ArgTypes...>>::type type;
    };
};

template <class ReturnType, class ObjectType, class... ArgTypes>
struct method_traits<ReturnType (ObjectType::*)(ArgTypes...) const>
{
    typedef ReturnType result_type;
    typedef ObjectType object_type;
    template <unsigned N>
    struct argument
    {
        typedef typename std::tuple_element<N - 1, std::tuple<ArgTypes...>>::type type;
    };
};

struct Foo
{
    int bar(double, float) const ;
};

template <class MemberFun>
void test(MemberFun f)
{
    typename method_traits<MemberFun>::result_type result;
    typename method_traits<MemberFun>::object_type object;
    typename method_traits<MemberFun>::template argument<1>::type i = 10;  //:)
    result = (object.*f)(i, 2.0f);
}

int main()
{
    test(&Foo::bar);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM