This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

### 3638. `vector<bool>::swap(reference, reference)` is useless

Section: 22.3.12 [vector.bool] Status: New Submitter: Jonathan Wakely Opened: 2021-11-12 Last modified: 2022-01-22

Priority: 3

View other active issues in [vector.bool].

View all other issues in [vector.bool].

View all issues with New status.

Discussion:

`vector<bool>` provides a static member function that can be used to swap rvalues of type `vector<bool>::reference` like so:

>     vector<bool> v{true, false};
>     vector<bool>::swap(v[0], v[1]);

This is not useful. Nobody calls `swap` like that. This fails to make `v[0]` swappable with `v[1]` as per 16.4.4.3 [swappable.requirements]. The similar SGI STL `bit_vector` class that `vector<bool>` is partially inspired by has a "global function" with the same signature, described as:

> "Swaps the bits referred to by `x` and `y`. This is a global function, not a member function. It is necessary because the ordinary version of `swap` takes arguments of type `T&`, and `bit_vector::reference` is a class, not a built-in C++ reference."

For some reason this became a static member function of `vector<bool>` in the C++ standard.

We should restore the intended functionality, and deprecate the useless function.

Previous resolution [SUPERSEDED]:

> This wording is relative to N4901.

> 1. Create a new subclause [vector.bool.general] below 22.3.12 [vector.bool] and move paragraphs p1-p3 (including the class template `vector<bool, Allocator>` partial specialization synopsis) into that subclause.

> 2. Add to the synopsis in [vector.bool.general] p1 (née 22.3.12 [vector.bool] p1):

>    >     […]
>    >     // bit reference
>    >     class reference {
>    >       friend class vector;
>    >       constexpr reference() noexcept;
>    >     public:
>    >       constexpr reference(const reference&) = default;
>    >       constexpr ~reference();
>    >       constexpr operator bool() const noexcept;
>    >       constexpr reference& operator=(bool x) noexcept;
>    >       constexpr reference& operator=(const reference& x) noexcept;
>    >       constexpr const reference& operator=(bool x) const noexcept;
>    >       constexpr void flip() noexcept; // flips the bit

>    >       friend constexpr void swap(reference x, reference y) noexcept;
>    >       friend constexpr void swap(reference x, bool& y) noexcept;
>    >       friend constexpr void swap(bool& x, reference y) noexcept;
>    >     };
>    >     […]

> 3. Remove the static `swap` function from the class template `vector<bool, Allocator>` partial specialization synopsis:

>    >     […]
>    >     constexpr void swap(vector&);
>    >     constexpr static void swap(reference x, reference y) noexcept;
>    >     constexpr void flip() noexcept; // flips all bits
>    >     […]

> 4. Create a new subclause [vector.bool.ref] after p3, with p4 as its first paragraph, and add after it:

>    > 22.3.12.? Class `vector<bool, Allocator>::reference` [vector.bool.ref]

>    > -1- `reference` is a class that simulates the behavior of references of a single bit in `vector<bool>`. The conversion function returns `true` when the bit is set, and `false` otherwise. The assignment operators set the bit when the argument is (convertible to) `true` and clear it otherwise. `flip` reverses the state of the bit.

>    >     constexpr void flip() noexcept;

>    > > -?- Effects: `*this = !*this;`

>    >      friend constexpr void swap(reference x, reference y) noexcept;
>    >      friend constexpr void swap(reference x, bool& y) noexcept;
>    >      friend constexpr void swap(bool& x, reference y) noexcept;

>    > > -?- Effects: Exchanges the contents of `x` and `y` as if by:

>    > > >     bool b = x;
>    > > >     x = y;
>    > > >     y = b;

> 5. Create a new subclause [vector.bool.mem] after that, containing the paragraphs describing `flip()` and the `hash` specialization:

>    > 22.3.12.? Class `vector<bool, Allocator>` members [vector.bool.mem]

>    >     constexpr void flip() noexcept;

>    > > -1- Effects: Replaces each element in the container with its complement.

>    >      constexpr static void swap(reference x, reference y) noexcept;

>    > > -6- Effects: Exchanges the contents of `x` and `y` as if by:

>    > > >     bool b = x;
>    > > >     x = y;
>    > > >     y = b;

>    >     template<class Allocator> struct hash<vector<bool, Allocator>>;

>    > > -7- The specialization is enabled (20.14.19 [unord.hash]).

> 6. Create a new subclause [depr.vector.bool.swap] after D.21 [depr.string.capacity]

