public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libstdc++/112942] New: swap(variant&, variant&) is incorrectly marked as deleted
@ 2023-12-10  0:28 kotonartem at protonmail dot com
  2023-12-10  0:30 ` [Bug libstdc++/112942] " pinskia at gcc dot gnu.org
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: kotonartem at protonmail dot com @ 2023-12-10  0:28 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 112942
           Summary: swap(variant&, variant&) is incorrectly marked as
                    deleted
           Product: gcc
           Version: 13.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: kotonartem at protonmail dot com
  Target Milestone: ---

GCC rejects the following code (when using libstdc++):

```
#include <variant>

struct A
{};

void swap(A&, A&) = delete;

void foo()
{
    using V = std::variant<A>;
    V a, b;

    using std::swap; // this is unnecessary due to ADL
    swap(a, b);
}
```

with the following message:

```
<source>: In function 'void foo()':
<source>:14:9: error: use of deleted function
'std::enable_if_t<(!((is_move_constructible_v<_Types> && ...) &&
(is_swappable_v<_Types> && ...)))> std::swap(variant<_Types ...>&,
variant<_Types ...>&) [with _Types = {A};
enable_if_t<(!((is_move_constructible_v<_Types> && ...) &&
(is_swappable_v<_Types> && ...)))> = void]'
   14 |     swap(a, b);
      |     ~~~~^~~~~~
In file included from <source>:1:
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/variant:1303:5: note:
declared here
 1303 |     swap(variant<_Types...>&, variant<_Types...>&) = delete;
      |     ^~~~
```

The compiler explorer link: https://godbolt.org/z/5od4s5cf3.

There is also a similar test case that expects the current behavior:
https://github.com/gcc-mirror/gcc/blob/c250ff9/libstdc%2B%2B-v3/testsuite/20_util/variant/compile.cc#L294-L300.
> ```
> // Not swappable, and variant<C> not swappable via the generic std::swap.
> struct C { };
> void swap(C&, C&) = delete;
> 
> static_assert( !std::is_swappable_v<variant<C>> );
> static_assert( !std::is_swappable_v<variant<int, C>> );
> static_assert( !std::is_swappable_v<variant<C, int>> );
> ```

I believe that this behavior is incorrect and the variant should indeed be
swappable even if `swap(A&, A&)` is deleted.

My reasoning is that in [variant.specalg] the `std::is_swappable_v<T_i>`
requirement is mentioned under "Constraints" section, which, according to
[structure.specifications], describes "the conditions for the function's
participation in overload resolution". That is in contrast to "Mandates"
section, which would render the program ill-formed.

And since the `swap(variant<A>&, variant<A>&)` overload is not considered, the
generic `template<class T> void swap(T& a, T& b)` should be chosen instead.
Unlike the former overload, it only requires `T` (aka `variant<A>`) to be both
move constructible and move assignable, which it is.

It should be noted that libc++ handles this case correctly, i.e.
`std::is_swappable_v<std::variant<A>>` is `true`.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-12-10 12:37 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-10  0:28 [Bug libstdc++/112942] New: swap(variant&, variant&) is incorrectly marked as deleted kotonartem at protonmail dot com
2023-12-10  0:30 ` [Bug libstdc++/112942] " pinskia at gcc dot gnu.org
2023-12-10  0:35 ` pinskia at gcc dot gnu.org
2023-12-10  0:54 ` kotonartem at protonmail dot com
2023-12-10  1:04 ` pinskia at gcc dot gnu.org
2023-12-10 12:36 ` [Bug libstdc++/112942] [LWG2766] " redi at gcc dot gnu.org
2023-12-10 12:37 ` redi at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).