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?
Foo const* p = /*...*/ ; *p = Foo();. Now replace the pointer with optional:optional<Foo const> p; *p = Foo();. Same behaviour. - R. Martinho Fernandesboost::optional<T>is essentially a drop-in replacement for aT. If you have something const, then you don't reassign it. If you want to reassign it, don't make it const. - Kerrek SBFoo const *p = gen(...);p=gen(...);. This should work fine forFoo const *, but doesn't work foroptional<const Foo>. - Managuoptional<Foo>andoptional<const Foo>both make a copy for the user. Why do you want to restrict the constness of their copy? It seems to be the same a returning a constant copy of an object to the user from a function. - Dave S