C++万能容器 std::any
any是一种很特殊的容器,它只能容纳一个元素,但这个元素可以是任意的类型,可以是基本数据类型(int,double,char,float...)也可以是复合数据类型(类、结构体)
1.构造
initializer_list使用any
#include <iostream>
//#include <initializer_list>
#include <vector>
#include <any>
int main()
{
std::string a = "aa";
std::vector<std::any> vec{ 111,a,1.2f,"bbb" };
const char* b = "aa";
for (auto elem : vec)
{
int x = 0;
//std::cout <<"vector type:" << elem.type().name() << std::endl;
if (typeid(elem).name() == typeid(a).name())
{
std::cout << "string type:";
std::cout << std::any_cast<std::string>(elem) << std::endl; //进不来
}
if (elem.type().name() == typeid(a).name())
{
std::cout << "string type:";
auto ret = std::any_cast<std::string>(elem); //类型错误会抛出异常
std::cout << ret << std::endl;
}
if (elem.type().name() == typeid(x).name())
{
std::cout << "int type:";
x = std::any_cast<int>(elem); //类型错误会抛出异常
std::cout << x << std::endl;
}
if (elem.type().name() == typeid(b).name())
{
std::cout << "const char* type:";
auto ret = std::any_cast<const char*>(elem); //类型错误会抛出异常
std::cout << ret << std::endl;
}
}
return 0;
}
自定义any容器
#include <memory>
class MyAny
{
public:
template <typename T> //这里用模板函数不用模板类,因为如果是模板类,实例化一个MyAny对象就需要指定类型,这样做any就没有了意义,
MyAny(T t):base(std::make_unique<Data<T>>(t)) {}
template <typename T>
T any_cast()
{
auto p = dynamic_cast<Data<T>*>(base.get());
if (!p)
throw "type is error\n";
return p->value;
}
private:
class Base
{
public:
virtual ~Base() {} // 基类是一个多态类,必须定义析构函数
};
template <typename T>
class Data:public Base
{
public:
Data(T t) :value(t) {}
T value;
};
//Data data; //派生的子类Data需要模板参数才能创建,所以这里必须是没有模板的基类
std::unique_ptr<Base> base; //如果是模板函数,不知道存储的数据类型,就需要在MyAny类内部再定义一个模板基类Base
//Base base; //不能用普通对象,因为无法把类型从Base转换到Data,没法访问value
};
int main()
{
MyAny d(0);
MyAny e = 'c';
MyAny f = "test";
auto ret0 = d.any_cast<double>(); // 这里的类型一定要一致,否则this指针为空
auto ret1 = e.any_cast<char>();
auto ret2 = f.any_cast<const char*>();
auto ret3 = f.any_cast<char*>(); //throw error
return 0;
}