2012-05-04 9 views
5

Considere el siguiente ejemplo:Como llegar miembro de la estructura con una cadena usando macros C++

struct MyStruct { 
    int a; 
    int b; 
}; 

puedo usar macros para establecer un miembro de una instancia de la estructura al hacer esto:

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

continuación, en cualquier función que puedo decir:

setVar(a, 4) 

¿Cómo puedo enviar en una forma de cadena a la macro? ¿Eso también es posible?

setVar("a", 4) 

EDIT: Hay un montón de estructuras predefinidas con miembros que son todos de tipo double. Solo sé qué estructura estoy utilizando mediante un archivo de configuración XML que se transfiere. Después del análisis, tengo un conjunto de cadenas que son una lista de todos los miembros de datos y valores que deben establecerse. Necesito usar esta lista para establecer valores para cada uno de los miembros en la estructura.

+7

por qué le gustaría utilizar macros de este tipo? – crashmstr

+1

¿Desea programar mediante programación nombres de campos de tiempo de ejecución? Esto es imposible. – liori

+0

No, hay un montón de estructuras predefinidas a las que necesito acceder y solo puedo acceder utilizando un archivo xml con una lista de sus variables. Hay otra manera de hacer esto? Además, x siempre será del tipo double – ulu5

Respuesta

6

sólo es posible si se define la estructura en sí el uso de algunos macro, por ejemplo:

#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

Supongo que funciona, pero, las gafas, ¡no ocultan el horror! Aarrrggghhhh. – Skizz

+0

Bastante justo. Eso es básicamente lo que he escuchado, pero algunas personas me dijeron que podía hacerlo con macros usando stringification y algunos otros trucos. Simplemente no veo cómo. – ulu5

0

he codificado un código rápido y sucio, pero podría darle algunas ideas, espero que ayude. El truco principal aquí es usar uniones.

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

no podría ser lo que está buscando, pero una solución alternativa a las macros, etc .. no sería más que un poco de encapsulación y diseño orientado a objetos. Puede cambiar la clase Campo a una plantilla más adelante y podrá representar cualquier cosa básicamente.

Puede crear una clase

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; 
}; 

Y a continuación, una clase de estructura

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

Y luego utilizarlo:

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()))); 
Cuestiones relacionadas