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

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: 2024-02-22

Priority: 4

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.

[2024-02-22; Reflector poll]

Set priority to 4 after reflector poll in September 2023.

"Not convinced it's worth adding a small amount of future maintenance burden to catch a tiny amount of nonsense-but-not-dangerous code slightly earlier (at the point of call instead of point of use)."

"NAD. We reject bind_front<null_f>() because bind_front(null_f)() compiles but gives UB. Neither bind_front(42)() nor bind_front<42>() compiles."

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.