5

我有一个可选的 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
}

但是 VS2008 抱怨说我的bar结构现在由于元素而具有一个复制构造函数。boost::optional<details>

作为替代,我添加了一个布尔标志来指示可选参数是否有效,但它很笨重:

union helper
{
    int foo;
    struct 
    {
        char basic;
        struct details {
            bool valid;
            //...
        } extended;
    } bar;
    //  ...
};

我考虑实施details::operator bool()以返回details::valid变量,但这很模糊并且对人类不利。
boost::optional<>清楚地记录语法和意图,不需要侦探工作。

最后,helper联合需要是 POD,所以我不能做任何动态分配 - 否则我会使用指针。

boost::optional<>对在联合中可用的语法相似的东西有什么建议吗?

4

2 回答 2

13

您不能将非 POD 类型用作联合中的字段。在 C++ 中使用 boost::variant 或类似的东西而不是联合。保留 union 只是为了与用 C 编写的模块兼容。

于 2011-01-12T20:58:02.800 回答
0

正如其他人所提到的,理想的做法是将 a 更改union为 a boost::variant<>

但是,如果这不可能,您可以实现boost::optional<>如下的 POD 近似值:

执行

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;  }
};

如果您持有 的 const 实例,则 const 访问器是必需的Optional<>

用法

像指针一样,Optional<T>没有默认状态,必须先初始化,然后才能依赖它(null 或 not)。
与 不同boost::optional<T>Optional<T>不能从其T值类型构造,只能从另一个构造Optional<T>
如果您真的想在构造时对其进行值或空初始化,您可以使用operator Optional<T>(). 我选择不这样做。

建造

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;
}

所以 - 结果并没有太糟糕。它不会让我感到很温暖和模糊,但它可以完成工作。

于 2011-01-13T20:33:32.203 回答