https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92193
Jonathan Wakely <redi at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2019-11-29 Ever confirmed|0 |1 --- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> --- This results in a far worse experience for users in C++20, where lots more things become constexpr. With the patch I suggested in Bug 92727 comment 4 the diagnostic in C++17 mode would be: In file included from /home/jwakely/gcc/10/include/c++/10.0.0/vector:67, from up.cc:1: /home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_vector.h: In instantiation of 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = X; _Alloc = std::allocator<X>; std::vector<_Tp, _Alloc>::value_type = X]': up.cc:14:18: required from here /home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_vector.h:1188:18: error: static assertion failed 1188 | static_assert(is_copy_constructible_v<value_type>); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ But compiling the exact same code with -std=gnu++2a gives: In file included from /home/jwakely/gcc/10/include/c++/10.0.0/vector:67, from up.cc:1: /home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_vector.h: In instantiation of 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = X; _Alloc = std::allocator<X>; std::vector<_Tp, _Alloc>::value_type = X]': up.cc:14:18: required from here /home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_vector.h:1188:18: error: static assertion failed 1188 | static_assert(is_copy_constructible_v<value_type>); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from /home/jwakely/gcc/10/include/c++/10.0.0/ext/alloc_traits.h:34, from /home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_uninitialized.h:67, from /home/jwakely/gcc/10/include/c++/10.0.0/vector:66, from up.cc:1: /home/jwakely/gcc/10/include/c++/10.0.0/bits/alloc_traits.h: In instantiation of 'static constexpr void std::allocator_traits<std::allocator<_Up> >::construct(std::allocator_traits<std::allocator<_Up> >::allocator_type&, _Up*, _Args&& ...) [with _Up = X; _Args = {const X&}; _Tp = X; std::allocator_traits<std::allocator<_Up> >::allocator_type = std::allocator<X>]': /home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_vector.h:1193:30: required from 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = X; _Alloc = std::allocator<X>; std::vector<_Tp, _Alloc>::value_type = X]' up.cc:14:18: required from here /home/jwakely/gcc/10/include/c++/10.0.0/bits/alloc_traits.h:504:20: error: use of deleted function 'X::X(const X&)' 504 | noexcept(noexcept(::new((void*)__p) _Up(std::declval<_Args>()...))) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ up.cc:6:7: note: 'X::X(const X&)' is implicitly deleted because the default definition would be ill-formed: 6 | class X { | ^ up.cc:6:7: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Y; _Dp = std::default_delete<Y>]' In file included from /home/jwakely/gcc/10/include/c++/10.0.0/memory:82, from up.cc:2: /home/jwakely/gcc/10/include/c++/10.0.0/bits/unique_ptr.h:456:7: note: declared here 456 | unique_ptr(const unique_ptr&) = delete; | ^~~~~~~~~~ In file included from /home/jwakely/gcc/10/include/c++/10.0.0/ext/alloc_traits.h:34, from /home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_uninitialized.h:67, from /home/jwakely/gcc/10/include/c++/10.0.0/vector:66, from up.cc:1: /home/jwakely/gcc/10/include/c++/10.0.0/bits/alloc_traits.h: In instantiation of 'static constexpr void std::allocator_traits<std::allocator<_Up> >::construct(std::allocator_traits<std::allocator<_Up> >::allocator_type&, _Up*, _Args&& ...) [with _Up = X; _Args = {const X&}; _Tp = X; std::allocator_traits<std::allocator<_Up> >::allocator_type = std::allocator<X>]': /home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_vector.h:1193:30: required from 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = X; _Alloc = std::allocator<X>; std::vector<_Tp, _Alloc>::value_type = X]' up.cc:14:18: required from here /home/jwakely/gcc/10/include/c++/10.0.0/bits/alloc_traits.h:509:21: error: no matching function for call to 'construct_at(X*&, const X&)' 509 | std::construct_at(__p, std::forward<_Args>(__args)...); | ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from /home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_tempbuf.h:60, from /home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_algo.h:62, from /home/jwakely/gcc/10/include/c++/10.0.0/vector:62, from up.cc:1: /home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_construct.h:94:5: note: candidate: 'template<class _Tp, class ... _Args> constexpr decltype (::new(void*(0)) _Tp) std::construct_at(_Tp*, _Args&& ...)' 94 | construct_at(_Tp* __location, _Args&&... __args) | ^~~~~~~~~~~~ /home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_construct.h:94:5: note: template argument deduction/substitution failed: /home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_construct.h: In substitution of 'template<class _Tp, class ... _Args> constexpr decltype (::new(void*(0)) _Tp) std::construct_at(_Tp*, _Args&& ...) [with _Tp = X; _Args = {const X&}]': /home/jwakely/gcc/10/include/c++/10.0.0/bits/alloc_traits.h:509:21: required from 'static constexpr void std::allocator_traits<std::allocator<_Up> >::construct(std::allocator_traits<std::allocator<_Up> >::allocator_type&, _Up*, _Args&& ...) [with _Up = X; _Args = {const X&}; _Tp = X; std::allocator_traits<std::allocator<_Up> >::allocator_type = std::allocator<X>]' /home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_vector.h:1193:30: required from 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = X; _Alloc = std::allocator<X>; std::vector<_Tp, _Alloc>::value_type = X]' up.cc:14:18: required from here /home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_construct.h:96:17: error: use of deleted function 'X::X(const X&)' 96 | -> decltype(::new((void*)0) _Tp(std::declval<_Args>()...)) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ That's because in C++20 some of the code following the static assertion involves a constexpr function, which calls another constexpr function, which calls another ... and all of them get evaluated and barf out their errors. The whole point of the static_assert is to stop that happening.