C++ boost::可选<&燃气轮机;在一个联盟里?

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;

我有一个可选的POD结构,它将包含在联合中。
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;
}