【发布时间】:2012-07-12 19:31:36
【问题描述】:
在我看来boost::optional应该有四种变体
optional<Foo>=> 持有可变的 Foo 并且可以在初始化后重新分配optional<Foo const> const=> 持有一个 const Foo,初始化后不能重新赋值optional<Foo> const=>(应该?)持有一个可变的 Foo 但初始化后不能重新分配optional<Foo const>=>(应该?)持有一个 const Foo 并且可以在初始化后重新分配
前 2 个案例按预期工作。但是optional<Foo> const 取消对 const Foo 的引用,而optional<Foo const> 不允许在初始化后重新分配(如this question 中所述)。
const 值类型的重新分配是我遇到的具体情况,错误是:
/usr/include/boost/optional/optional.hpp:486:错误:将 'const Foo' 作为 'Foo& Foo::operator=(const Foo&)' 的 'this' 参数传递会丢弃限定符 [-fpermissive]
它发生在这里:
void assign_value(argument_type val,is_not_reference_tag) { get_impl() = val; }
在构造之后,实现将赋值运算符用于您参数化可选项的类型。它显然不想要一个 const 值的左操作数。但是为什么你不能将一个非 const 可选项重置为一个新的 const 值,例如在这种情况下:
optional<Foo const> theFoo (maybeGetFoo());
while (someCondition) {
// do some work involving calling some methods on theFoo
// ...but they should only be const ones
theFoo = maybeGetFoo();
}
一些问题:
我是否正确,想要这个在概念上是好的,而不能做到这一点只是实施中的侥幸吗?
如果我不编辑 boost 源,那么在不完全废弃 boost::optional 的情况下实现上述循环中的逻辑的干净方法是什么?
如果这确实有意义并且我要编辑 boost::optional 源(我已经不得不这样做support movable types,尽管我怀疑他们很快就会自己这样做)那么有哪些微创改变可以解决问题呢?
【问题讨论】:
-
考虑
Foo const* p = /*...*/ ; *p = Foo();。现在将指针替换为可选的:optional<Foo const> p; *p = Foo();。相同的行为。 -
boost::optional<T>本质上是T的替代品。如果你有一些 const,那么你不要重新分配它。如果您想重新分配它,请不要将其设为 const。 -
虽然这不是所问的,但问题可能更多的是针对
Foo const *p = gen(...);p=gen(...);。这应该适用于Foo const *,但不适用于optional<const Foo>。 -
@Managu 因为 optional 存在以提供值语义,而带有指针的示例正在处理引用语义。
-
optional<Foo>和optional<const Foo>都为用户制作副本。为什么要限制其副本的常量性?从函数返回一个对象的常量副本给用户似乎是一样的。
标签: c++ boost assignment-operator const-correctness boost-optional