https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123610

            Bug ID: 123610
           Summary: Optional empty vector prefers invalid explicit
                    in_place_t construction
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: harald at gigawatt dot nl
  Target Milestone: ---

I'm not entirely sure if this is a valid bug, but it seems like clear enough
code that used to work that it's at least worth having a report for it.

=====

#include <optional>
#include <vector>
std::optional<std::vector<int>> foo() { return {{}}; }

=====

This was accepted up to GCC 12, but since GCC 13 it is rejected:
https://godbolt.org/z/WrxbMTfea:

<source>: In function 'std::optional<std::vector<int> > foo()':
<source>:3:51: error: converting to 'std::optional<std::vector<int> >' from
initializer list would use explicit constructor 'constexpr
std::optional<_Tp>::optional(std::in_place_t, _Args&& ...) [with _Args = {};
typename std::enable_if<__and_v<std::is_constructible<_Tp, _Args ...> >,
bool>::type <anonymous> = false; _Tp = std::vector<int>]'
    3 | std::optional<std::vector<int>> foo() { return {{}}; }
      |                                                   ^
<source>:3:51: error: converting to 'std::in_place_t' from initializer list
would use explicit constructor 'constexpr std::in_place_t::in_place_t()'
Compiler returned: 1

Clang, MSVC, EDG accept this.

Comments in bug 109247 suggest that GCC implements the correct intended
behaviour in the compiler and the other compilers are non-compliant, and I
think that probably applies here too: the invalid explicit
optional(std::in_place_t, Args&&...) constructor is more specialised than the
valid non-explicit optional(U&& value) constructor on account of U being a
template parameter, so technically, I think GCC is right to prefer that invalid
constructor.

At the same time though, the approach in bug 109247 was that it was okay to
implement a workaround to just make the code work. It's perfectly clear what
the user is trying to do, it works in other compilers, and there is no reason
to reject it. I hope that same approach can be taken here: it should be
perfectly clear that the intended behaviour is to construct an optional from an
empty vector, and it would be nice if that can somehow be made to work again.

Reply via email to