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

            Bug ID: 84601
           Summary: std::optional<std::pair<int, int>> is not assignment
                    copyable
           Product: gcc
           Version: 8.0.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: romain.geissler at amadeus dot com
  Target Milestone: ---

Hi,

I am having trouble with this simple code snippet:

<<EOF
#include <optional>

using pair_t = std::pair<int, int>;
using opt_t = std::optional<pair_t>;

static_assert(std::is_copy_constructible_v<opt_t::value_type>);
static_assert(std::is_copy_assignable_v<opt_t::value_type>);

static_assert(std::is_copy_assignable_v<opt_t>); // assertion fails.

class A
{
    void f(const opt_t& opt)
    {
        _opt = opt; // compilation failure here. 
    }

    opt_t _opt;
};
EOF

Compiled with:  -std=gnu++17

gcc 8 says:
<<GCC_ERROR
file.cpp:9:15: error: static assertion failed
 static_assert(std::is_copy_assignable_v<opt_t>); // assertion fails.
               ^~~
file.cpp: In member function ‘void A::f(const opt_t&)’:
file.cpp:15:16: error: use of deleted function ‘std::optional<std::pair<int,
int> >& std::optional<std::pair<int, int> >::operator=(const
std::optional<std::pair<int, int> >&)’
         _opt = opt; // compilation failure here.
                ^~~    
In file included from file.cpp:1:
/remote/tools/Linux/2.6/1A/toolchain/x86_64-2.6.32-v4.0.14/include/c++/8.0.1/optional:612:11:
note: ‘std::optional<std::pair<int, int> >& std::optional<std::pair<int, int>
>::operat
or=(const std::optional<std::pair<int, int> >&)’ is implicitly deleted because
the default definition would be ill-formed:
     class optional
           ^~~~~~~~
/remote/tools/Linux/2.6/1A/toolchain/x86_64-2.6.32-v4.0.14/include/c++/8.0.1/optional:612:11:
error: use of deleted function ‘std::_Optional_base<_Tp, true, true>&
std::_Optional_ba
se<_Tp, true, true>::operator=(const std::_Optional_base<_Tp, true, true>&)
[with _Tp = std::pair<int, int>]’
/remote/tools/Linux/2.6/1A/toolchain/x86_64-2.6.32-v4.0.14/include/c++/8.0.1/optional:560:23:
note: ‘std::_Optional_base<_Tp, true, true>& std::_Optional_base<_Tp, true,
true>::oper
ator=(const std::_Optional_base<_Tp, true, true>&) [with _Tp = std::pair<int,
int>]’ is implicitly deleted because the default definition would be
ill-formed:
       _Optional_base& operator=(const _Optional_base&) = default;
                       ^~~~~~~~
/remote/tools/Linux/2.6/1A/toolchain/x86_64-2.6.32-v4.0.14/include/c++/8.0.1/optional:560:23:
error: use of deleted function ‘std::_Optional_payload<std::pair<int, int>,
true>& std:
:_Optional_payload<std::pair<int, int>, true>::operator=(const
std::_Optional_payload<std::pair<int, int>, true>&)’
/remote/tools/Linux/2.6/1A/toolchain/x86_64-2.6.32-v4.0.14/include/c++/8.0.1/optional:105:12:
note: ‘std::_Optional_payload<std::pair<int, int>, true>&
std::_Optional_payload<std::p
air<int, int>, true>::operator=(const std::_Optional_payload<std::pair<int,
int>, true>&)’ is implicitly deleted because the default definition would be
ill-formed:
     struct _Optional_payload
            ^~~~~~~~~~~~~~~~~
/remote/tools/Linux/2.6/1A/toolchain/x86_64-2.6.32-v4.0.14/include/c++/8.0.1/optional:159:24:
error: union member ‘std::_Optional_payload<std::pair<int, int>,
true>::<unnamed union>
::_M_payload’ with non-trivial ‘std::pair<_T1, _T2>& std::pair<_T1,
_T2>::operator=(typename
std::conditional<std::__and_<std::is_copy_assignable<_Tp>,
std::is_copy_assignable<_T2>
>::value, const std::pair<_T1, _T2>&, const std::__nonesuch_no_braces&>::type) 
>[with _T1 = int; _T2 = int; typename 
>std::conditional<std::__and_<std::is_copy_assignable<_Tp>, std::i
s_copy_assignable<_T2> >::value, const std::pair<_T1, _T2>&, const
std::__nonesuch_no_braces&>::type = const std::pair<int, int>&]’
           _Stored_type _M_payload;
                        ^~~~~~~~~~
GCC_ERROR

Clang 6 fails with similar reason (non trivial copy assignment operator on
union member):

<<CLANG_ERROR
file.cpp:9:1: error: static_assert failed due to requirement
'std::is_copy_assignable_v<opt_t>'
static_assert(std::is_copy_assignable_v<opt_t>); // assertion fails.
^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
file.cpp:15:14: error: object of type 'std::optional<std::pair<int, int> >'
cannot be assigned because its copy assignment operator is implicitly deleted
        _opt = opt; // compilation failure here.
             ^
/opt/1A/toolchain/x86_64-2.6.32-v4.0.14/lib64/gcc/x86_64-1a-linux-gnu/8.0.1/../../../../include/c++/8.0.1/optional:613:7:
note: copy assignment operator of 'optional<std::pair<int,
int> >' is implicitly deleted because base class '_Optional_base<std::pair<int,
int> >' has a deleted copy assignment operator
    : private _Optional_base<_Tp>,
      ^
/opt/1A/toolchain/x86_64-2.6.32-v4.0.14/lib64/gcc/x86_64-1a-linux-gnu/8.0.1/../../../../include/c++/8.0.1/optional:560:23:
note: explicitly defaulted function was implicitly deleted
 here
      _Optional_base& operator=(const _Optional_base&) = default;
                      ^
/opt/1A/toolchain/x86_64-2.6.32-v4.0.14/lib64/gcc/x86_64-1a-linux-gnu/8.0.1/../../../../include/c++/8.0.1/optional:584:30:
note: copy assignment operator of '_Optional_base<std::pai
r<int, int>, true, true>' is implicitly deleted because field '_M_payload' has
a deleted copy assignment operator
      _Optional_payload<_Tp> _M_payload;
                             ^
/opt/1A/toolchain/x86_64-2.6.32-v4.0.14/lib64/gcc/x86_64-1a-linux-gnu/8.0.1/../../../../include/c++/8.0.1/optional:159:24:
note: copy assignment operator of '_Optional_payload<std::
pair<int, int>, true>' is implicitly deleted because variant field '_M_payload'
has a non-trivial copy assignment operator
          _Stored_type _M_payload;
                       ^
CLANG_ERROR

Unless I missed something from the std::optional specification, we should be
able to use std::optional with std::pair's of integral types. Is this error
actually expected ?

Note: with the implementation from gcc 7 (and libstdc++ shipping with it), this
snippet was accepted (and clang 5 + libstdc++ from gcc 7 was also accepting
it).

Cheers,
Romain

Reply via email to