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

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C++ any optional variant

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/397576

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月11日 上午9:15
下一篇 2023年4月11日 上午9:16

相关推荐