Title
Incorrect constrains for function_ref constructors from nontype_t
Status
new
Section
[func.wrap.ref.ctor]
Submitter
Tomasz Kamiński

Created on 2025-05-14.00:00:00 last changed 3 weeks ago

Messages

Date: 2025-05-14.10:07:01

Proposed resolution:

This wording is relative to N5008.

  1. Modify [func.wrap.ref.ctor] as indicated:

    template<auto f> constexpr function_ref(nontype_t<f>) noexcept;
    

    -8- Let F be decltype(f).

    -9- Constraints: is-invocable-using<const F&> is true.

    […]
    template<auto f, class U> constexpr function_ref(nontype_t<f>, U&& obj) noexcept;
    

    -12- Let T be remove_reference_t<U> and F be decltype(f).

    -13- Constraints::

    1. (13.1) — is_rvalue_reference_v<U&&> is false, and

    2. (13.2) — is-invocable-using<const F&, T cv&> is true.

    […]
    template<auto f, class T> constexpr function_ref(nontype_t<f>, T cv* obj) noexcept;
    

    -17- Let F be decltype(f).

    -16- Constraints: is-invocable-using<const F&, T cv*> is true.

    […]
Date: 2025-05-18.08:49:08

For the following class:

struct M
{
   void operator();
};

The constructor of function_ref<void()> from nontype_t is considered to be valid candidate (is_constructible_v<function_ref<void()>, nontype_t<M{}>> is true), despite the fact that the corresponding invocation of template argument object, that is const lvalue, is ill-formed. As consequence we produce a hard error from inside of this constructor.

This is caused by the fact that for constructors with non-type auto f parameter, we are checking if is-invocable-using<F> is true, where F is decltype(f) i.e. M for the example. We should use const F& or decltype((f)).

History
Date User Action Args
2025-05-14 10:07:01adminsetmessages: + msg14750
2025-05-14 00:00:00admincreate