Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ boost::variant和boost::如何工作?_C++_Unions_Boost Variant_Boost Any - Fatal编程技术网

C++ boost::variant和boost::如何工作?

C++ boost::variant和boost::如何工作?,c++,unions,boost-variant,boost-any,C++,Unions,Boost Variant,Boost Any,boost库中的variant和any如何在内部工作?在我正在处理的项目中,我当前使用的是标记的联合。我想使用其他东西,因为C++中的联合不允许使用构造函数、析构函数或重载赋值操作符使用对象。 我询问了任何一个和变体的大小,并用它们做了一些实验。在我的平台中,variant的大小是它可能的最长类型加上8个字节:我认为它只是我的类型信息的8个字节,其余的是存储的值。另一方面,any只需要8个字节。因为我是在64位平台上,所以我想任何一个都只包含一个指针 任何人怎么知道它是什么类型的?Variant

boost库中的variant和any如何在内部工作?在我正在处理的项目中,我当前使用的是标记的联合。我想使用其他东西,因为C++中的联合不允许使用构造函数、析构函数或重载赋值操作符使用对象。 我询问了任何一个和变体的大小,并用它们做了一些实验。在我的平台中,variant的大小是它可能的最长类型加上8个字节:我认为它只是我的类型信息的8个字节,其余的是存储的值。另一方面,any只需要8个字节。因为我是在64位平台上,所以我想任何一个都只包含一个指针


任何人怎么知道它是什么类型的?Variant如何通过模板实现其功能?在使用这些类之前,我想了解更多。

boost::any和
boost::variant
之间的关键区别在于
any
可以存储任何类型,而
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*
(以及模板化的销毁回调来正确删除指针)来实现,但实际上实现使用的是
any::placeholder*
,使用
any::holder
作为
any::placeholder
的子类来统一类型。

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


variant在概念上与您之前所做的类似,但它并没有真正地使用
联合
,而是采用手动方法在其缓冲区中放置、构造/销毁对象(同时明确地处理对齐问题)它的工作原理是,在实际的<代码>联合<代码> S.< /P> < P>中,C++有复杂的类型:如果你阅读Booost::任何文档,它们都提供了思想的来源:

<>是基本信息隐藏,是一个必备的C++技能。学习它

由于这里投票率最高的答案是完全错误的,我怀疑人们是否真的会去查看源代码来验证这一事实,下面是any-like接口的一个基本实现,它将使用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...
};
struct f\u any
{
f_any():ptr(){}
~f_any(){delete ptr;}
bool valid()常量{return ptr!=0;}
void f(){assert(ptr);ptr->f();}
结构占位符
{
虚拟~占位符(){}
虚空f()常数=0;
};
模板
结构impl:占位符
{
impl(T const&T):val(T){
void f()常量{val.f();}
T值;
};
//ptr现在可以指向整个
//从impl生成的结构类型
占位符*ptr;
模板
f_any(T const&T):ptr(新impl(T)){
//任务等。。。
};

boost::any做的基本操作与any相同,只是f()实际返回
typeinfo const&
,并提供对any_cast函数的其他信息访问以使其工作。

您也可以在其网站上看到源代码。例如,和。
#include
是超链接的,因此您可以直接查看它们包含的文件。这个答案完全错误。任何人都不会,我重复一遍,不会使用虚空指针。疯狂的埃迪是正确的<代码>任何都不会使用
void*
实现,因为这会使资源清理更加困难。相反,它使用多态类层次结构,并为存储的每个类型使用派生类模板。这允许通过虚拟析构函数进行清理。然而,你剩下的答案真的很好,所以我没有投我自己的反对票。对不起,我站在正确的立场上。我见过类似的实现,它们使用void*指针和模板化销毁函数,但您是对的,boost使用的是any::placeholder*而不是void*,any::holder作为any::placeholder的子类。@IgorGanapolsky隐式/自动转换仅限于此。要转换这两个元素,需要复制/转换元素。(顺便说一句,这是一件好事,因为它可以防止您无意中复制大量昂贵的副本)。顺便说一句,这只是类型擦除。这是一个非常有用的原则。我最近真的很好奇,为什么它不是唯一的\u ptr而不是原始指针?这有什么好的理由吗?或者这与性能有关?这可能会避免删除,不是吗?@Belov我认为使用unique_ptr没有什么问题(尽管我不是智能指针方面的专家)。所以我认为这是因为这个答案最初是在C++11标准被批准之前发布的,从那时起,没有人真正费心去修复这样一个小问题。因为这个答案是编写的(可能),boost typeerasure可以让您捕获类型的其他属性。