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

### 3300. Non-array `ssize` overload is underconstrained

Section: 25.7 [iterator.range] Status: C++20 Submitter: Casey Carter Opened: 2019-09-27 Last modified: 2021-02-25

Priority: 3

View other active issues in [iterator.range].

View all other issues in [iterator.range].

View all issues with C++20 status.

Discussion:

The overload of `ssize` specified in 25.7 [iterator.range]/18 has no constraints, yet it specializes `make_signed_t` which has a precondition that its type parameter is an integral type or enumeration but not `bool` (21.3.8.4 [meta.trans.sign]). This precondition needs to be propagated to `ssize` as "Mandates [or Constraints]: `decltype(c.size())` [meets the requirements for the type argument to `make_signed`]". "Mandates" seems to be more in line with LWG guidance since there are no traits nor concepts that observe `ssize`.

[2019-11-16 Issue Prioritization]

Priority to 3 after reflector discussion.

Previous resolution [SUPERSEDED]:

> This wording is relative to N4830.

> 1. Modify 25.7 [iterator.range] as indicated:

>    >     template<class C> constexpr auto ssize(const C& c)
>    >       -> common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>;

>    > > -?- Mandates: `decltype(c.size())` is a (possibly cv-qualified) integral or enumeration type but not a `bool` type.

>    > > -18- Returns:

>    > > >     static_cast<common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>>(c.size())

[2019-10-28; Tim provides improved wording]

Previous resolution [SUPERSEDED]:

> This wording is relative to N4835.

> 1. Modify 25.7 [iterator.range] as indicated:

>    >     template<class C> constexpr auto ssize(const C& c)
>    >       -> common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>;

>    > > -?- Mandates: `decltype(c.size())` is an integral or enumeration type other than `bool`.

>    > > -18- Returns:

>    > > >     static_cast<common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>>(c.size())

[2019-11-18; Casey comments and improves wording]

It would be better to provided the Mandates: guarantee in [tab:meta.trans.sign] instead of one special place where the `make_signed` template is used. The wording below attempts to realize that.

[2019-11-23 Issue Prioritization]

Status to Tentatively Ready after five positive votes on the reflector.

Proposed resolution:

This wording is relative to N4835.

1. Change Table 52 — "Sign modifications" in [tab:meta.trans.sign] as indicated:

   Table 52 — Sign modifications [tab:meta.trans.sign]
   Template | Comments
   --- | ---
   `template <class T> struct make_signed;` | If `T` names a (possibly cv-qualified) signed integer type (6.8.2 [basic.fundamental]) then the member typedef `type` names the type `T`; otherwise, if `T` names a (possibly cv-qualified) unsigned integer type then `type` names the corresponding signed integer type, with the same cv-qualifiers as `T`; otherwise, `type` names the signed integer type with smallest rank (6.8.6 [conv.rank]) for which `sizeof(T) == sizeof(type)`, with the same cv-qualifiers as `T`. Requires Mandates: `T` shall be is an (possibly cv-qualified) integral type or enumeration type other than cv but not a `bool` type.
   `template <class T> struct make_unsigned;` | If `T` names a (possibly cv-qualified) unsigned integer type (6.8.2 [basic.fundamental]) then the member typedef `type` names the type `T`; otherwise, if `T` names a (possibly cv-qualified) signed integer type then `type` names the corresponding unsigned integer type, with the same cv-qualifiers as `T`; otherwise, `type` names the unsigned integer type with smallest rank (6.8.6 [conv.rank]) for which `sizeof(T) == sizeof(type)`, with the same cv-qualifiers as `T`. Requires Mandates: `T` shall be is an (possibly cv-qualified) integral type or enumeration type other than cv but not a `bool` type.

2. Change 25.7 [iterator.range] as indicated:

   >     template<class C> constexpr auto ssize(const C& c)
   >       -> common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>;

   > > -18- Returns Effects: Equivalent to:

   > > >     return static_cast<common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>>(c.size());