C++ any optional variant

C++17 收编了boost库的 boost::any ,  boost::optional,  boost::variant

any可以模仿动态类型语言的变量。注意,any不是模板类,因此,可以这样做:

#include <iostream>
#include <any>
#include <vector>
int main()
{
    using namespace std;
    
    vector<any> myvec={ any(10), any("abc"), any(3.14f) };
    
    for( auto& a : myvec){
        if (a.type() == typeid(int)){
            int i = std::any_cast<int>(a);
            std::cout <<"i="<<i<< std::endl;
        }
        else if (a.type() == typeid(const char*)) {
            const char* str = std::any_cast<const char*>(a);
            std::cout <<"str="<<str<< std::endl;
        }
        else if (a.type() == typeid(float)){
            float d = std::any_cast<float>(a);
            std::cout <<"d="<<d<< std::endl;
        }
    }
}

考虑一个函数返回用户信息。当用户存在时,需要想办法告知调用者。可以这样:

#include <iostream>#include <string>
struct User{
    int user_id;
    std::string name;
};

User query_user_by_uid(int user_id){
    //查询用户资料,返回对象
    //...
    //当用户不存在时,返回空的用户对象
    return User{-1,""};
}

int main()
{
    using namespace std;
    
    User u = query_user_by_uid(12345);
    if (u.user_id==-1){
        std::cout << "用户不存在" << std::endl;
    }
}

其它方式:返回个(User*)0空指针,或者抛例外no_user_found_exception,等等。

如果对上述方式都不满意,可以使用optional, 代码如下:

#include <iostream>
#include <optional>
#include <string>
struct User{
    int user_id;
    std::string name;
    User(int i, std::string n){ //构造函数
        user_id = i;
        name = n;
    }
};

std::optional<User> query_user_by_uid(int user_id){
    //查询用户资料,返回对象
    //...
    return std::optional<User>(std::in_place, user_id, "hello");
    //当用户不存在时,返回空的用户对象
    return std::optional<User>();
}

int main()
{
    using namespace std;
    
    std::optional<User> u = query_user_by_uid(12345);
    if (!u){
        std::cout << "用户不存在" << std::endl;
    }
    else{
        auto& user = *u;
        std::cout << "user name=" << user.name << std::endl;
    }
}

注意,std::in_place是个全局常量,用于告知optional创建User对象的方式是in place construct。不熟悉placement new的同学可以去搜索相关知识。

最后一个兄弟是variant。能替换union类,是更好的解决方案。代码如下:

#include <iostream>
#include <variant>
#include <string>

struct User{
    int user_id;
    std::string name;
    User(int i, std::string n){ //构造函数
        user_id = i;
        name = n;
    }
};

int main()
{
    std::variant<std::string, int, User> user( std::in_place_type<User>, 12345, "hello"); //in place构造User对象
    std::variant<std::string, int, User> i( 12345 );
    std::variant<std::string, int, User> str( "hello" );
    std::variant<std::string, int, User> nul_str();   //构造的索引0位置的对象,就是构造一个std::string
    std::variant<User, int> wft();                    //User没有默认构造函数,因此编译报错 
    std::variant<std::monostate, User, int> ok();    //默认按照索引0对应的类型构造(让User避开索引0),默认构造一个monostate对象(占位用)。
    
    std::cout << "存放的是第"<< user.index() << "个类型的数据" << std::endl; //索引0开始,2代表User
    user = 123;
    std::cout << "存放的是第"<< user.index() << "个类型的数据 " << std::get<int>(user) <<std::endl; //索引1开始,1代表int
    user.emplace<std::string>("world");  //in place construct
    std::cout << "存放的是第"<< user.index() << "个类型的数据 " << std::get<std::string>(user) <<std::endl; //索引1开始,1代表int
}

查询当前存放的数据的类型(通过index()函数),存放,读取,全部满足要求!还有什么不满足的呢?那就是Mordern C++化!!代码如下:

#include <iostream>
#include <variant>
#include <string>

struct User{
    int user_id;
    std::string name;
    User(int i, std::string n){ //构造函数
        user_id = i;
        name = n;
    }
};

void handleData(int i){ std::cout << "i="<< i; }
void handleData(const User &d){ std::cout << "User.name=" << d.name ; }
void handleData(const std::string  &s){ std::cout << "s=" << s; }

int main()
{
    std::variant<std::string, int, User> user( std::in_place_type<User>, 12345, "hello"); //in place构造User对象
    std::visit( [](auto const & val) { handleData(val); }, user);
}

原理待研究

 

转载于:https://www.cnblogs.com/thomas76/p/8556500.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值