Opened 6 years ago

Last modified 6 years ago

#12788 reopened Bugs

optional 1.63 no longer can be initialized from '<brace-enclosed initializer list>'

Reported by: piotrwn1@… Owned by: akrzemi1
Milestone: To Be Determined Component: optional
Version: Boost 1.63.0 Severity: Problem
Keywords: Cc: akrzemi1

Description

The code below compiles fine with boost.1.62 - but it can't compile with boost1.63:

    struct S
    {
        int a;
        int b;
    };
    boost::optional<S> so;
    so = {1,2};

With error:

error: no match for 'operator=' (operand types are 'boost::optional<S>' and '<brace-enclosed initializer list>')

Change History (9)

comment:1 by piotrwn1@…, 6 years ago

To clarify: compiled with gcc5.3 with -std=c++14

comment:3 by rschiele@…, 6 years ago

Note that you can get the old behavior back by defining BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX for your code.

comment:4 by akrzemi1, 6 years ago

Owner: changed from Fernando Cacciola to akrzemi1
Status: newassigned

comment:5 by akrzemi1, 6 years ago

Cc: akrzemi1 added
Resolution: invalid
Status: assignedclosed

This breakage is intentional.

In fact the previous behavior was inconsistent with std::optional and error-prone. Braces should deduce type optional<T>, not to T. For more details of why it was confusing, see here:

http://stackoverflow.com/questions/40391244/difference-between-boost-optional-and-stdexperimental-optional-assignment/40677193#40677193

Now the following puts the optional into no-value state:

boost::optional<S> so;
so = {};

Just like std::optional.

comment:6 by piotrwn1@…, 6 years ago

Well, the OP problem was not with empty braces.

comment:7 by piotrwn1@…, 6 years ago

This is real problem, please do not close.

See this code:

#include <boost/optional.hpp>
#include <optional>
#include <iostream>

#define PRN(a) std::cout << #a "\n";
#define DEF(a, r) a { PRN(a); r }

struct Verbose {
    DEF(Verbose(int,double),)
    DEF(Verbose(),)
    DEF(~Verbose(),)
    DEF(Verbose(const Verbose&),)
    DEF(Verbose(Verbose&&),)
    DEF(Verbose& operator = (const Verbose&), return *this;)
    DEF(Verbose& operator = (Verbose&&), return *this;)
};

using vbo = boost::optional<Verbose>;
using vso = std::optional<Verbose>;

int main() {
    vbo bo;
    vso so;
    
    bo = {1,1.1}; // works for boost1.62, not for boost.1.63
    so = {1,1.1}; // works for std::optional
}

Link do demo: http://melpon.org/wandbox/permlink/wDvuR7T9b7bI5fHq

comment:8 by piotrwn1@…, 6 years ago

Resolution: invalid
Status: closedreopened

comment:9 by Jürgen Hunold, 6 years ago

Create an auto test from the example

See https://github.com/boostorg/optional/pull/28

Note: See TracTickets for help on using tickets.