简体   繁体   中英

Use a variable to determine struct member

In my code I'm using multiple structs of the following structure:

struct Track {
    string artist;                      
    string cd;                          
    // etc....  
};

The structs can be referred to as: Track1, Track2, etc.
I'm trying to make a function that uses a variable to determine which member it should output.
For example:

string x ="cd"                                
cout << Track1.x << endl;

I can't really figure out how to do this... I keep getting the error that 'x' is not a member of the Struct.

Thanks for taking time to read this, I hope you can help me out.

C++ is not a scripting language, so you can't do "variable variables" like that.

The usual way to do this is to use a map instead:

std::map<std::string, std::string> myValues;

Then the following are the same:

std::cout << myValues["cd"] << std::endl;

and

std::string x = "cd";
std::cout << myValues[x] << std::endl;

However, I question your design. It seems like a track has a fixed number of properties so individual members make sense, rather than a map to which elements may be added and removed. You could restrict access to the map and write code that ensures it has all the track properties stored within it (and nothing else) at all times.

But I suggest revisiting the need for "variable variables" here in the first place. Passing a string into a function to determine its semantics doesn't seem particularly efficient, robust or resilient. Why not return a reference to the entire Track object, then the caller can examine any property they want?

std::cout << getTrack(arguments...).cd << std::endl;

It is not possible to specify a class member by a run-time name. The only immediate language feature that allows one to specify a class member by a run-time value (ie as you put it "use a variable to determine struct member") is pointers of "pointer-to-member" type

Track track1 = { "Some Artist", "Some CD" };
Track track2 = { "Some Other Artist", "Some Other CD" };

std::string Track::*member = &Track::cd; // pointer-to-member points to 'cd' member
std::cout << track1.*member << std::endl;
std::cout << track2.*member << std::endl;

member = &Track::artist; // pointer-to-member points to 'artist' member
std::cout << track1.*member << std::endl;
std::cout << track2.*member << std::endl;

Now, if you want to be able to select a specific member using a string containing its name (as in your original post), you have no other choice but to implement the name-to-member mapping manually. You can use the aforementioned pointer-to-members to build such mapping

std::map<std::string, std::string Track::*> mapping = {
  { "artist", &Track::artist },
  { "cd", &Track::cd }
};

std::string Track::*member = mapping["cd"];
std::cout << track1.*member << std::endl;
std::cout << track2.*member << std::endl;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM