• C++ Boost.Any 源码剖析与实现


    Boost.Any

    强类型语言,例如C++,要求每个变量都有一个特定的类型来定义它可以存储什么样的信息。这种实用像极了JavaScript、Python,允许开发人员将任何类型的信息存储在变量中

    使用

    例子

    #include 
    
    int main() {
        boost::any a = 1;
        a = 3.14;
        a = true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    要使用boost::any

    前提

    1. 包含头文件 boost/any.hpp
    2. 存储在类型变量中的任何值都必须是可复制构造的
    3. 因此不可以存储C 数组,因为C 数组是不可复制构造的

    例子,将字符串存储在 boost::any

    #include 
    #include 
    
    int main() {
    	boost:any a = std::string{"Boost"};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    例子,访问boost::any 的值,请使用强转运算符 boost::any_cast

    #include 
    #include 
    
    int main() {
      boost::any a = 1;
      std::cout << boost::any_cast<int>(a) << '\n';
      a = 3.14;
      std::cout << boost::any_cast<double>(a) << '\n';
      a = true;
      std::cout << std::boolalpha << boost::any_cast<bool>(a) << '\n';
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    例子,如果 boost::any_cast 变量值被转换。如果指定了无效类型, boost::bad_any_cast 则会抛出类型异常

    #include 
    #include 
    
    int main() {
      try
      {
        boost::any a = 1;
        std::cout << boost::any_cast<float>(a) << '\n';
      }
      catch (boost::bad_any_cast &e)
      {
        std::cerr << e.what() << '\n';
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    例子,检查当前存储值的类型

    #include 
    #include 
    #include 
    
    int main() {
      boost::any a = 1;
      if (!a.empty())
      {
        const std::type_info &ti = a.type();
        std::cout << ti.name() << '\n';
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    例子,通过指针访问值

    #include 
    #include 
    
    int main() {
      boost::any a = 1;
      int *i = boost::any_cast<int>(&a);
      std::cout << *i << '\n';
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    源码实现

    https://www.boost.org/doc/libs/1_80_0/boost/any.hpp

    个人实现

    https://github.com/yeshenyong/practice_cpp

    any.hpp

    #include 
    #include 
    #include 
    namespace selfboost {
    class any {
        public:
            any() : content(nullptr) {}
            // 模板构造
            template <typename _Tp>
            any(const _Tp& value) : content(new holder<_Tp>(value)) {}
            // 拷贝构造
            any(const any& other) : content(other.content ? other.content->clone() : nullptr) {}
            // 移动构造
            any(any&& other) noexcept : content(other.content) { other.content = nullptr; }
            ~any() {
                if (!content) delete content;
            }
    
            // 判空
            bool isNull() const  { return content == nullptr; }
            const std::type_info& type() const { return content == nullptr ? typeid(void) : content->type(); }
    
    
            any& swap(any& rhs) noexcept {
                placeholder* tmp = content;
                content = rhs.content;
                rhs.content = tmp;
                return *this;
            }
    
            template <typename _Tp>
            _Tp *get() { return content == nullptr ? nullptr : content->type() == typeid(_Tp) ? &static_cast<any::holder<_Tp> *>(content)->hold : nullptr; }
    
            template <typename _Tp>
            any& operator=(const _Tp& rhs) {
                any(rhs).swap(*this);
                return *this;
            }
    
            // 完美转发
            template <typename _Tp>
            any& operator=(_Tp&& rhs) {
                any(static_cast<_Tp&&>(rhs)).swap(*this);
                return *this;
            }
    
            any & operator=(any rhs) {
                rhs.swap(*this);
                return *this;
            }
        public:
            bool empty() const noexcept {
                return !content;
            }
    
            void clear() noexcept {
                any().swap(*this);
            }
        private:
            // 保存数据接口
            class placeholder {
                public:
                    virtual ~placeholder() {}
                    // 查询类型
                    virtual const std::type_info& type() const noexcept = 0;
                    // 实现复制
                    virtual placeholder* clone(void) = 0;          
            };
            template <typename _Tp>
            class holder final : public placeholder {
                public:
                    holder(const _Tp& value) : hold(value) {}
                    ~holder() {}
                    const std::type_info& type() const noexcept override { return typeid(_Tp); }
                    placeholder* clone() override {
                        return new holder(hold);
                    }
                    holder &operator=(const holder&) = delete;
                public:
                    _Tp hold;
            };
            // 数据保存
            placeholder* content;
            // 用于类型转换
            template< typename _Tp>
            friend _Tp *any_cast(const any& rhs);
    };
    template <typename _Tp>
    _Tp* any_cast(const any& rhs) {
        assert(rhs.type() == typeid(_Tp));
        return &(static_cast<any::holder<_Tp>*>(rhs.content)->hold);
    }
    
    } // namespace selfboost
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94

    使用

    #include "any.hpp"
    #include 
    
    using namespace std;
    
    int main() {
        selfboost::any a = 1;
        std::cout << *selfboost::any_cast<int>(a) << '\n';
        a = 3.14;
        std::cout << *selfboost::any_cast<double>(a) << '\n';
        a = true;
        std::cout << std::boolalpha << *selfboost::any_cast<bool>(a) << '\n';
    
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    缺少功能

    1. 异常捕捉(输出了不符合hold 类型)
    2. 没有对一些不符合any 类型的(如C 数组)进行剔除
    3. 待完善
  • 相关阅读:
    Python分享之对象的属性
    【C语言】通讯录(动态版本)
    【调参】如何为神经网络选择最合适的学习率lr-LRFinder-for-Keras
    二、IDEA创建Maven项目
    采集网页数据保存到文本文件---爬取古诗文网站
    Java(五)(Object类,克隆,Objects类,包装类,StringBuilder,StringJoiner,BigDecimal)
    oracle练习02
    【python之django1.11框架四】模型层(ORM语法)的介绍
    go语言grpc的快速体验-grpc流模式
    【微信小程序开发(三)】实现卡片的层叠滑动
  • 原文地址:https://blog.csdn.net/weixin_44974875/article/details/126568299