在我看来,应该有boost::optional
optional<Foo>
=&gt;持有一个可变的Foo,可以在初始化后重新分配
optional<Foo const> const
=&gt;持有const Foo,初始化后无法重新分配
optional<Foo> const
=&gt; (应该?)持有一个可变的Foo,但在初始化后不能重新分配
optional<Foo const>
=&gt; (应该?)持有一个const Foo,可以在初始化后重新分配
前2个案例按预期工作。但optional<Foo> const
取消引用const Foo,optional<Foo const>
不允许在初始化后重新分配(如this question中所述)。
const值类型的重新分配是我遇到的具体内容,错误是:
/usr/include/boost/optional/optional.hpp:486:错误:将'const Foo'作为'Foo&amp;的'this'参数传递Foo :: operator =(const Foo&amp;)'丢弃限定符[-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,但我怀疑他们会自己这样做那么什么微创改变可以做到这一点?
答案 0 :(得分:3)
所以基本上问题似乎与optional& optional<T (not a ref)>::operator= ( T const& rhs )
boost::optional<const Foo> theFoo;
中的这个注释有关:
注意:如果*已初始化,则使用T的赋值运算符,否则使用其复制构造函数。
也就是说,假设您有boost::optional<>
。由于默认构造的theFoo=defaultFoo;
为空,因此语句为:
defaultFoo
应该是指“将构造theFoo
复制到const Foo
的内部存储中”。由于内部存储中没有任何内容,这是有道理的,即使内部存储应该容纳theFoo
。完成后,theFoo
将不会为空。
theFoo=defaultFoo;
包含值后,语句
defaultFoo
应表示“将theFoo
分配到theFoo
内部存储空间中的对象”。但const
的内部存储不可分配(因为它是boost::optional<...>
),因此这会引发(编译时?)错误。
不幸的是,您会注意到最后两个语句是相同的,但在概念上需要不同的编译时行为。但是,没有什么可以让编译器说出两者之间的区别。
特别是在您描述的场景中,将T
的赋值运算符定义为具有语义可能更有意义:
如果*已初始化,则首先销毁其当前内容。然后使用
T
的拷贝构造函数。
毕竟,通过说*theFoo = rhs
,完全有可能调用{{1}}的赋值运算符(如果这是你真正想做的)。
答案 1 :(得分:2)
回答你的三个问题:
您还可以尝试this proposal中的可选参考实现。
答案 2 :(得分:2)
(1)一个人对“应该”行为的看法取决于选项是“零或一个任意类型对象的容器”或< em>“一个类型的瘦代理,具有附加功能”。现有代码使用后一种思想,通过这样做,它删除了列表中“四种不同行为”的一半。这降低了复杂性,并使您无意中引入低效的用法。
(2)对于其值可复制的任何Foo
类型,可以通过创建一个新的可选项来轻松切换可变和不可变的选项。因此,在给定的情况下,您可以将其简单地变为可变,然后将其复制到不可变的值中。
optional<Foo> theMutableFoo (maybeGetFoo());
while (someCondition) {
optional<Foo const> theFoo (theMutableFoo);
// do some work involving calling some methods on theFoo
// ...but they should only be const ones
// ...therefore, just don't use theMutableFoo in here!
theMutableFoo = maybeGetFoo();
}
鉴于模型是一个类型的“瘦代理”,如果类型没有包含在一个可选项中,这就是你必须要做的事情。在这种情况下,普通的const值类型需要相同的处理。
(3)我们必须跟进information given by @Andrzej才能找到答案。但是这样的实现更改可能不会比每次创建新的可选项更好(如上面的循环中所示)。最好接受现有的设计。