2012-05-04 16 views
5

Rozważmy następujący przykład:Jak zdobyć elementu struct z ciągiem przy pomocy makr C++

struct MyStruct { 
    int a; 
    int b; 
}; 

mogę korzystać z makr, aby ustawić element z instancji struct robiąc to:

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

następnie w dowolnej funkcji mogę powiedzieć:

setVar(a, 4) 

jak mogę wysłać je w postaci ciągu do makra? Czy to też jest możliwe?

setVar("a", 4) 

EDYCJA: Istnieje kilka predefiniowanych struktur z członami, które są typu podwójnego. Wiem tylko, jakiej struktury używam przez plik konfiguracyjny XML, który jest przekazywany. Po przeanalizowaniu mam pęczek ciągów, które są listą wszystkich elementów danych i wartości, które należy ustawić. Potrzebuję użyć tej listy, aby ustawić wartości dla każdego członka w strukturze.

+7

Dlaczego chcesz korzystać z makr w ten sposób? – crashmstr

+1

Czy chcesz programowo w czasie wykonywania skonstruować nazwy pól? To jest niemożliwe. – liori

+0

Nie, istnieje garstka predefiniowanych struktur, do których potrzebuję uzyskać dostęp do danych i mogę uzyskać do nich dostęp tylko za pomocą pliku xml z listą jego zmiennych. Czy jest inny sposób na zrobienie tego? Również x będzie zawsze typu podwójnie – ulu5

Odpowiedz

6

Jest to możliwe tylko wtedy, gdy zdefiniowanie samego struct przy użyciu jakiegoś makro, na przykład:

#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

Przypuszczam, że działa, ale, gogle, nie ukrywają ohydą! Aarrrggghhhh. – Skizz

+0

Wystarczająco fair. Zasadniczo to, co słyszałem, ale kilka osób powiedziało mi, że mogę to zrobić za pomocą makr, stosując szykowanie i kilka innych sztuczek. Po prostu nie rozumiem. – ulu5

0

mam zakodowane niektóre szybkie i zabrudzony kodu, ale może dać Ci kilka pomysłów, nadzieję, że pomoże. Główną lewą stroną są tu również związki zawodowe.

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

Może nie być to, czego szukasz, ale alternatywne rozwiązanie do makra itp .. będzie tylko niektóre enkapsulacji i OO projekt. Możesz później zmienić klasę Field na szablon, a będziesz mógł w zasadzie reprezentować wszystko.

Można utworzyć klasę

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

a następnie klasę struktura

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

A potem z niego korzystać:

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()))); 
Powiązane problemy