The last specialization of incrementable_traits is under-constrained
Hewill Kang

Created on 2022-12-07.00:00:00 last changed 3 weeks ago


Date: 2023-01-06.14:40:19

Proposed resolution:

This wording is relative to N4917.

  1. Modify [incrementable.traits] as indicated:

    namespace std {
      template<class T>
        concept nonbool-integral = integral<T> && !same_as<T, bool>;         // exposition only
      template<class T> struct incrementable_traits { };
      template<class T>
        requires (!requires { typename T::difference_type; } &&
                  requires(const T& a, const T& b) { { a - b } -> nonbool-integralintegral; })
      struct incrementable_traits<T> {
        using difference_type = make_signed_t<decltype(declval<T>() - declval<T>())>;
Date: 2023-01-15.00:00:00

[ 2023-01-06; Reflector poll ]

Set priority to 3 after reflector poll.

"I would prefer to place the new checks directly in the requires-clause instead of introducing nonbool-integral."

Date: 2022-12-15.00:00:00

[ 2022-12-13; Minor wording improvements after LWG reflector discussion ]

Remove remove_cv_t within nonbool-integral, because bool prvalues cannot be cv-qualified.

Date: 2022-12-07.00:00:00

The last specialization of incremental_traits requires that the result obtained by subtracting two objects of type const T must model integral, then apply make_signed_t to it as the difference type of type T.

However, since bool also models integral, but is not a valid template argument for make_signed_t, we should ban such cases to avoid unnecessary hard errors (online example):

#include <ranges>

struct Bool { 
  bool operator-(Bool) const; 

template<class T>
concept can_iota_view = requires(T t) { std::ranges::iota_view(t); };

static_assert(!can_iota_view<Bool>); // hard error
Date User Action Args
2023-01-06 14:40:19adminsetmessages: + msg13173
2022-12-13 16:30:47adminsetmessages: + msg13155
2022-12-10 13:23:30adminsetmessages: + msg13150
2022-12-07 00:00:00admincreate