Reputation: 883
Say I have an object defined like this:
struct Something
{
int attribute1;
string attribute2;
}
I then have a File that contains a bunch of information that should be applied to a created object. However, the attribute name that it should be applied to is also stored in the file. In other words, the text file would contain two values like so:
123, "attribute1"
I need a way to reference an object's attribute by a string. Something like Something[variable_holding_attribute_name]
would be perfect!
Is there any way of doing this in C++? Please also note that I can't use a map
, as the object contains more than 1 data type.
Upvotes: 1
Views: 1420
Reputation: 595742
Just because your struct
uses different data types does not mean you cannot use a std::map
to access them, because you can. Try something like this:
struct Something
{
int attribute1;
std::string attribute2;
};
void set_attr1(Something &obj, const std::string &value)
{
std::istringstream iss(value);
iss >> obj.attribute1;
}
void set_attr2(Something &obj, const std::string &value)
{
obj.attribute2 = value;
};
typedef void (*set_func)(Something&, const std::string&);
std::map<std::string, set_func> m;
m["attribute1"] = &set_attr1;
m["attribute2"] = &set_attr2;
...
Something obj;
std::string value = ...; // "123"
std::string name = ...; // "attribute1"
m[name](obj, value);
/*
Or safer:
std::map<std::string, set_func>::iterator iter = m.find(name);
if (iter != m.end())
iter->second(obj, value);
*/
If you want something a little more flexible that allows you to re-use a given function for multiple fields of the same data type, even re-use the same functions for map
s of different struct
s, you can do this instead:
template<typename ObjType, typename MemType, MemType ObjType::*member>
void set_member(ObjType &obj, const std::string &value)
{
std::istringstream iss(value);
iss >> obj.*member;
}
template<typename ObjType, std::string ObjType::*member>
void set_str_member(ObjType &obj, const std::string &value)
{
obj.*member = value;
}
template<typename ObjType>
struct set_member_hlpr
{
typedef void (*func_type)(ObjType&, const std::string&);
};
struct Something
{
int attribute1;
std::string attribute2;
};
std::map<std::string, set_func_hlpr<Something>::func_type > m;
m["attribute1"] = &set_member<Something, int, &Something::attribute1>
// you can use set_member() for Something::attribute2, but
// std::istringstream will split the input value on whitespace,
// which may not be desirable. If you want to preserve the whole
// value, use set_str_member() instead..
m["attribute2"] = &set_str_member<Something, &Something::attribute2>;
...
Something obj;
std::string value = ...; // "123"
std::string name = ...; // "attribute1"
m[name](obj, value);
/*
Or safer:
std::map<std::string, set_func>::iterator iter = m.find(name);
if (iter != m.end())
iter->second(obj, value);
*/
Upvotes: 1