---
title: "Fix LWG4543: incorrect cast between"
document: P4042R0
date: 2026-03-18
audience: LWG
reply-to:
  - "Matthias Kretz < <m.kretz@gsi.de>"
paper-type: proposal
---

| Document Number: | P4042R0 |
| --- | --- |
| Date: | 2026-03-18 |
| Reply-to: | Matthias Kretz <m.kretz@gsi.de> |
| Audience: | LWG |
| Target: | C++26 |

# Fix LWG4543: incorrect cast between

### 1

#### (placeholder)

#### 2

This has been implemented and tested in the patch that’s currently in review for libstdc++.

#### 3

##### In [simd.overview] add:

:::wording-add

[simd.overview] template<class U> constexpr explicit(see below) basic_vec(U&& value) noexcept; template<class U, class UAbi> constexpr explicit(see below) basic_vec(const basic_vec<U, UAbi>&) noexcept; <ins>template<class U, class UAbi></ins> <ins>constexpr explicit(see below) basic_vec(const basic_vec<U, UAbi>&) noexcept = delete;</ins> template<class G> constexpr explicit basic_vec(G&& gen);

:::

##### In [simd.ctor] add:

[simd.ctor] `template<class` `U``,` `class` `UAbi``>` `constexpr` `explicit(``see` `below``)` `basic_vec``(const` `basic_vec``<``U``,` `UAbi``>&` `x``)` `noexcept``;`

5 *Constraints*:

* `simd-size-v``<U,` `UAbi>` `==` `size()` is `true`, and

* `U` satisfies `explicitly-convertible-to``<T>`.

6 *Effects*: Initializes the 𝑖th element with `static_cast<T>(x[`𝑖`])` for all 𝑖in the range of [`0`, `size()`).

7 *Remarks:* The expression inside `explicit` evaluates to `true` if either

* the conversion from `U` to `value_type` is not value-preserving, or

* both `U` and `value_type` are integral types and the integer conversion rank ([conv.rank]) of `U` is
greater than the integer conversion rank of `value_type`, or

* both `U` and `value_type` are floating-point types and the floating-point conversion rank ([conv.rank])
of `U` is greater than the floating-point conversion rank of `value_type`.

:::wording-add

<ins>template<class U, class UAbi></ins> <ins>constexpr explicit(see below) basic_vec(const basic_vec<U, UAbi>&) noexcept = delete;</ins>

:::

:::wording-add

<ins>-?-</ins> <ins>Constraints:</ins>

:::

:::wording-add

<ins>• simd-size-v<U, UAbi> == size() is false, or</ins>

:::

:::wording-add

<ins>• U does not satisfy explicitly-convertible-to<T>.</ins>

:::

:::wording-add

<ins>-?-</ins> <ins>Remarks: The expression inside explicit evaluates to simd-size-v<U, UAbi> == size().</ins>

:::

##### In [simd.mask.overview] modify:

:::wording-add

[simd.mask.overview] constexpr explicit basic_mask(same_as<value_type> auto) noexcept; template<size_t UBytes, class UAbi> constexpr explicit basic_mask(const basic_mask<UBytes, UAbi>&) noexcept; <ins>template<size_t UBytes, class UAbi></ins> <ins>constexpr explicit basic_mask(const basic_mask<UBytes, UAbi>&) noexcept = delete;</ins> <ins>template<class U, class UAbi></ins> <ins>constexpr explicit basic_mask(const basic_vec<U, UAbi>&) noexcept = delete;</ins> template<class G> constexpr explicit basic_mask(G&& gen); template<same_as<bitset<size()>> T> constexpr basic_mask(const T& b) noexcept; template<unsigned_integral T> requires (!same_as<T, value_type>) constexpr explicit basic_mask(T val) noexcept;

:::

*//* *([simd.mask.subscr]),* `basic_mask` *subscript* *operators* `constexpr` `value_type` `operator[](``simd-size-type``)` `const;` `template<``simd-integral` `I``>` `constexpr` `resize_t``<``I``::``size``(),` `basic_mask``>` `operator[](const` `I``&` `indices``)` `const;`

*//* *([simd.mask.unary]),* `basic_mask` *unary* *operators* `constexpr` `basic_mask` `operator!()` `const` `noexcept``;` `constexpr` `see` `below` `operator+()` `const` `noexcept``;` `constexpr` `see` `below` `operator-()` `const` `noexcept``;` `constexpr` `see` `below` `operator~()` `const` `noexcept``;`

:::wording

// ([simd.mask.conv]), basic_mask conversions template<class U, class <del>A</del><ins>UAbi</ins>> constexpr explicit(sizeof(U) != Bytes) operator basic_vec<U, <del>A</del><ins>UAbi</ins>>() const noexcept; <ins>template<class U, class UAbi></ins> <ins>constexpr operator basic_vec<U, UAbi>() const noexcept = delete;</ins> constexpr bitset<size()> to_bitset() const noexcept; constexpr unsigned long long to_ullong() const;

:::

##### In [simd.mask.ctor] add:

[simd.mask.ctor] `template<``size_t` `UBytes``,` `class` `UAbi``>` `constexpr` `explicit` `basic_mask``(const` `basic_mask``<``UBytes``,` `UAbi``>&` `x``)` `noexcept``;`

2 *Constraints*: `basic_mask<UBytes,` `UAbi>::size()` `==` `size()` is `true`.

3 *Effects*: Initializes the 𝑖th element with `x[`𝑖`]` for all 𝑖in the range of [`0`, `size()`).

:::wording-add

<ins>template<size_t UBytes, class UAbi></ins> <ins>constexpr explicit basic_mask(const basic_mask<UBytes, UAbi>& x) noexcept = delete;</ins>

:::

:::wording-add

<ins>-?-</ins> <ins>Constraints: basic_mask<UBytes, UAbi>::size() == size() is false.</ins>

:::

##### In [simd.mask.conv] add:

:::wording

[simd.mask.conv] template<class U, class <del>A</del><ins>UAbi</ins>> constexpr explicit(sizeof(U) != Bytes) operator basic_vec<U, <del>A</del><ins>UAbi</ins>>() const noexcept;

:::

:::wording

1 Constraints: simd-size-v<U, <del>A</del><ins>UAbi</ins>> == <del>mask-size-v<Bytes, Abi></del><ins>size() is true</ins>.

:::

2 *Returns:* A data-parallel object where the 𝑖th element is initialized to `static_cast<U>(operator[](`𝑖`))`.

:::wording-add

<ins>template<class U, class UAbi></ins> <ins>constexpr operator basic_vec<U, UAbi>() const noexcept = delete;</ins>

:::

:::wording-add

<ins>-?-</ins> <ins>Constraints: simd-size-v<U, UAbi> == size() is false.</ins>

:::

```cpp
constexpr bitset<size()> to_bitset() const noexcept;
```
