Opened 8 years ago

Closed 8 years ago

#10839 closed Bugs (fixed)

dereferencing of rvalue optional<T&> fails due to invalid assignment of rvalue to non-const ref

Reported by: stefan.bund@… Owned by: akrzemi1
Milestone: Boost 1.58.0 Component: optional
Version: Boost 1.57.0 Severity: Problem
Keywords: Cc:

Description

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).

Attachments (2)

optional.hpp.diff (2.7 KB ) - added by stefa 8 years ago.
optional.hpp.2.diff (2.4 KB ) - added by stefan.bund@… 8 years ago.
correct version of patch

Download all attachments as: .zip

Change History (6)

by stefa, 8 years ago

Attachment: optional.hpp.diff added

comment:1 by anonymous, 8 years ago

I just realized, that such a move member is already defined, it's just not used. I have attached a patch which solves the problem for me.

by stefan.bund@…, 8 years ago

Attachment: optional.hpp.2.diff added

correct version of patch

comment:2 by viboes, 8 years ago

Component: Noneoptional
Owner: set to Fernando Cacciola

comment:3 by akrzemi1, 8 years ago

Owner: changed from Fernando Cacciola to akrzemi1
Status: newassigned

comment:4 by akrzemi1, 8 years ago

Milestone: To Be DeterminedBoost 1.58.0
Resolution: fixed
Status: assignedclosed

Value accessors in rvalues of optional references now work correctly.

Note: See TracTickets for help on using tickets.