[Boost-bugs] [Boost C++ Libraries] #10839: dereferencing of rvalue optional<T&> fails due to invalid assignment of rvalue to non-const ref

Subject: [Boost-bugs] [Boost C++ Libraries] #10839: dereferencing of rvalue optional<T&> fails due to invalid assignment of rvalue to non-const ref
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2014-12-02 19:17:01


#10839: dereferencing of rvalue optional<T&> fails due to invalid assignment of
rvalue to non-const ref
---------------------------+------------------------------
 Reporter: stefan.bund@… | Type: Bugs
   Status: new | Milestone: To Be Determined
Component: None | Version: Boost 1.57.0
 Severity: Problem | Keywords:
---------------------------+------------------------------
 Compiling the following code using `g++-4.9.2 -std=gnu++1y`
 {{{
 #include <boost/optional.hpp>

 int main(int, char const **)
 {
     int i (0);
     boost::optional<int &> opt (i);
     // we use std::move here to force opt to be an rvalue. The same error
     // is triggered if the optional is returned from a function call
     return * std::move(opt);
 }
 }}}

 results in the error message

> lib/boost/install/include/boost/optional/optional.hpp:1010:89: error:
 invalid initialization of non-const reference of type
 'boost::optional<int&>::reference_type_of_temporary_wrapper {aka int&}'
 from an rvalue of type 'boost::move_detail::remove_reference<int&>::type
 {aka int}'

 Looking at the source code in `optional.hpp`, the culprit seems to be:

 {{{
 template <class T>
 class optional : public optional_detail::optional_base<T>
 {
     // ...

     reference_type_of_temporary_wrapper operator *() &&
     { return boost::move(this->get()) ; }

      // ...
 };
 }}}

 `reference_type_of_termporary_wrapper` is typedefed to `int &` as is to be
 expected. If I am not mistaken, the `std::move` call however is not
 correct in this case: it converts it's `int &` argument (the result of
 `this->get()`) to `int &&` which is ''not'' implicitly convertible to `int
 &` (the return type).

 This problem only occurs with `optional<T&>` not with `optional<T const
 &>` since for the latter, `reference_type_of_temporary_wrapper` is `int
 const &` and `int &&` is convertible to `int const &`.

 Possible resolution: If the type of the optional is a reference type,
 don't apply `std::move` (e.g. add a static `move` member function to
 `types_when_isnt_ref` and `types_when_is_ref` and use that member instead
 of `boost::move` here).

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/10839>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:17 UTC