利用模板类继承非模板类,实现一个可以存储任意类型的容器
#ifndef _ANY_H_
#define _ANY_H_
#include <string>
#include <algorithm>
class IAnyItem
{
public:
virtual ~IAnyItem() {}
virtual const std::type_info& type() const = 0;
virtual bool empty() const = 0;
virtual IAnyItem* clone() const = 0;
};
class Any;
template<typename T>
class AnyItem : public IAnyItem
{
private:
AnyItem(const AnyItem<T>& x):elementNum(x.elementNum) {
value = new T(*x.value);
}
AnyItem(const AnyItem<T>& x, size_t ele): elementNum(ele) {
value = new T[elementNum]();
memcpy(value, x.value, sizeof(T) * elementNum);
}
AnyItem():value(nullptr),elementNum(0) {}
AnyItem(T val[], size_t n): elementNum(n) {
value = new T[elementNum]();
memcpy(value, val, sizeof(T) * n);
}
AnyItem(const T& val):elementNum(0) {
value = new T(val);
}
virtual ~AnyItem() {
if (value) {
if(elementNum > 0) {
delete[] value;
}else {
delete value;
}
value = nullptr;
}
}
virtual const std::type_info& type() const{
return typeid(T);
}
virtual bool empty() const{
return value == nullptr;
}
virtual IAnyItem* clone() const {
IAnyItem* item = nullptr;
if(elementNum > 0) {
item = new AnyItem<T>(*this, elementNum);
}else {
item = new AnyItem<T>(*this);
}
return item;
}
const T& get() const {
return *value;
}
T& ref() {
return *value;
}
AnyItem operator=(const T& val) {
*value = val;
return *this;
}
public:
friend class Any;
private:
T* value;
size_t elementNum; // 当类型是数组类型是有效 元素个数
};
class Any
{
public:
Any():item(nullptr){}
template<typename T>
Any(const T& val):item(new AnyItem<T>(val)){}
template<typename T>
Any(T val[], size_t n):item(new AnyItem<T>(val, n)){} // 数组类型需要传递元素个数
template<typename T>
Any(const AnyItem<T>& x) {
item = x.clone();
}
Any(const char* x):item(new AnyItem<std::string>(x)){}
Any(char* x):item(new AnyItem<std::string>(x)){}
Any(Any&& x):item(x.item) {
x.item = nullptr;
}
Any(const Any& x):item(nullptr){
if (x.getItem()) {
item = x.getItem()->clone();
}
}
~Any() {
if (item) {
delete item;
}
}
template<typename T>
const T& any_cast() const {
AnyItem<T>* anyitem = static_cast<AnyItem<T>*>(item);
return anyitem->get();
}
template<typename T>
T& ref() {
AnyItem<T>* anyitem = static_cast<AnyItem<T>*>(item);
return anyitem->ref();
}
bool empty() const {
return item == nullptr || item->empty();
}
Any operator=(const Any& x) {
Any tmp(x);
this->swap(tmp);
return *this;
}
template<typename T>
Any operator=(const AnyItem<T>& x) {
Any tmp(x);
this->swap(tmp);
return *this;
}
template<typename T>
Any operator=(const T& x) {
Any tmp(x);
this->swap(tmp);
return *this;
}
const std::type_info& type() const {
return item->type();
}
private:
void swap(Any& x) {
using std::swap;
swap(this->item, x.item);
}
const IAnyItem* getItem() const {
return item;
}
private:
IAnyItem* item;
};
#endif
测试
int main() {
string* ss = new string("yy");
vector<Any> t;
Any a(123);
Any b(string("xxx"));
Any c(ss);
t.push_back(a);
t.push_back(b);
t.push_back(c);
auto x = t[0].any_cast<int>();
auto s = t[1].any_cast<string>();
auto k = t[2].any_cast<string*>();
cout << x << " " << s <<" "<< *k << endl;
system("pause");
return 0;
}
对于char*, const char* 类型, Any容器内部自动转为std::string。所以外部在使用时需要将其转为std::string类型;
如:char buf[100] = {'1','2'}; Any a(buf); std::string str = a.any_cast<std::string>();