typedef boost::variant<int, std::string> Value;
這時ValueT就可以放int或者std::string。另外我不建議在外部直接使用boost::variant, 而是間接封壹層。比如
class Value
{
public:
Value();
Value(int val);
Value(const std::string& val);
bool isString() const;
bool isInt() const;
const std::string& string() const;
uint32_t uint32() const;
private:
boost::variant<int, std::string> _data;
};
這樣boost::variant被當成實現的壹部分,外面看不到,當舍棄boost::variant的時會方便點。上面做法基本上已經滿足需求了。
假如真不想用boost::variant, 可以使用union來替代
class Value
{
public:
private:
int _type;
union
{
int intV;
std::string strV;
};
};
C++11支持union裏面放對象,但是我經常不記得具體語法的,上面語法應該是錯的,領會思路就行了。很多情況下字符串賦值之後是不變的,union裏面也不建議放有構造函數的數據,就可以演變成
union
{
int intV;
const char* strV;
};
為減少字符串復制,再在字符串前面加引用計數。變成
| ref_count | str_data |
strV指向str_data。ref_count跟str_data是連續放在壹起的。這樣Value復制的時候修改引用計數。ref_count通常為2字節或者4字節長。
其實上面的代碼不用自己來寫的。找個比較好json庫,裏面通常會有個Value類可以放多種類型的,偷過來修改壹下就可以用了。
假如妳真的想放任意數據,可以使用
class BaseHolder
{
public:
virtual ~BaseHolder() {}
};
template <typename T>
class Holder : public BaseHolder
{
public:
private;
T _data;
};
之後,容器裏面放BaseHolder的智能指針,比如std::shared_ptr。之前看過boost::any裏面的不必要復制有點多。