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.
[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.
Modify 22.10.13 [func.not.fn] as indicated:
template<auto f> constexpr unspecified not_fn() noexcept;-6- […]
-7- Mandates: Ifis_pointer_v<F> || is_member_pointer_v<F>
istrue
, thenf != nullptr
istrue
is_scalar_v<F>
istrue
, then eitheris_pointer_v<F> && is_function_v<remove_pointer_t<F>>
istrue
oris_member_pointer_v<F>
istrue
, andf != nullptr
istrue
in either case.
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:
(7.1) — […]
(7.2) — […]
(7.3) — if
is_pointer_v<F> || is_member_pointer_v<F>
istrue
, thenf != nullptr
istrue
is_scalar_v<F>
istrue
, then eitheris_pointer_v<F> && is_function_v<remove_pointer_t<F>>
istrue
oris_member_pointer_v<F>
istrue
, andf != nullptr
istrue
in either case.