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?
1
1 Answer
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:
- It can be trivially constructed from
std::is_arithmetic
, or fromstd::integral
andstd::floating_point
. - It is unclear which of these constructions should be preferred.
See also: Will there be a concept for arithmetic types in C++ standard library?
Issues with std::invocable
and convenience concepts in general
A 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 likestd::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
.
The difficulty of standardizing a proposal
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.
2
-
2
"The user can just make these themselves." Wouldn't it be desirable to have a new C++ programmer to be able to use concepts as an abstraction layer, without having to understand the underlying (and less intuitive) C++11 metaprogramming library? The other points make a lot of sense.
– TooTone9 hours ago
-
3
@TooTone yeah, sure. There is benefit in having additional convenience concepts, even if the implementation is relatively simple. That's why I've said that a proposal for convenience concepts could likely find success. It was just too much effort with too few returns to standardize it back in the day.
– Jan Schultke9 hours ago
std::is_invocable_r
doesn't test that a functor returns a specific type R. It tests that the return type is convertible to R. I suspect the rationale here would be the same for havingstd::same_as
andstd::convertible_to
in the final design of concepts. I.e. both are valid, so the standard doesn't arbitrarily pick one, letting us choose when needed.10 hours ago