您可以通过创建从 type_info 指针到特定类型数据的映射来做到这一点。
这是一个例子:
#include <iostream>
#include <map>
#include <typeinfo>
// Custom comparison operator that uses the std::type_info::before member
// function. Comparing the pointers doesn't work since there is no
// guarantee that the typeid operator always gives you the same object
// for the same type.
struct BeforeType {
bool operator()(const std::type_info *a,const std::type_info *b) const
{
return a->before(*b);
}
};
struct A {
template <typename T>
int &member()
{
return member_map[&typeid(T)];
}
std::map<const std::type_info *,int,BeforeType> member_map;
};
int main(int,char**)
{
A a1, a2;
++a1.member<int>();
++a1.member<int>();
++a1.member<double>();
++a2.member<int>();
std::cout << a1.member<int>() << "\n";
std::cout << a1.member<double>() << "\n";
std::cout << a1.member<float>() << "\n";
std::cout << a2.member<int>() << "\n";
return 0;
}
输出是:
2
1
0
1
如果您对包含不同类型值的容器感兴趣,可以使用如下内容:
#include <iostream>
#include <map>
#include <typeinfo>
struct BeforeType {
bool operator()(const std::type_info *a,const std::type_info *b) const
{
return a->before(*b);
}
};
struct Value {
virtual ~Value() { }
virtual Value *clone() = 0;
};
template <typename T>
struct BasicValue : Value {
T value;
BasicValue() : value() { }
BasicValue(const T &value) : value(value) { }
virtual Value *clone() { return new BasicValue(value); }
};
struct TypeMap {
TypeMap() { }
TypeMap(const TypeMap &that)
{
add(that.value_map);
}
template <typename T>
T &value()
{
ValueMap::iterator iter = value_map.find(&typeid(T));
if (iter==value_map.end()) {
BasicValue<T> *member_ptr = new BasicValue<T>;
value_map.insert(ValueMap::value_type(&typeid(T),member_ptr));
return member_ptr->value;
}
return static_cast<BasicValue<T> *>(iter->second)->value;
}
TypeMap &operator=(const TypeMap &that)
{
clear();
add(that.value_map);
return *this;
}
void clear()
{
while (!value_map.empty()) {
Value *member_ptr = value_map.begin()->second;
value_map.erase(value_map.begin());
delete member_ptr;
}
}
~TypeMap()
{
clear();
}
private:
typedef std::map<const std::type_info *,Value *,BeforeType> ValueMap;
ValueMap value_map;
void add(const ValueMap &value_map)
{
ValueMap::const_iterator iter = value_map.begin(), end = value_map.end();
for (;iter!=end;++iter) {
this->value_map[iter->first] = iter->second->clone();
}
}
};
int main(int,char**)
{
TypeMap type_map;
type_map.value<int>() = 5;
type_map.value<float>() = 2.5;
type_map.value<std::string>() = "hi";
std::cout << type_map.value<int>() << "\n";
std::cout << type_map.value<float>() << "\n";
std::cout << type_map.value<std::string>() << "\n";
return 0;
}
输出是:
5
2.5
hi
但是,如果您使用的是 boost,则可以大大简化:
struct TypeMap {
template <typename T>
T &value()
{
boost::any &any_value = value_map[&typeid(T)];
if (any_value.empty()) {
any_value = T();
}
return *boost::any_cast<T>(&any_value);
}
private:
std::map<const std::type_info *,boost::any,BeforeType> value_map;
};
使用 C++11,您还可以通过以下方式摆脱自定义比较std::type_index
:
struct TypeMap {
template <typename T>
T &value()
{
boost::any &any_value = value_map[std::type_index(typeid(T))];
if (any_value.empty()) {
any_value = T();
}
return *boost::any_cast<T>(&any_value);
}
private:
std::map<const std::type_index,boost::any> value_map;
};