我有一个可选的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<>
在联合中可用的东西吗?
答案 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;
}
所以 - 它并没有变得太糟糕。它并没有让我感到温暖和模糊,但它完成了工作。