2012-05-04 16 views
5

consideri il seguente esempio:Come arrivare membro struct con una stringa utilizzando le macro C++

struct MyStruct { 
    int a; 
    int b; 
}; 

posso usare le macro per impostare un membro da un'istanza della struct in questo modo:

#define setVar(x,y) instance.x = y 

poi in ogni funzione di quello che posso dire:

setVar(a, 4) 

come posso inviare una come una stringa alla macro? È anche possibile?

setVar("a", 4) 

MODIFICA: ci sono un sacco di strutture predefinite con membri tutti di tipo doppio. So solo quale struct sto usando da un file di configurazione XML che viene passato. Dopo l'analisi, ho un gruppo di stringhe che sono un elenco di tutti i dati membri e valori che devono essere impostati. Ho bisogno di usare questa lista per impostare i valori per ciascuno dei membri nella struttura.

+7

perché si vuole utilizzare le macro di questo tipo? – crashmstr

+1

Vuoi a livello di programmazione in runtime costruire nomi di campi? Questo è impossibile. – liori

+0

No, ci sono un sacco di strutture predefinite di cui ho bisogno per accedere ai dati e posso accedervi solo usando un file xml con un elenco delle sue variabili. c'è un altro modo per fare ciò? Inoltre, x sarà sempre di tipo double – ulu5

risposta

6

è possibile solo se si definisce lo struct stesso utilizzando alcune macro, ad esempio:

#define MY_STRUCT_STRUCTURE FIELD(a) FIELD(b) FIELD(d) FIELD(e) FIELD(f) 

struct MyStruct { 

# define FIELD(name) int name; 
    MY_STRUCT_STRUCTURE 
# undef FIELD 

    bool setVar(char* fieldname, int val) 
    { 
# define FIELD(name) if(strcmp(#name,fieldname)==0){name=val; return true;}; 
    MY_STRUCT_STRUCTURE 
# undef FIELD 
    return false; // name not found 
    } 
}; 


int main() 
{ 
    MyStruct s; 
    s.setVar("a",1); 
    s.setVar("b",2); 
    s.setVar("f",100); 
} 
+2

Suppongo che funzioni, ma, gli occhialini, non nascondono l'orrore! Aarrrggghhhh. – Skizz

+0

Abbastanza giusto. Questo è fondamentalmente ciò che ho sentito, ma alcune persone mi hanno detto che potevo farlo con le macro usando la stringificazione e qualche altro trucco. Io proprio non vedo come. – ulu5

0

ho codificato un certo codice rapido e sporco, ma potrebbe darvi qualche idea, la speranza che aiuta. Il trucco principale qui è usare anche i sindacati.

struct MyStruct 
{ 
int a; 
double b; 

MyStruct() 
    : a(0), b(0) {} 
}; 

MyStruct instance; 

union value 
{ 
    long value_a; 
    double value_d; 
} myvalue; 


void blah_a(value v) 
{ 
    instance.a = v.value_a; 
} 

void blah_b(value v) 
{ 
    instance.b = v.value_d; 
} 

struct 
{ 
    (void)(*fn)(value); 
    const char* key; 
} 

lookup_table[] = 
{ 
    { &blah_a, "a" }, 
    { &blah_b, "b" } 
}; 

void setVar(const char* c, value v) 
{ 
    for (int i = 0; lookup_table[i].fn; i++) 
      if (c == lookup_table[i].key) 
       (*(lookup_table[i].fn))(v); 
} 

int main(int argc, char* argv[]) 
{ 
    value v; 
    v.value_a = 6; 
    setVar("a", v); 
    return 0; 
} 
0

potrebbe non essere quello che stai cercando, ma una soluzione alternativa alle macro ecc .. sarebbe solo un po 'di incapsulamento e progettazione OO. Puoi cambiare la classe Field in un template in un secondo momento e sarai in grado di rappresentare qualsiasi cosa in pratica.

È possibile creare una classe

class Field 
{ 
public: 
    Field(const std::string& name, const std::string& type); 
    virtual ~Field(void); 
    std::string toString() const; 
    std::string getName() const; 
    int getValue() const { return value }; 
private: 
    std::string name; 
    std::string type; 
    int value; 
}; 

E poi una classe struttura

#pragma once 
#include <boost/ptr_container/ptr_deque.hpp> 
#include <string> 

class Field; 

class MyStructure 
{ 
public: 
    typedef boost::ptr_deque<Field> FieldList; 
    typedef FieldList::iterator FieldListIter; 
    typedef FieldList::auto_type AutoField; 

    MyStructure(void); 
    MyStructure(const std::string& name); 
    virtual ~MyStructure(void); 

    void setName(const std::string& name); 
    std::string getName() const; 
    void addField(std::auto_ptr<Field> field); 
    std::string getFieldValue(const std::string& name) const; 
    MyStructure::AutoField removeField(const std::string& name); 
    std::string toString(void) const; 

private: 
    std::string struct_name; 
    FieldList fields; 
}; 

E poi usarlo:

auto_ptr<MySructure> struct_a(new MySructure("StructName1",0)); 
struct_a->addField(auto_ptr<Field> (new Field("Field1", 1))); 
struct_a->addField(auto_ptr<Field> (new Field(var_str1, 2))); 
struct_a->addField(auto_ptr<Field> (new Field(getName(), getVal()))); 
Problemi correlati