为什么我的struct不能有boost :: variant类型的成员但是可以有vector <boost :: variant>类型的成员?

时间:2016-02-11 18:17:38

标签: c++ boost boost-variant incomplete-type

我定义了以下 boost :: variant 类型:

#include <boost/variant.hpp>
#include <vector>
#include <string> 

struct SharedNodeType;
typedef float TypeA;
typedef int TypeB;
typedef std::string TypeC;
typedef char* TypeD;

typedef boost::variant
<TypeA, TypeB, TypeC, TypeD, SharedNodeType> BaseNodeType;

其中TypeA,TypeB,TypeC和TypeD是完全限定的,完整类型(确切的类型是无关紧要的,但在这种情况下,它们是其他结构)。

我定义了以下结构:

struct SharedNodeType
{
     std::string nodeName;
     BaseNodeType node;
};

但是,上面编写的结构将不会编译,给出错误页面(这里包含的内容太多),主要与&#34;不允许的不完整类型有关。&#34;

第一个编译器错误是:

In file included from ./apps/iv_parserTest.cc(1):
/opt/common/boost/1.50.py2.7/include/boost/mpl/sizeof.hpp(27): error: incomplete type is not allowed
 : mpl::size_t< sizeof(T)>

但是,如果我将结构更改为以下内容,则编译没有问题:

struct SharedNodeType {
     std::string nodeName;
     std::vector<BaseNodeType> node;
};

由于我的SharedNodeType永远不会有多个节点,这对我来说似乎很浪费。

为什么结构的第二种形式会编译,但第一种形式不会?

编辑: 在进行了一些实验之后,我确定问题似乎在于BaseNodeType变体类型也包含SharedNodeType。我已相应更新了我的代码示例,但它仍然存在这样的问题:如果编译器在std::vector内部而不是其他情况下编译器能够解析这些类型。

1 个答案:

答案 0 :(得分:4)

使用类型作为成员要求它是完整的(显然,因为需要知道大小)。

因此有catch-22(变体的大小现在取决于SharedNodeType的大小,反之亦然)。

你需要破坏依赖循环。

意外解决方案

当您使用std::vector<BaseNodeType> intead BaseNodeType时,您遇到了意外变通办法/解决方案,并且您的特定库实现慷慨/不小心支持此功能。

据我所知,这从来就不是标准库容器的必需功能,实际上我想我记得在实例化时,规范而非强制 value_type是完整的。< / p>

现在,您仍然可以通过切换到Boost Container的vector模板(boost::containers::vector<BaseNodeType>)来可靠地使用此变通方法,显式支持不完整类型的实例化

Surefire解决方案

Boost Variant拥有自己的工具来处理专门用于创建(可能)递归变体类型的不完整类型。

您的原始样本将如下所示,已修复:

<强> Live On Coliru

#include <boost/variant.hpp>
#include <vector>
#include <string> 

struct SharedNodeType;
typedef float       TypeA;
typedef int         TypeB;
typedef std::string TypeC;
typedef char*       TypeD;

typedef boost::variant<TypeA, TypeB, TypeC, TypeD, boost::recursive_wrapper<SharedNodeType> > BaseNodeType;

struct SharedNodeType
{
     std::string nodeName;
     BaseNodeType node;
};

int main() {
    BaseNodeType bnt;
    SharedNodeType snt;
}