我知道你不能將成員指針轉換爲指向非成員的指針(例如,void*
),但是你可以在指向成員的指針之間進行轉換同班?例如:對於某些類別C
和類型T
和U
,是否可以將T C::*
轉換爲U C::*
?在成員指針間轉換
我希望能夠將字符串名稱映射到某些類的指針成員。例如,給定:
template<class ClassType>
struct mbr_map_traits {
typedef std::string mbr_name_type;
typedef void* ClassType::*any_mbr_ptr;
typedef std::map<mbr_name_type,any_mbr_ptr> map_type;
};
/**
* A %mbr_map is used to map a string to an arbitrary pointer-to-member of some class.
* @tparam ClassType The class whose members to map to.
*/
template<class ClassType>
struct mbr_map : mbr_map_traits<ClassType>::map_type {
typedef typename mbr_map_traits<ClassType>::mbr_name_type mbr_name_type;
/**
* Initalizes an entry in the map so as to mape \a name to a pointer-to-member.
* @param name The name to map.
* @param p The pointer-to-member to map to.
*/
template<typename MemberType>
void mbr_init(mbr_name_type const &name, MemberType ClassType::*p) {
typedef typename mbr_map_traits<ClassType>::any_mbr_ptr any_mbr_ptr;
(*this)[ name ] = reinterpret_cast<any_mbr_ptr>(p); // IS THIS OK?
}
/**
* Sets the value of a class member by name.
* @param c The class whose member to set.
* @param name The name of the class member to set.
* @param value The value to set the member to.
* @return true only if \a name exists in the map.
*/
template<typename MemberType>
bool mbr_set(ClassType &c, mbr_name_type const &name, MemberType const &value) {
typedef typename mbr_map<ClassType>::const_iterator const_iterator;
const_iterator const found = this->find(name);
if (found != this->end()) {
typedef MemberType ClassType::*mbr_ptr;
c.*reinterpret_cast<mbr_ptr>(found->second) = value; // IS THIS OK?
return true;
}
return false;
}
};
和一些一次性初始化:
struct S {
std::string s;
int i;
bool b;
};
void mbr_map_init(mbr_map<S> *m) {
m->mbr_init("string_mbr", &S::s);
m->mbr_init("int_mbr", &S::i);
m->mbr_init("bool_mbr", &S::b);
}
我可以這樣做:
using namespace std;
int main() {
mbr_map<S> m;
mbr_map_init(&m);
S s;
m.mbr_set(s, "string_mbr", string("hello"));
m.mbr_set(s, "int_mbr", 42);
m.mbr_set(s, "bool_mbr", true);
cout << s.s << endl;
cout << s.i << endl;
cout << s.b << endl;
return 0;
}
,並打印我設置的值。但這是合法?
(我想這樣做的原因是爲了從配置文件中讀取到結構體成員參數名稱和值映射。)
那麼你會怎麼做呢? –
我不會相信一些隨機的用戶輸入來指定類型。您可以使用預處理器對名稱進行字符串化,並使用它將名稱與類型和字段關聯起來,這是在編譯時完成的。在運行時你只需要一些與名字相關的專用類型解析器。沒有重新解釋在任何地方施放,也沒有類型猜測mbr_set。但是如果你想保留你的地圖,至少檢查一下類型是否相同。例如,你可以使用boost :: any,或者std :: type_info – user3427419
我的代碼按照寫法,對名字和類型進行了硬編碼。用戶輸入只來自conf文件,根據定義,它必須是用戶可配置的。 –