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

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           See Also|                            |https://gcc.gnu.org/bugzill
                   |                            |a/show_bug.cgi?id=80858

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Barry Revzin from comment #0)
> 1. It would be hugely beneficial if the diagnostic pointing to the
> originating line in my code for the problem.

I think this is PR 80858 (and also PR 106029).

> 2. It would be nice to have if (a) the diagnostic could explain why I didn't
> have a move constructor (though possibly this is over-fitting to this
> particular bug)

Maybe PR 53234 (and others).

>  or (b) the diagnostic could not dive into the depths of
> libstdc++ and just tell me that std::map<int, M> wasn't copyable because M
> wasn't copyable and stop at that point (this one doesn't feel like
> over-fitting though).

With a custom allocator it might actually be valid though, because "copying" M
is done by calling the allocator's construct function (or
allocator_traits::construct which calls std::construct_at) which might do
something funky (e.g. default construct a new object, ignoring the thing being
copied). In the general case, we don't know what "copying" the map does, so we
have to try it and see where it fails.

In reality, that never happens, and we could probably do something better for
std::map using std::allocator. But where to do that check and what to check for
isn't obvious. We could put it in the default allocator_traits::construct but
that's only one stack frame above std::construct_at so isn't really going to
reduce the diagnostic output much.

With this change:

--- /home/jwakely/gcc/13/include/c++/13.0.0/bits/stl_tree.h~    2022-07-04
13:39:45.482834753 +0100
+++ /home/jwakely/gcc/13/include/c++/13.0.0/bits/stl_tree.h     2022-07-04
13:39:42.575833073 +0100
@@ -935,10 +935,6 @@
       _Rb_tree(const _Rb_tree& __x)
       : _M_impl(__x._M_impl)
       {
+#if __cpp_if_constexpr
+        if constexpr (is_same_v<allocator_type, allocator<value_type>>)
+          static_assert( is_copy_constructible_v<value_type> );
+#endif
        if (__x._M_root() != 0)
          _M_root() = _M_copy(__x);
       }

The error becomes:

In file included from /home/jwakely/gcc/13/include/c++/13.0.0/map:60,
                 from 106176.C:1:
/home/jwakely/gcc/13/include/c++/13.0.0/bits/stl_tree.h: In instantiation of
'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Rb_tree(const
std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&) [with _Key = int;
_Val = std::pair<const int, C::M>; _KeyOfValue =
std::_Select1st<std::pair<const int, C::M> >; _Compare = std::less<int>; _Alloc
= std::allocator<std::pair<const int, C::M> >]':
/home/jwakely/gcc/13/include/c++/13.0.0/bits/stl_map.h:217:7:   required from
here
/home/jwakely/gcc/13/include/c++/13.0.0/bits/stl_tree.h:940:26: error: static
assertion failed
  940 |           static_assert( is_copy_constructible_v<value_type> );
      |                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/jwakely/gcc/13/include/c++/13.0.0/bits/stl_tree.h:940:26: note:
'std::is_copy_constructible_v<std::pair<const int, C::M> >' evaluates to false

This still doesn't tell you where the copy is required from in your own code
(PR 80858) and is arguably worse in some ways, because using a static_assert
before trying the std::construct_at call means you no longer get this part of
the output:

/home/jwakely/gcc/13/include/c++/13.0.0/bits/stl_pair.h:197:17: error: use of
deleted function 'C::M::M(const C::M&)'
106176.C:13:12: note: 'constexpr C::M::M(const C::M&)' is implicitly declared
as deleted because 'C::M' declares a move constructor or move assignment
operator
   13 |     struct M
      |            ^

Because the code no longer actually tries to use that copy constructor (except
inside a SFINAE context in the implementation of std::is_constructible) that is
not shown.

Reply via email to