C++20 added concepts, and the standard library includes quite a few of them. One concept in particular caught my eye: std::invocable which validates that a functor can be invoked with a set of arguments.
std::invocable is just syntactic sugar for std::is_invocable. However, the standard library further defines std::is_invocable_r which tests whether a functor can be invoked with a set of arguments, but also that it returns a certain type once invoked. There are also nothrow versions of both of these utilities. However, there are no equivalent concepts defined in the standard.
Is there a reason the standard does not define these concepts, or was it just an oversight? Is there perhaps some minutia that a casual reader did not pick up on that made the committee decide not to include these?
The design approach of the concepts library is much more minimalistic than that of type traits. For example, there is no std::arithmetic concept to match the std::is_arithmetic trait. This has two reasons:
std::is_arithmetic, or from std::integral and std::floating_point.See also: Will there be a concept for arithmetic types in C++ standard library?
std::invocable and convenience concepts in generalA similar problem exists with std::invocable and its _r and nothrow variants. You can trivially construct a concept like this:
template <typename T, typename R, typename... Args>
concept invocable_r = invocable<T, Args...> && requires (Args&&... args) {
{ invoke(forward<Args>(args)...) } -> convertible_to<R>;
};
However, it is not so clear that this is the definitive implementation. You could also construct it in terms of std::invoke_r, and it's unclear whether std::convertible_to should still be used then.
In summary, the concepts library does not include concepts with the following issues:
The concept can be easily constructed from others, so it is merely there for convenience. This includes nothrow variants, _r variants, disjunctions like std::arithmetic etc. The user can just make these themselves.
There are multiple possible implementations, and it isn't perfectly clear which one should make it into the standard library. Keep in mind that the exact way a concept is defined can make it more constrained than another concept, so implementation details matter.
Note that concepts standardization was largely driven by the ranges library, and std::invocable_r is not essential to constraining ranges. std::invoke is used by std::indirect_result_t in std::indirectly_writable.
Last but not least, remember that standardizing any language feature is a difficult task. The slimmer a proposal, the easier it is to get it through the committee. If someone made a proposal nowadays that provides such convenience concepts, there is a good chance that it would find success, however, it would have been a difficult task back in the day which would have increased the size of the proposal (P9898: Standard Library Concepts) considerably.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With