std::indirectly_unary_invocable, std::indirectly_regular_unary_invocable - cppreference.com

From cppreference.com

Defined in header

<iterator>

std::indirectly_unary_invocable

template<classF,classI>conceptindirectly_unary_invocable=std::indirectly_readable<I>&&std::copy_constructible<F>&&std::invocable<F&,/*indirect-value-t*/<I>>&&std::invocable<F&,std::iter_reference_t<I>>&&std::common_reference_with<std::invoke_result_t<F&,/*indirect-value-t*/<I>>,std::invoke_result_t<F&,std::iter_reference_t<I>>>;(since C++20)std::indirectly_regular_unary_invocable

template<classF,classI>conceptindirectly_regular_unary_invocable=std::indirectly_readable<I>&&std::copy_constructible<F>&&std::regular_invocable<F&,/*indirect-value-t*/<I>>&&std::regular_invocable<F&,std::iter_reference_t<I>>&&std::common_reference_with<std::invoke_result_t<F&,/*indirect-value-t*/<I>>,std::invoke_result_t<F&,std::iter_reference_t<I>>>;(since C++20)The concepts indirectly_unary_invocable and indirectly_regular_unary_invocable specify requirements for algorithms that call (regular) unary invocables as their arguments. The key difference between these concepts and

std::invocable

is that they are applied to the type the I references, rather than I itself.

Notes

The distinction between indirectly_unary_invocable and indirectly_regular_unary_invocable is purely semantic.

Example

Run this code

#include<algorithm>#include<iterator>#include<print>#include<ranges>structIntWrapper{inti;explicitIntWrapper(inti):i(i){}IntWrapper(IntWrapper&&)=default;IntWrapper&operator=(IntWrapper&&)=default;};intmain(){autoints=std::views::iota(1,10);autoprint=[](IntWrapperw){std::print("{} ",w.i);};autowrap=[](inti){returnIntWrapper{i};};usingProj=std::projected<decltype(ints.begin()),decltype(wrap)>;// error (evaluated to false) until P2609R3:// this was because 'std::iter_value_t<Proj> &' is the same as 'IntWrapper&'// which is not convertible to 'IntWrapper' (implicitly deleted copy ctor)static_assert(std::indirectly_unary_invocable<decltype(print),Proj>);// if the compile-time check above evaluates to true, then this is well-formed:std::ranges::for_each(ints,print,wrap);}Output:

1 2 3 4 5 6 7 8 9 Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior

P2609R3

C++20 some requirements were defined in terms of std::iter_value_t<I>&
which mishandled projections resulting in incompatibility with invocable F&defined in terms of /*indirect-value-t*/<I>
to correctly handle such projections

P2997R1

C++20 corresponding concepts required F& to satisfy

invocable

and

regular_invocable

, respectively, with std::iter_common_reference_t<I>does not require