2016-10-18 1 views
2

Ich habe meinen Kopf schon seit geraumer Zeit wurde hämmern jetzt ein Array/Vektor zu erstellen versuchen, die Verweise auf verschiedene Arten von Variablen finden Sie im Beispiel enthalten:Gibt es eine Möglichkeit, ein Array/Vektor zu erstellen, das Verweise auf verschiedene Arten von Variablen enthält?

class Validate 
{ 
private: 
    some_array/vector[]; //0 would refer to x, 1 to y, and so on.. 
    uint8_t x; 
    uint16_t y; 
    int32_t z; 
public: 
    Validate(); 
    void doSomething(uint8_t &member); 
    void doSomething(uint16_t &member); 
    void doSomething(int32_t &member); 
} 

Der springende Punkt ist, so dass ich kann mit diesem Array/Vektor leicht in einem „for-Schleife“, so etwas wie:

void Validate::doSomething(uint_8 &member) 
{ 
    //Do whatever with the variable refered to. 
} 
Validate::Validate() 
{ 
    for(int i = 0 ; i < 2 ; i++) 
     doSomething(some_array/vector[i]); 
} 

Vielleicht eine jemand hat Antwort oder vielleicht eine bessere Lösung für mich.

+1

Sie können versuchen, für Ihre Zwecke boost :: Variante zu verwenden. –

+0

Vektoren sind homogen, sie können nur eine Art von Wert enthalten. Sie könnten einige hässliche Polymorphie-Tricks machen, um das zu tun, was Sie versuchen, aber die bessere Antwort ist, dass Sie nach einem std :: tuple suchen. Wenn Sie in der Lage sein möchten, über den Container zu iterieren, müssen Sie einige boost :: fusion oder boost :: hana - esque Metafunktionen verwenden. Das alles nimmt an, dass Sie die Typen zur Kompilierungszeit bestimmen können. – RyanP

+0

Ich bin kein Experte, aber das erste, was mir in den Sinn kam, ist ein "void void" zu erschaffen. Ich weiß nicht, wie gut dieses Design ist, aber vielleicht kann das den Trick machen. – PRP

Antwort

0

Sie haben zwei Probleme. Erstens kann ein Container keine Elemente verschiedener Typen enthalten. Zweitens können Sie keine Referenzen in einem Container speichern.

Eine Möglichkeit, das erste Problem zu lösen, ist std::variant aus C++ 17 (oder boost::variant). Um das zweite Problem zu lösen Sie std::reference_wrapper verwenden:

class Validate { 
    using Uint8Ref = std::reference_wrapper<uint8_t>; 
    using Uint16Ref = std::reference_wrapper<uint16_t>; 
    using Uint32Ref = std::reference_wrapper<int32_t>; 
    using MemberType = std::variant<Uint8Ref, Uint16Ref, Uint32Ref>; 

    std::vector<MemberType> members; 
    uint8_t     x; 
    uint16_t    y; 
    int32_t     z; 

public: 
    Validate(); 
    void doSomething(uint8_t &member); 
    void doSomething(uint16_t &member); 
    void doSomething(int32_t &member); 
}; 

Validate::Validate() : members({std::ref(x), std::ref(y), std::ref(z)}) {  
    for (auto member : members) { 
     std::visit([this](auto member){this->doSomething(member);}, member); 
    } 
} 

Live demo.

Alternativ können Sie eine polymorphe Basisklasse für ein Mitglied erstellen, die Sie in einem Behälter gespeichert werden können:

class MemberType { 
public: 
virtual ~MemberType(){} 
virtual void accept(Validate& validate) = 0; 
}; 

class Validate {  
    std::array<std::unique_ptr<MemberType>, 3> members; 
    // as before... 
}; 

template<typename T> 
class MemberTypeImpl : public MemberType { 
    T& member; 
public: 
    MemberTypeImpl(T& member) : member(member){} 
    void accept(Validate& validate) override { 
    validate.doSomething(member); 
    } 
}; 

template<typename T> 
std::unique_ptr<MemberType> make_member_type(T& member) { 
    return std::make_unique<MemberTypeImpl<T>>(member); 
} 

Validate::Validate() 
    : members({make_member_type(x), make_member_type(y), make_member_type(z)}) { 
    for (auto& member : members) { 
     member->accept(*this); 
    } 
} 
+0

Ich habe es tatsächlich mit Boost-Tupel arbeiten, aber es stellte sich heraus, dass diese ganze Art des Denkens den Code viel härter macht, als es sein muss, die ursprüngliche Aufgabe bestand darin, hex von einer Zeichenkette zu entschlüsseln und ein paar der Werte daraus zu erhalten , das war eine völlig unnötige Art, es zu tun, wenn ich buchstäblich nur von einem substr() lesen kann. – Tomzter

+0

Vielen Dank für die Hilfe und Entschuldigung für die Verschwendung Ihrer Zeit. – Tomzter

+0

@Tomzter Kein Problem, ich habe über die Tupel-Lösung nachgedacht, aber die Wiederholung von Tupeln ist ein bisschen mühsam. –

Verwandte Themen