如何检查类型是否源自向量/列表/双端队列?

Sur*_*K S 3 c++ templates type-traits c++20 c++-templates

我正在使用 C++20。我能够检查类型是否是某种向量/双端队列/列表,如下所示:

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>>);

Run Code Online (Sandbox Code Playgroud)

(我想知道在 C++20 中是否有更好的方法来做到这一点,现在我们有了requires表达式等。)

但是,现在我想要的是is_listish接受从向量/列表/双端队列派生的类。例如:

struct MyVec : public std::vector<int> { };
static_assert(is_listish<MyVec>); //This should be true
Run Code Online (Sandbox Code Playgroud)

我不确定这是否可能。这是我尝试过的:

template <typename B, typename D>
  requires std::is_base_of_v<B, D>
struct is_listish_trait<D> {
  static constexpr bool value = 1;
};
Run Code Online (Sandbox Code Playgroud)

然而,编译器抱怨它无法推导出 B(这是可以理解的)。

怎样才能做到这一点呢?

Jar*_*d42 5

使用requires,您可以这样做:

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); }
    ;
Run Code Online (Sandbox Code Playgroud)

演示

  • 你可以用指针来做到这一点 (`requires(std::add_pointer_t&lt;T&gt; p) { []&lt;typename U, typename A&gt;(const volatile std::vector&lt;U, A&gt;*){}(p); } `) 以防止考虑转换 (3认同)