It seems to me there should be four variants of boost::optional
optional<Foo>
=> holds a mutable Foo and can be reassigned after initializationoptional<Foo const> const
=> holds a const Foo and can't be reassigned after initializationoptional<Foo> const
=> (should?) hold a mutable Foo but can't be reassigned after initializationoptional<Foo const>
=> (should?) hold a const Foo and can be reassigned after initialization
The first 2 cases work as expected. But the optional<Foo> const
dereferences to a const Foo, and the optional<Foo const>
doesn't allow reassignment after initialization (as touched upon in this question).
The reassignment of the const value types is specifically what I ran into, and the error is:
/usr/include/boost/optional/optional.hpp:486: error: passing ‘const Foo’ as ‘this’ argument of ‘Foo& Foo::operator=(const Foo&)’ discards qualifiers [-fpermissive]
And it happens here:
void assign_value(argument_type val,is_not_reference_tag) { get_impl() = val; }
After construction, the implementation uses the assignment operator for the type you parameterized the optional with. It obviously doesn't want a left-hand operand which is a const value. But why shouldn't you be able to reset a non-const optional to a new const value, such as in this case:
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();
}
Some Questions:
Am I right that wanting this is conceptually fine, and not being able to do it is just a fluke in the implementation?
If I don't edit the boost sources, what would be a clean way to implement logic like in the loop above without scrapping boost::optional altogether?
If this does make sense and I were to edit the boost::optional source (which I've already had to do to make it support movable types, though I suspect they'll be doing that themselves soon) then what minimally invasive changes might do the trick?