3979. Should we reject std::bind_front<42>() and its friends?

Section: 22.10.13 [func.not.fn], 22.10.14 [func.bind.partial] Status: New Submitter: Jiang An Opened: 2023-08-22 Last modified: 2023-09-24 09:43:08 UTC

Priority: Not Prioritized

View all other issues in [func.not.fn].

View all issues with New status.

Discussion:

std::bind_front<42>() seems to be currently well-formed, but the result isn't invocable with any arguments. Given we are already detecting types and values of the NTTP for new overloads of std::bind_front, std::bind_back, and std::not_fn, it might be better to diagnose such cases when NTTP is of a scalar type.

Note that we might need to separately handle NTTP of scalar and class types for these functions when CWG2459 is not resolved, because it might be necessary to avoid copying a template parameter object.

Proposed resolution:

This wording is relative to N4958.

  1. Modify 22.10.13 [func.not.fn] as indicated:

    template<auto f> constexpr unspecified not_fn() noexcept;
    

    -6- […]

    -7- Mandates: If is_pointer_v<F> || is_member_pointer_v<F> is true, then f != nullptr is trueis_scalar_v<F> is true, then either is_pointer_v<F> && is_function_v<remove_pointer_t<F>> is true or is_member_pointer_v<F> is true, and f != nullptr is true in either case.

  2. Modify 22.10.14 [func.bind.partial] as indicated:

    template<auto f, class... Args>
      constexpr unspecified bind_front(Args&&... args);
    template<auto f, class... Args>
      constexpr unspecified bind_back(Args&&... args);
    

    -6- […]

    -7- Mandates:

    1. (7.1) — […]

    2. (7.2) — […]

    3. (7.3) — if is_pointer_v<F> || is_member_pointer_v<F> is true, then f != nullptr is trueis_scalar_v<F> is true, then either is_pointer_v<F> && is_function_v<remove_pointer_t<F>> is true or is_member_pointer_v<F> is true, and f != nullptr is true in either case.