Title
std::to_address() should be SFINAE-friendly
Status
new
Section
[pointer.conversion]
Submitter
Peter Kasting

Created on 2024-03-13.00:00:00 last changed 8 months ago

Messages

Date: 2024-03-13.10:42:50

Proposed resolution:

This wording is relative to N4971.

  1. Modify [pointer.conversion] as indicated:

    template<class Ptr> constexpr auto to_address(const Ptr& p) noexcept;

    -?- Constraints: Either the expression pointer_traits<Ptr>::to_address(p) is well-formed (see [pointer.traits.optmem]), or the expression p.operator->() is well-formed.

    -3- Returns: pointer_traits<Ptr>::to_address(p) if that expression is well-formed (see [pointer.traits.optmem]), otherwise to_address(p.operator->()).

  2. Modify [iterator.concept.contiguous] as indicated:

    -1- The contiguous_iterator concept provides a guarantee that the denoted elements are stored contiguously in memory.

    
    template<class I>
      concept contiguous_iterator =
        random_access_iterator<I> &&
        derived_from<ITER_CONCEPT(I), contiguous_iterator_tag> &&
        is_lvalue_reference_v<iter_reference_t<I>> &&
        same_as<iter_value_t<I>, remove_cvref_t<iter_reference_t<I>>> &&
        requires(const I& i) {
          { to_address(i) } -> same_as<add_pointer_t<iter_reference_t<I>>>;
        }
        std::same_as<decltype([] { return std::to_address(std::declval<I>()); }()),
                     std::add_pointer_t<std::iter_reference_t<I>>>;
    
    The submitter welcomes less awkward alternatives to achieve the desired hard error for contiguous_iterator.
Date: 2024-03-13.00:00:00

LWG 3545 made std::pointer_traits SFINAE-friendly. However, std::to_address is still not required to be SFINAE-friendly.

This requires callers who wish to accept both pointer-like and non-pointer-like types to guard calls with a constraint that reimplements the core logic of to_address, such as the following:


template<typename T>
concept IsPointerLike = requires { typename std::pointer_traits<T>::pointer; }
                         || requires (const T& t) { t.operator->(); };

Making `to_address` not be SFINAE-friendly was seen as desirable, so `std::contiguous_iterator` would produce a hard error for types marked with `contiguous_iterator_tag` that do not properly support `to_address`. Thus any fix should not regress that unless LWG explicitly decides to do so. Also note that libc++'s current implementation of `to_address`, which is SFINAE-friendly, does not produce such a hard error.

History
Date User Action Args
2024-03-13 10:41:07adminsetmessages: + msg14005
2024-03-13 00:00:00admincreate