前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >std::any 解决类型不确定性的利器

std::any 解决类型不确定性的利器

作者头像
程序员的园
发布2024-07-18 13:30:26
130
发布2024-07-18 13:30:26
举报
文章被收录于专栏:程序员的园——原创文章

背景

C++是一种强类型的语言。要求变量和表达式的类型在编译时必须能够确定。但是也经常会遇到需要处理不确定类型的情况。如函数需要可以接受任意类型的参数,或者在一个容器中存储各种类型的对象,以往可以通过指针和模板来解决,但是这些方法存在代码冗长、可读性差等问题。而 C++17 引入的 std::any 类模板则提供了一种更加优雅和方便的解决方案。如下示例代码展示了在vector中存储不同类型的值。

代码语言:javascript
复制
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的用法

代码语言:javascript
复制
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对象的构造、赋值、拷贝、取值、转换和异常处理。

注意

  • std::any在进行any_cast转换时,如果类型不匹配会触发异常,在进行any_cast转换前,需要先判断是否存在指定类型的值,存在使用指针和使用typeid两种方法,见示例代码。
  • std::any含有的值必须是可拷贝的,否则会编译报错。
  • std::any作为类模板可以存在任意类型,提供了使用便利性,但其具有内存占用大的弊端。经测试any占用40个字节,是int的10倍。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-04-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员的园 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档