C++ boost::可选<&燃气轮机;在一个联盟里?
我有一个可选的POD结构,它将包含在联合中。C++ boost::可选<&燃气轮机;在一个联盟里?,c++,boost,optional-variables,C++,Boost,Optional Variables,我有一个可选的POD结构,它将包含在联合中。 boost::optional通过值保存其类型,因此我认为这可以工作: union helper { int foo; struct { char basic_info; struct details { //... }; boost::optional<details> extended_info; } bar;
boost::optional
通过值保存其类型,因此我认为这可以工作:
union helper
{
int foo;
struct
{
char basic_info;
struct details {
//...
};
boost::optional<details> extended_info;
} bar;
// ...
};
helper x = make_bar();
if( x.bar.extended_info )
{
// use x.bar.extended_info->elements
}
我考虑过实现details::operator bool()
来返回details::valid
变量,但这是模糊的,是对人类的伤害。boost::optional
清楚地记录了语法和意图,不需要进行检测工作
最后,helper
联合需要是POD,所以我不能进行任何动态分配-否则我将使用指针
对于语法上类似于在联合中可用的boost::optional的内容,您有什么建议吗?您不能将非POD类型用作联合中的字段。使用Boosi::变体或类似于C++的东西,而不是联合。只为与用C编写的模块兼容而保留union。正如其他人所提到的,理想的做法是从
union
更改为boost::variant
但是,如果这不可能,您可以实现POD近似值boost::optional
,如下所示:
实施
分配
数据存取
所以,结果并不是太糟糕。它不会让我感到很温暖和模糊,但它完成了任务。为什么你不能使用指针?允许您动态分配POD;它只是没有自动初始化。或者您的
助手
联合是否需要说明您的条
结构的大小?联合是按值复制的,并作为字节发送到另一个进程,因此我无法共享内存。将非POD类型转换为字节是未定义的行为。您必须使用POD类型进行二进制序列化。事实上,现在大多数都不使用二进制通信协议,而是使用基于XML的通信协议。你是对的。不幸的是,这是一个遗留产品,无法轻易更改。我一次咬一口大象。基本上是这样-使用boost::variant。我有很多将联合序列化为字节的遗留代码。我想现在就避免重构,你必须使用你描述的用于序列化的“笨重”助手,并用可选的转换变量。非POD对象的内存布局可能会通过编译器的下一个版本/service pack/编译选项进行优化,但方式不同,无需操作。mskfisher,请查看boost:apply_vistor。我在代码中使用它来序列化boost变体。
union helper
{
int foo;
struct
{
char basic;
struct details {
bool valid;
//...
} extended;
} bar;
// ...
};
template <typename T>
class Optional
{
T value;
bool valid;
public:
// for the if(var) test
operator bool() const { return valid; }
// for assigning a value
Optional<T> &operator=(T rhs)
{
value = rhs;
valid = true;
return *this;
}
// for assigning "empty"
Optional<T> &operator=(void *)
{
valid = false;
return *this;
}
// non-const accessors
T &operator*() { return value; }
T *operator->() { return &value; }
// const accessors
const T &operator*() const { return value; }
const T *operator->() const { return &value; }
};
Optional<details> additional_info;
Optional<details> more_info(additional_info);
// if there's no additional info
additional_info = 0;
// if there is extended info
details x;
// ...populate x...
additional_info = x;
if( extended_info )
{
extended_info->member;
// - or -
details &info = *extended_info;
}