boost :: variant和boost :: any如何工作?

sal*_*r p 65 c++ boost-variant boost-any unions

如何使用boost库中的变体和任何内部工作?在我正在进行的项目中,我目前使用标记的联合.我想使用其他东西,因为C++中的联合不允许您使用带有构造函数,析构函数或重载赋值运算符的对象.

我查询了任何和变体的大小,并用它们做了一些实验.在我的平台中,variant采用其最长可能类型的大小加上8个字节:我认为我只是8字节的类型信息,其余的是存储值.另一方面,任何只需要8个字节.由于我在64位平台上,我猜任何只是一个指针.

怎么知道它有什么类型?Variant如何通过模板实现它的功能?在使用它们之前,我想更多地了解这些类.

Edw*_*nge 78

如果你阅读了boost :: any文档,他们会提供这个想法的来源:http://www.two-sdg.demon.co.uk/curbralan/papers/ValuedConversions.pdf

它是基本的信息隐藏,是一种必不可少的C++技能.学习它!

由于这里最高的投票答案是完全错误的,我怀疑人们实际上会去查看源代码以验证这一事实,这里是任何类似接口的基本实现,它将使用f()函数包装任何类型允许它被调用:

struct f_any
{
   f_any() : ptr() {}
   ~f_any() { delete ptr; }
   bool valid() const { return ptr != 0; }
   void f() { assert(ptr); ptr->f(); }

   struct placeholder
   {
     virtual ~placeholder() {}
     virtual void f() const = 0;
   };

   template < typename T >
   struct impl : placeholder
   {
     impl(T const& t) : val(t) {}
     void f() const { val.f(); }
     T val;
    };
   // ptr can now point to the entire family of 
   // struct types generated from impl<T>
   placeholder * ptr;

   template < typename T >
   f_any(T const& t) : ptr(new impl<T>(t)) {}

  // assignment, etc...
};
Run Code Online (Sandbox Code Playgroud)

boost :: any做同样的基本事情,除了f()实际返回typeinfo const&并提供其他信息访问any_cast函数才能工作.

  • 顺便说一句,这只是类型擦除.一个非常有用的原则. (5认同)

Mic*_*yan 20

boost::any和之间的关键区别boost::variantany可以存储任何类型,而variant只能存储一组枚举类型中的一个.该any类型存储void*指针的对象,以及一个typeinfo对象要记住的基本类型和执行某种程度的类型安全的.在boost::variant,它计算最大大小的对象,并使用"placement new"在此缓冲区中分配对象.它还存储类型或类型索引.

请注意,如果安装了Boost,您应该能够在"any.hpp"和"variant.hpp"中看到源文件.只需在"/ usr","/ usr/local"和"/ opt/local"中搜索"include/boost/variant.hpp"和"include/boost/any.hpp",直到找到已安装的标题,然后你可以看看.

编辑
正如下面的评论中指出的那样,我对boost :: any的描述略有不准确.虽然它可以使用void*(以及模板化的destroy回调来正确删除指针)来实现,但实际实现使用any<T>::placeholder*with any<T>::holder<T>作为any<T>::placeholder统一类型的子类.

  • 这个答案是完全错误的.任何不,我重复不使用void指针. (12认同)
  • 疯狂的艾迪是对的; `any`没有使用`void*`实现,因为它使资源清理更难.相反,它使用多态类层次结构,并为存储的每种类型派生类模板.这允许通过虚拟析构函数进行清理.但是,你的其余答案真的很棒,所以我没有添加自己的downvote. (7认同)
  • 您还可以在他们的网站上看到来源.例如,[这里是any.hpp的内容](http://www.boost.org/doc/libs/release/boost/any.hpp)和[这里是variant.hpp的内容](http:// www.boost.org/doc/libs/release/boost/variant.hpp).`#include`s是超链接的,所以你可以直接看到他们`#include`的文件. (4认同)
  • 对不起,我有所纠正.我已经看到类似的实现使用带有模板化destroy函数的void*指针,但是你是对的,boost使用任何:: placeholder*而不是void*,任何:: holder <T>作为any的子类: :占位符. (2认同)

Ton*_*roy 9

boost::any只是typeinfo在模板化构造函数运行时快照:它有一个指向非模板化基类的指针,该基类提供对typeinfo的访问,构造函数派生一个特定于类型的类来满足该接口.实际上可以使用相同的技术来捕获一组类型的其他常见功能(例如,流式传输,通用运算符,特定功能),尽管boost不提供对此的控制.

boost :: variant在概念上类似于你之前所做的,但是并没有逐字地使用a union而是采用手动方法在缓冲区中放置构造/破坏对象(同时明确地处理对齐问题),它解决了C++在实际的unions中有复杂的类型.