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