开发者

Bind members of different classes

In a C++ program I have two classes (structs) like

struct A
{
    int x;
    double y;
    // other members
};

struct B
{
    int x;
    double y2;
    // other members
};

I'd like to somehow "bind" the corresponding members, e.g. A::x to B::x and A::y to B::y2. By "bind" I mean ability to obtain a reference to the bound variable, for example given a member of class A I could assign it to the value of the corresponding B member.

Once I have such bind, I'd like to build a bind table or something similar which I could iterate over. This would allow, for example, copying the corresponding fields from A a; to B b; like CopyBound(a, b, bind_table);, but probably also doing some other things not limited to Copy interface.

The problem with this bind_table is that I want static typing and the bind_table would have to contain different typ开发者_如何学Goes in this case. For example, a table of pointers to class members would contain &A::x and &A::y, but they are of different type, so I cannot just put them say into an array.

Any ideas how this can be conveniently implemented, having as much compile-time type checking as possible?


Perhaps you want some template metaprogramming along the lines of this:

#include <iostream>

// An item in the list of bound members
template<typename Class, typename T, T Class::*Ptr, typename Next = void> struct m
{
    typedef Class containing_type;
    typedef T value_type;
    typedef Next next;
    static T Class::*pointer;
};
template<typename Class, typename T, T Class::*Ptr, typename Next>
    T Class::* m<Class, T, Ptr, Next>::pointer = Ptr;

// Iterator for the member list
template<typename Item1, typename Item2> struct apply_helper
{
    typedef typename Item1::containing_type A;
    typedef typename Item2::containing_type B;

    template<typename Op>
    static void apply(A& a, B& b, Op op)
    {
        op(a.*Item1::pointer, b.*Item2::pointer);
        apply_helper<typename Item1::next, typename Item2::next>::apply(a, b, op);
    }
};

template<typename Item1> struct apply_helper<Item1, void>
{
    // An error referencing this means you forgot a member in the list
};
template<typename Item2> struct apply_helper<void, Item2>
{
    // An error referencing this means you forgot a member in the list
};
template<> struct apply_helper<void, void>
{
        template<typename A, typename B, typename Op>
        static void apply(A& a, B& b, Op op) {}
};


// This function initiates the enumeration of the members
template<typename A, typename B, typename Op> void apply(A& a, B& b, Op op)
{
    apply_helper<typename A::members, typename B::members>::apply(a, b, op);
}


// EXAMPLE

struct MyA
{
    int v1;
    double v2;
    typedef m<MyA, int, &MyA::v1,
            m<MyA, double, &MyA::v2> > members;
};

struct MyB
{
    int v1;
    double v2;
    typedef m<MyB, int, &MyB::v1,
            m<MyB, double, &MyB::v2> > members;
};

// A functor which demonstrates printing the value before copying    
struct CopyAnyValue
{
    template<typename T> void operator()(T& t1, T& t2)
    {
        std::cout << "t1 = " << t1 << std::endl;
        t2 = t1;
    }
};

int main()
{
    MyA a;
    MyB b;

    a.v1 = 3;
    a.v2 = 5.5;

    apply(a, b, CopyAnyValue());

    std::cout << "v1: " << b.v1 << "  v2: " << b.v2 << std::endl;

    return 0;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