2017-06-29 9 views
2

.*演算子を逆にすることを検討しています。オブジェクトとそのメンバーのアドレスからメンバへのポインタを取得する

私はポインタを持っているときに*と逆参照することができますし、逆参照された値から&オペレータによってポインタに戻ります。

メンバーへのポインタを使用すると、.*演算子(オブジェクトインスタンスを提供する)で逆参照できますが、オブジェクトから元のポインタへのポインタとその逆参照フィールドを取得する演算子はありません。

は、次のようなデータ構造を考えてみましょう:

struct Point { double x, y, z; }; 

今、私はそれdouble &Point&オブジェクトのフィールドである(Point&, double&)ペア、からメンバーdouble Point::*へのポインタを取得する必要があります。私は以下のように与えられたデータ型のために手でそれを書くことができ

template<typename DataType, typename Member> 
constexpr Member DataType::* obtain_member_ptr(const DataType &that, const Member &fieldInThat); 

int main(int, char*[]) { 
    Point pt; 
    static_assert(obtain_member_ptr(pt, pt.x) == &Point::x, "error"); 
    static_assert(obtain_member_ptr(pt, pt.y) == &Point::y, "error"); 
    static_assert(obtain_member_ptr(pt, pt.z) == &Point::z, "error"); 
} 

::私はto_member_ptrような機能を必要と言い換える

constexpr double Point::* obtain_member_ptr(const Point &that, const double &fieldInThat)  { 
    if(&that.x == &fieldInThat) return &Point::x; 
    if(&that.y == &fieldInThat) return &Point::y; 
    if(&that.z == &fieldInThat) return &Point::z; 
    return nullptr; 
} 

しかし、それは、プレーン定型と私のように思えますコンパイラが私のためにそれをする方法があるはずだと感じる。

オブジェクトとそのフィールドからオブジェクトへのポインタを移植する方法はありますか?

+3

を? [XY問題](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)を追跡していますか? –

+3

静的でないクラス*メンバー変数へのポインタは使用できません。 '&Point :: x'は存在しないので単に有効ではありません。クラス変数([offsetofマクロ](http://en.cppreference.com/w/cpp/types/offsetof)参照)からメンバー変数に* offset *を得ることはできますが、オブジェクトを必要とする非静的メンバ変数、クラスのインスタンス –

+0

[シングルトンパターン](https://sourcemaking.com/design_patterns/singleton)と似ています。 – Drise

答えて

3

visit_structを使用して、あなたが最初の反射を追加する可能性があります。

struct Point { double x, y, z; }; 

VISITABLE_STRUCT(Point, x, y, z); 

次に、あなたの構造体を参照してください:あなたがそれを必要としない何のため

template <typename C, typename T> 
struct MemberPtrGetter 
{ 
    constexpr MemberPtrGetter(const C& c, const T& field) : c(c), field(field) {} 

    // Correct type, check reference. 
    constexpr void operator() (const char* name, T C::*member) const 
    { 
     if (&(c.*member) == &field) 
     { 
      res = member; 
     } 
    } 

    // other field type -> ignore 
    template <typename U> constexpr void operator() (const char* , U C::*member) const {} 

    const C& c; 
    const Member& field; 
    Member C::* res = nullptr; 
}; 


template<typename C, typename T> 
constexpr T C::* obtain_member_ptr(const C& c, const T& field) 
{ 
    MemberPtrGetter<C, T> visitor{c, field}; 
    visit_struct::apply_visitor<C>(visitor); 
    return visitor.res; 
} 
関連する問題