为什么我的结构不能有 boost::variant 类型的成员,但可以有 vector<boost::variant> 类型的成员?
Why can my struct not have a member of type boost::variant but can have a member of type vector<boost::variant>?
我定义了以下 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;
};
但是,上面写的结构 不会 编译,给出错误页面(太多不能包含在这里),主要与 "incomplete type not allowed."[=18 有关=]
第一个编译器错误是:
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
中,而不是在其他情况下。
使用类型作为成员需要它是完整的(显然,因为需要知道大小)。
因此有 catch-22(变体的大小现在取决于 SharedNodeType 的大小,反之亦然)。
你需要打破依赖循环。
意外解决方案
当你使用 std::vector<BaseNodeType>
而不是 BaseNodeType
和你的特定库实现 意外 workaround/solution
=50=]支持这个。
据我所知,这从来都不是标准库容器所必需的功能,事实上我想我记得规范 mandate value_type在实例化时完成。
现在,您仍然可以通过切换到 Boost Container 的 vector
模板 (boost::containers::vector<BaseNodeType>
) 来可靠地使用此解决方法,明确 支持不完整的实例化类型。
Surefire 解决方案
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, boost::recursive_wrapper<SharedNodeType> > BaseNodeType;
struct SharedNodeType
{
std::string nodeName;
BaseNodeType node;
};
int main() {
BaseNodeType bnt;
SharedNodeType snt;
}
我定义了以下 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;
};
但是,上面写的结构 不会 编译,给出错误页面(太多不能包含在这里),主要与 "incomplete type not allowed."[=18 有关=]
第一个编译器错误是:
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
中,而不是在其他情况下。
使用类型作为成员需要它是完整的(显然,因为需要知道大小)。
因此有 catch-22(变体的大小现在取决于 SharedNodeType 的大小,反之亦然)。
你需要打破依赖循环。
意外解决方案
当你使用 std::vector<BaseNodeType>
而不是 BaseNodeType
和你的特定库实现 意外 workaround/solution
=50=]支持这个。
据我所知,这从来都不是标准库容器所必需的功能,事实上我想我记得规范 mandate value_type在实例化时完成。
现在,您仍然可以通过切换到 Boost Container 的 vector
模板 (boost::containers::vector<BaseNodeType>
) 来可靠地使用此解决方法,明确 支持不完整的实例化类型。
Surefire 解决方案
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, boost::recursive_wrapper<SharedNodeType> > BaseNodeType;
struct SharedNodeType
{
std::string nodeName;
BaseNodeType node;
};
int main() {
BaseNodeType bnt;
SharedNodeType snt;
}