升压::可选<>在工会?

时间:2011-01-12 20:53:53

标签: c++ boost optional-variables

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

但是由于bar元素,VS2008抱怨我的boost::optional<details>结构现在had a copy constructor

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

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

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

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

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

2 个答案:

答案 0 :(得分:13)

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

答案 1 :(得分:0)

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

但是,如果无法做到这一点,您可以按如下方式实现POD近似boost::optional<>

实施

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<>的常量实例,那么const访问器是必需的。

用法

与指针一样,Optional<T>没有默认状态,必须先进行初始化才能依赖它(无效或无效)。
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;
}

所以 - 它并没有变得太糟糕。它并没有让我感到温暖和模糊,但它完成了工作。