万能容器可以存储任意类型数据,可以提升程序的灵活度。例如:std::vector<std::any>就是一个可以存储多种数据类型的数组。
any的API
构造函数
可以直接定义一个any类直接赋值:
std::any a = 10;
拷贝构造:
std::any b(10);
std::any a(b);
移动构造:
std::any c(std::move(b)); // 移动构造
成员函数
-
std::any_cast
用于获取存储在 std::any
中的值,支持类型安全的转换。如果类型不匹配,将抛出 std::bad_any_cast
异常。
std::any a = 42;
int value = std::any_cast<int>(a); // 获取 int 类型的值int* valueptr = std::any_cast<int>(&a); // 获取 类型指针 的值
-
std::has_val
检查 std::any
是否存储了一个值。
bool has_value() const noexcept;
-
std::type
返回存储值的类型信息(std::type_info
)
const std::type_info& type() const noexcept;
-
std::reset
清除存储的值,使 std::any
变为空。
void reset() noexcept;
模拟实现
思路:
使用继承这一特性,基类的指针可以访问派生类的成员。派生类使用模板来创建,通过基类访问数据。
class my_any{
private:class basic{public:virtual const std::type_info& type() = 0;//返回存储数据的类型virtual basic* clone() = 0;//构造一个与自身数据相同的对象,方便拷贝构造};template<class T>class derive : basic{public:derive(T val):_val(val){}virtual const std::type_info& type(){return typeid(T);}virtual derive* clone(){return new derive<T>(_val);}T _val;//存储的数据};basic* _content;//基类指针
public:my_any():_content(nullptr){}template<class T>my_any(const T& val)//赋值构造:_content((basic*)new derive<T>(val)){}my_any(const my_any& a)//拷贝构造{if(a._content == nullptr){_content = nullptr;}else{_content = a._content->clone();}}~my_any(){delete(_content);}my_any& swap(my_any &a)//方便赋值运算符重载,对临时对象进行自动释放{std::swap(_content, a._content);return *this;}template<class T>my_any& operator=(const T& val){my_any(val).swap(*this);return *this;}my_any& operator=(const my_any& a){my_any(a).swap(*this);return *this;}template<class T>T* get(){if(typeid(T) == _content->type()){return &(((derive<T>*)_content)->_val);}else{std::cout << "类型不匹配" << std:: endl;}}
};