zoukankan      html  css  js  c++  java
  • C++ 之 Python 字典类型实现

    变体类型 std::variant

    在此之前需要先介绍一下类模板std::variant,其表示一个类型安全的联合体。 std::variant 的一个实例在任意时刻要么保有其一个可选类型之一的值,要么在错误情况下无值。与union在聚合初始化中的行为一致, 若 variant 保有某个对象类型 T 的值,则直接于 variant 的对象表示中分配 T 的对象表示。不允许 variant 分配额外的(动态)内存。简单来说就是一个可变类型的变量,其获取方法跟元组的第一个获取方法类似。代码如下

    #include <variant>
    #include <string>
    #include <cassert>
     
    int main()
    {
        std::variant<int, float> v, w;
        v = 12; // v 含 int
        int i = std::get<int>(v);
        w = std::get<int>(v);
        w = std::get<0>(v); // 与前一行效果相同
    }
    

    更加优秀的状态是std::visitoverloaded模板函数相互配合实现,代码如下:

    #include <variant>
    #include <iostream>
    #include <sstream>
    #include <string>
    
    template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
    template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; 
    
    int main() {
    	std::stringstream convert;
    	std::variant<int, long long int, std::string, double> value = 12.3;
    	std::visit(overloaded{
    	        [&convert](int value) { convert << value << 'i'; },
    	        [&convert](long long int value) { convert << value << 'i'; },
    	        [&convert](double value) { convert << value; },
    	        [&convert](const std::string &value) { convert << '"' << value << '"'; },
    	}, value);
    	std::cout << convert.str();
    }
    

    如果看懂了,你肯定感觉很惊艳。不过作为一个入门级选手的我,属实看不懂。首先是overload就没看懂,不错是template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; 模板参数的自动推导,如果你知道这是类型推导的一步,那已经明白1/3了。

    [&convert](int value) { convert << value << 'i'; },
    [&convert](long long int value) { convert << value << 'i'; },
    [&convert](double value) { convert << value; },
    [&convert](const std::string &value) { convert << '"' << value << '"'; }
    

    这四句话都是如果不明白Lambda 表达式可以查看博文C++ 11 新特性总结,而Lambda 表达式是一个函数对象,其作为overload参数输入,会使得编译器根据自动推导命令,直接将其类作为模板参数表实现类型的声明即获得一个类overloaded<Lambda1,Lambda2,Lambda3>

    接下来是using的变长声明using 声明还挺长一段,详细内容可以查看C++ 中文指南,简单来说,就是直接将父类中的函数直接拿来用,效果就像不是继承而来,在类内自己实现的。这样就有一个效果,如果父类和子类具有同名函数,便形成了函数重载。所以这里的using Ts::operator()...是将所有根据Lambda表达式所获取的继承类Ts()运算符函数直接拿来用,并且由于函数名一样出现类似函数重载的效果。

    最后是std::visit函数,其声明如下:

    template <class Visitor, class... Variants>
    constexpr /*...*/ visit(Visitor&& vis, Variants&&... vars);
    

    其实现的功能是,将vars的可能值传入vis中。

    所以最终便会实现,根据variant中可用参数类型不同,最终生成不一样的字符串,传入字符串流对象convert中。

    到此字典类型核心便的实现了一般,下一步是字符串映射,使用C++标准库中的std::mapstd::unordered_map 便可以实现了。下面是示例代码,可见可以轻松实现Python的字典效果。

    #include <variant>
    #include <iostream>
    #include <sstream>
    #include <string>
    #include <unordered_map>
    
    template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
    template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
    
    int main() {
    
        std::variant<int, long int, char, std::string, float, double> value1;
        std::unordered_map<std::string, std::variant<int, long int, char, std::string, float, double>> dictionary;
    
        dictionary["a"] = "Hello";
        dictionary["b"] = 'I';
        dictionary["c"] = 2;
        dictionary["d"] = 3.14159f;
    
        std::stringstream convert;
    
        for (const auto &item : dictionary) {
            convert.clear();
            convert.str("");
            std::visit(overloaded{
                    [&convert](char value) { convert << value; },
                    [&convert](int value) { convert << value; },
                    [&convert](long int value) { convert << value; },
                    [&convert](float value) { convert << value; },
                    [&convert](double value) { convert << value; },
                    [&convert](const std::string &value) { convert << value; },
            }, item.second);
            std::cout << item.first << ' ' << convert.str() << '
    ';
        }
    }
    

    打印信息如下:

    d 3.14159
    c 2
    a Hello
    b I
    
    任世事无常,勿忘初心
  • 相关阅读:
    BEC listen and translation exercise 44
    中译英12
    BEC listen and translation exercise 43
    中译英11
    BEC listen and translation exercise 42
    中译英10
    BEC listen and translation exercise 41
    中译英9
    BEC listen and translation exercise 40
    中译英8
  • 原文地址:https://www.cnblogs.com/FlameBlog/p/14714767.html
Copyright © 2011-2022 走看看