簡體   English   中英

我如何從其地址獲取成員函數的組成部分?

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

是否可以僅從其地址(而不是從成員函數類型)獲取成員函數的組成,例如類類型或返回類型?

對於例如給定

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

我喜歡

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

我還另外知道,成員函數具有類似R (C::*)()的簽名,即沒有參數且沒有cv限定。

謝謝。

您可以在模板函數中捕獲類型:

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

打印“ OK”,因此您可以將is_same支票放入其中。 我真的不知道問題是什么,但-顯然,我們這里使用模板參數推導的成員函數的類型。

如果你已經在某種程度上被無效reinterpret_cast一個成員函數指針到別的東西,從而放棄它的類型,那么沒有你不能恢復。

如果您已將成員函數指針轉換為兼容的成員函數指針類型,例如R (B::*)() -> R (D::*)() ,其中B是D的基類,則我認為您畢竟可以使用dynamic_cast來測試它是否真的是B函數。 您不能以這種方式恢復類型,只能恢復成員函數指針的typeid ,因為它是運行時操作。 類型實際上僅在C ++中存在,因此無法“獲取”值的動態類型,無論該值是成員函數指針還是其他任何值。 編譯器要么知道,要么不知道,如果知道,則存在各種模板技巧來實際使用該類型的成分。

不。 這是所謂的運行時反射的一部分,在像C ++這樣的低級語言中是不可能的。 您不能僅從地址獲得此數據。

無論您在做什么,在C ++中,您都可以使用模板魔術或預處理魔術來通過元編程方法來做到這一點。 例如,Boost庫依賴於這種方法。

在C ++ pre-0x中,您很難做到這一點。 在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;

然后根據需要擴展上述范圍。

您可以使用重載:

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


F(foo.bar());

您可以使用模板函數和部分專業化的解決方案。

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
}

如果出於某種原因要以簡單的類型傳遞成員函數指針,則可以使用以下內容獲取組成部分。 (這需要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