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;
}
精彩评论