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 from std::integral
and std::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 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
.
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.
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. – Monogamist