I'm using C++20. I was able to check if a type is some vector / deque / list as follows:
template <typename N> struct is_listish_trait {
static constexpr bool value = 0;
};
/* These are listish specializations */
template <typename N, typename A> struct is_listish_trait<std::vector<N, A>> {
static constexpr bool value = 1;
};
template <typename N, typename A> struct is_listish_trait<std::list<N, A>> {
static constexpr bool value = 1;
};
template <typename N, typename A> struct is_listish_trait<std::deque<N, A>> {
static constexpr bool value = 1;
};
template <typename T>
static constexpr bool is_listish = is_listish_trait<T>::value;
static_assert(!is_listish<int>);
static_assert(is_listish<std::vector<int>>);
(I am wondering if there is a better way to do this in C++20, now that we have requires
expressions, etc.)
However, now what I want is for is_listish
to accept classes that derive from vectors / lists / deques. For instance:
struct MyVec : public std::vector<int> { };
static_assert(is_listish<MyVec>); //This should be true
I'm not sure if this is possible. This is what I tried:
template <typename B, typename D>
requires std::is_base_of_v<B, D>
struct is_listish_trait<D> {
static constexpr bool value = 1;
};
However, the compiler complains that it cannot deduce B (which is understandable).
How can one do this?
With requires
, you might do:
template <typename T>
concept is_listish =
requires(T t) { []<typename U, typename A>(std::vector<U, A>&){}(t); }
or requires(T t) { []<typename U, typename A>(std::list<U, A>&){}(t); }
or requires(T t) { []<typename U, typename A>(std::deque<U, A>&){}(t); }
;