背景
C++是一种强类型的语言。要求变量和表达式的类型在编译时必须能够确定。但是也经常会遇到需要处理不确定类型的情况。如函数需要可以接受任意类型的参数,或者在一个容器中存储各种类型的对象,以往可以通过指针和模板来解决,但是这些方法存在代码冗长、可读性差等问题。而 C++17 引入的 std::any 类模板则提供了一种更加优雅和方便的解决方案。如下示例代码展示了在vector中存储不同类型的值。
void using_any_in_vec() {
std::vector<std::any> vec;
vec.push_back(42);
vec.push_back("hello");
vec.push_back(3.14);
for (constauto& item : vec) {
if (item.type() == typeid(int)) {
std::cout << "Integer value: " << std::any_cast<int>(item) << std::endl;
}
elseif (item.type() == typeid(constchar*)) {
std::cout << "String value: " << std::any_cast<constchar*>(item) << std::endl;
}
elseif (item.type() == typeid(double)) {
std::cout << "Double value: " << std::any_cast<double>(item) << std::endl;
}
}
}
std::any<T>是一个类模板,用于存储任意可拷贝构造的单个的对象。如基本类型、自定义类型(可拷贝)、甚至是函数对象等。std::any也存在含值和不含值两个状态,此处同std::optional一样,。
用法
std::any的用法
class C
{
public:
C(intc):m_c{c}{}
C(constC&)=delete;
private:
int m_c{0};
};
voidusing_any()
{
//创建对象
std::any value1;
std::any value2= std::make_any<int>(30);
std::any value3= value2;
std::any value4 = 99;
std::any value5 = "hello world";
value5.emplace<std::string>("China");//!
std::cout << sizeof(value1) << "\t" <<sizeof(value2)<<"\t"<< sizeof(value3) << "\t" << sizeof(value4) << "\t" << sizeof(value5) << "\n" ;
//std::any value6 = std::make_any<C>(10);//error
//判断是否含值
if (value2.has_value())//有值
{
//通过指针转换后的指针是否为空来判断是否存在指定类型的值
if (constauto p = std::any_cast<int>(&value2))
{
std::cout << "Integer value: " << *p << std::endl;
}
//通过与指定类型的typeid做对比,判断是否存在指定类型的值
if (value2.type() == typeid(int)) {
std::cout << "Integer value: " << std::any_cast<int>(value2) << std::endl;
}
try
{
//类型不匹配时会触发异常std::bad_any_cast
auto d = std::any_cast<double>(value2);
}
catch (conststd::bad_any_cast& e)
{
std::cout<<"value2 is not double type value";
}
}
else
{
std::cout<<"value2 do not contians value \n";
}
//交换两个值
value4 = value5;
value3.swap(value4);
//清空值/重置
value3.reset();
}
如上代码涵盖到了std::any对象的构造、赋值、拷贝、取值、转换和异常处理。
注意