I would like to have a concept
requiring an arbitrary vector as the return type:
template<typename T>
concept HasVector = requires (T t) {
{ T.vec() } -> std::same_as<std::vector<int>>; //works
{ T.vec() } -> std::same_as<std::vector<foo>>; //want to put something arbitrary in here
}
Such that we would have something like the following:
class A {
std::vector<int> vec() { /* ... */}
}
class B {
std::vector<double> vec() { /* ... */}
}
static_assert(HasVector<A>);
static_assert(HasVector<B>);
Moreover, it would be even nicer to require a vector as the return type whose value type satisfies some other concept, i.e.
template<typename T>
concept Arithmetic = // as in the standard
template<typename T>
concept HasArithmeticVector = requires (T t ) {
{ T. vec() } -> std::same_as<std::vector<Arithmetic>>;
Is there such a way to put this in names of concepts?
We start by writing a variable template to check if a type specializes a template:
template <typename T, template <typename...> class Z>
inline constexpr bool is_specialization_of = false;
template <template <typename...> class Z, class... Args>
inline constexpr bool is_specialization_of<Z<Args...>, Z> = true;
Which we can turn into a concept:
template <typename T, template <typename...> class Z>
concept Specializes = is_specialization_of<T, Z>;
Which we can then use to implement another concept:
template<typename T>
concept HasVector = requires (T t) {
{ t.vec() } -> Specializes<std::vector>;
};
If you want to then do further checking, that's just adding more requirements.
template<typename T>
concept HasVector = requires (T t) {
{ t.vec() } -> Specializes<std::vector>;
// or something along these lines
requires Arithmetic<decay_t<decltype(t.vec()[0])>>;
requires Arithmetic<range_value_t<decltype(t.vec())>>;
// etc.
};