2017-06-29 18 views
2

的对象的地址和获得一个指针到构件我想找扭转.*运算符。从其构件

当我有一个指针,我可以取消对它的引用与*,然后从提领值回到指针由&操作。

指针指向成员我可以使用.*运算符(提供对象实例)对它进行解引用,但没有操作符可从对象及其取消引用的字段获取原始指针成员。

考虑以下的数据结构:

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

现在我需要从(Point&, double&)对,其中该double &Point&对象的字段得到一个指向构件double Point::*

换句话说,我需要一个函数to_member_ptr这样的:

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

我可以手工编写它下面给出的数据类型:

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))得到一个*偏移*到成员变量,但是得到一个地址一个非静态成员变量,你需要一个对象,一个类的实例。 –

+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; 
}