Get attribute by name
Asked Answered
G

5

7

I have a struct definition with about 25 elements

struct X { field 1; field 2; .. };    

and I'm trying to fill it with some map values

Map<String,String> A    

and it appears to be very annoying to do such thing n times

X->xx = A["aaa"]    

every time that I want to fill my message struct.

Is it possible to access the members by name, e.g.

X->get_instance_of("xx").set(A["aaa"]);    

and put it into a loop?

Grayce answered 27/2, 2012 at 16:43 Comment(3)
Are all members of the same type?Crista
loop through what? The solution would be to set up some bindings, but it's difficult to know as you haven't given enough information.Deportation
The structure is always the same one? And.. are the fields types the same?Balbinder
C
10

C++ lacks built-in reflection capabilities of more dynamic languages, so you cannot do what you would like using he out of the box capabilities of the language.

However, if all members are of the same type, you can do it with a map of pointers to members and a little preparation:

 // typedef for the pointer-to-member
 typedef int X::*ptr_attr;

 // Declare the map of pointers to members
 map<string,ptr_attr> mattr;
 // Add pointers to individual members one by one:
 mattr["xx"] = &X::xx;
 mattr["yy"] = &X::yy;

// Now that you have an instance of x...
 X x;
// you can access its members by pointers using the syntax below:
 x.*mattr["xx"] = A["aa"];
Crista answered 27/2, 2012 at 16:50 Comment(7)
Even if they're different types, it can be done with function overloading.Cuirassier
@Nawaz Sure, but that would require an entirely different solution. Moreover, it is very likely that such solution would be more elegant than the one I proposed.Crista
Yes. One such solution is given by @Johannes Schaub here : https://mcmap.net/q/87734/-initializing-struct-using-an-arrayCuirassier
Question: &X::xx; in this line, X is not instantiated yet, but the address exist? How is this possible?Cybernetics
@starriet X is a type, so it does not go through an initialization (instances of X, such as x, go through an initialization, though). Pointer-to-member works like a glorified offset: C++ accesses mattr["xx"] for the "offset", operator .* adds it to the address of x and dereferences it, producing a reference to the corresponding member.Crista
@SergeyKalinichenko Thanks! Is .* itself a special operator, not the same as . and * combined? So, .* works something like *((&x) + mattr["xx"])?Cybernetics
@starriet Correct, member access operators .* and ->* are separate operators.Crista
B
2

Short answer: no. This is C++, a statically compiled language, where the structure member names are converted by the compiler into memory offsets. It is not dynamic like PHP or Python where the runtime is involved with all variable references.

Boelter answered 27/2, 2012 at 16:47 Comment(0)
R
1

No. C++ doesn't have reflection. Java does though. Unsurprisingly, SOA related stuff is more probably encountered with languages like Java than it is with languages like C.

Ratib answered 27/2, 2012 at 16:46 Comment(2)
Not sure that’s true. SOAP APIs in Java generate code wrappers as a compilation step. Why shouldn’t the same exist for C++? There’s no need to use reflection for that.Chinookan
It surely can be done in C++ as well, with member pointers and function overloads.Cuirassier
L
1

It's not really possible to do that; the information you need is no longer present at runtime. You might be able to do something with a map and some pointers, but to be honest you would probably be better off just wrapping it up in a function that takes a map and puts the values into the appropriate fields.

Libelant answered 27/2, 2012 at 16:46 Comment(0)
O
0

You could create a wrapper objet for your struct with set/get accessors that will let you iterate over string values for filling/reading the underlying struct that is static.

Otherwhere answered 27/2, 2012 at 16:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.