>    > D.? Deprecated `vector<bool, Allocator>` swap [depr.vector.bool.swap]

>    > -?- The following member is declared in addition to those members specified in 22.3.12 [vector.bool]:

>    >     namespace std {
>    >       template<class Allocator> class vector<bool, Allocator> {
>    >       public:
>    >         constexpr static void swap(reference x, reference y) noexcept;
>    >       };
>    >     }

>    >     constexpr static void swap(reference x, reference y) noexcept;

>    > > -?- Effects: `swap(x, y)`.

[2022-01-22; Jonathan replaces `swap(x, y)` in the Annex D wording, following reflector discussion about lookup for `swap` finding itself in that context. ]

[2022-01-30; Reflector poll]

Set priority to 3 after reflector poll.

Proposed resolution:

This wording is relative to N4901.

1. Create a new subclause [vector.bool.general] below 22.3.12 [vector.bool] and move paragraphs p1-p3 (including the class template `vector<bool, Allocator>` partial specialization synopsis) into that subclause.

2. Add to the synopsis in [vector.bool.general] p1 (née 22.3.12 [vector.bool] p1):

   >     […]
   >     // bit reference
   >     class reference {
   >       friend class vector;
   >       constexpr reference() noexcept;
   >     public:
   >       constexpr reference(const reference&) = default;
   >       constexpr ~reference();
   >       constexpr operator bool() const noexcept;
   >       constexpr reference& operator=(bool x) noexcept;
   >       constexpr reference& operator=(const reference& x) noexcept;
   >       constexpr const reference& operator=(bool x) const noexcept;
   >       constexpr void flip() noexcept; // flips the bit

   >       friend constexpr void swap(reference x, reference y) noexcept;
   >       friend constexpr void swap(reference x, bool& y) noexcept;
   >       friend constexpr void swap(bool& x, reference y) noexcept;
   >     };
   >     […]

3. Remove the static `swap` function from the class template `vector<bool, Allocator>` partial specialization synopsis:

   >     […]
   >     constexpr void swap(vector&);
   >     constexpr static void swap(reference x, reference y) noexcept;
   >     constexpr void flip() noexcept; // flips all bits
   >     […]

4. Create a new subclause [vector.bool.ref] after p3, with p4 as its first paragraph, and add after it:

   > 22.3.12.? Class `vector<bool, Allocator>::reference` [vector.bool.ref]

   > -1- `reference` is a class that simulates the behavior of references of a single bit in `vector<bool>`. The conversion function returns `true` when the bit is set, and `false` otherwise. The assignment operators set the bit when the argument is (convertible to) `true` and clear it otherwise. `flip` reverses the state of the bit.

   >     constexpr void flip() noexcept;

   > > -?- Effects: `*this = !*this;`

   >      friend constexpr void swap(reference x, reference y) noexcept;
   >      friend constexpr void swap(reference x, bool& y) noexcept;
   >      friend constexpr void swap(bool& x, reference y) noexcept;

   > > -?- Effects: Exchanges the contents of `x` and `y` as if by:

   > > >     bool b = x;
   > > >     x = y;
   > > >     y = b;

5. Create a new subclause [vector.bool.mem] after that, containing the paragraphs describing `flip()` and the `hash` specialization:

   > 22.3.12.? Class `vector<bool, Allocator>` members [vector.bool.mem]

   >     constexpr void flip() noexcept;

   > > -1- Effects: Replaces each element in the container with its complement.

   >      constexpr static void swap(reference x, reference y) noexcept;

   > > -6- Effects: Exchanges the contents of `x` and `y` as if by:

   > > >     bool b = x;
   > > >     x = y;
   > > >     y = b;

   >     template<class Allocator> struct hash<vector<bool, Allocator>>;

   > > -7- The specialization is enabled (20.14.19 [unord.hash]).

6. Create a new subclause [depr.vector.bool.swap] after D.21 [depr.string.capacity]

   > D.? Deprecated `vector<bool, Allocator>` swap [depr.vector.bool.swap]

   > -?- The following member is declared in addition to those members specified in 22.3.12 [vector.bool]:

   >     namespace std {
   >       template<class Allocator> class vector<bool, Allocator> {
   >       public:
   >         constexpr static void swap(reference x, reference y) noexcept;
   >       };
   >     }

   >     constexpr static void swap(reference x, reference y) noexcept;

   > > -?- Effects: Exchanges the contents of `x` and `y` as if by:

   > > >     bool b = x;
   > > >     x = y;
   > > >     y = b;