2011-01-02 11 views
1

In einem C++ Programm Ich habe zwei Klassen (structs) wieBind Mitglieder verschiedener Klassen

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

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

Ich mag irgendwie zu „binden“, um die entsprechenden Elemente, z.B. A::x bis B::x und A::y bis B::y2. Mit "binden" meine ich die Fähigkeit, einen Verweis auf die gebundene Variable zu erhalten, zum Beispiel bei einem Mitglied der Klasse A könnte ich es dem Wert des entsprechenden B Mitglieds zuweisen.

Sobald ich solche Bindung habe, würde ich gerne eine Bind-Tabelle oder etwas ähnliches, das ich über iterieren könnte. Dies würde zum Beispiel das Kopieren der entsprechenden Felder von A a; zu B b; wie CopyBound(a, b, bind_table); ermöglichen, aber wahrscheinlich auch einige andere Dinge tun, die nicht auf Copy Schnittstelle beschränkt sind.

Das Problem mit dieser bind_table ist, dass ich statische Typisierung und die bind_table müsste in diesem Fall verschiedene Typen enthalten. Zum Beispiel würde eine Tabelle von Zeigern zu Klassenmitgliedern &A::x und &A::y enthalten, aber sie sind von unterschiedlichem Typ, also kann ich sie nicht einfach in ein Array setzen.

Irgendwelche Ideen, wie dies bequem implementiert werden kann, mit so viel Kompilierzeit Typprüfung wie möglich?

+0

Bitte klären, ob dieses C oder C++ zumindest ist. – Jon

+0

@ Jon: Ich spreche über C++, aber wahrscheinlich könnte auch einige C-Style-Lösung gehen –

+0

Ihre Frage ist unklar. Der bindende Teil ist einfach (wenn du meinst, was ich denke, du meinst), aber es ist nicht klar, was du willst, um den "Bindetisch" zu machen oder zu tun. Felder von 'A a' nach' B b' kopieren? Wenn 'a' und 'b' bereits gebunden sind, dann ist das Kopieren nicht notwendig, und wenn sie nicht sind, hat es nichts mit der Bindung zu tun. – Beta

Antwort

3

Vielleicht möchten Sie einige Metaprogrammierung entlang der Linien von dieser:

#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; 
} 
Verwandte Themen