在C++中检查容器是否可以向后遍历。

huangapple go评论87阅读模式
英文:

Check if a container can be traversed backwards in C++

问题

我正在编写一个可以接受任何容器来存储值的模板。我需要检查传递给模板包装器的容器是否可以反向遍历(或者从规范的角度来说,是否满足_ReversibleContainer_的要求)。为了提供更多的上下文,这里是一段简单的代码:

using container = ... // 假设容器别名代表作为模板参数传递的容器
...
using reverse_iterator = std::conditional_t<???, container::reverse_iterator, container::iterator>;

是否有类型特性可供使用,或者其他解决方法?我该如何实现这一功能?

英文:

I'm writing a template which can take any container to store values into. I need to check if the container passed into the template wrapper can be traversed backwards (or, normatively speaking, meets the ReversibleContainer requirement). To provide a bit more context, here is a simple piece of code:

using container = ... // assume the container alias to represent the container
                      // passed in as a template parameter
...
using reverse_iterator = std::conditional_t&lt;???, container::reverse_iterator, container::iterator&gt;;

Is there any type trait for this or some other workaround? How can I implement this?

答案1

得分: 4

这是对SFINAE的相当直接的应用,has_reverse_iterator<T>将在T定义了reverse_iterator成员类型时评估为true

#include <type_traits>
#include <vector>
#include <forward_list>

template<typename T, typename=void>
struct has_reverse_iterator : std::false_type {};

template<typename T>
struct has_reverse_iterator<T,
			    typename std::void_t<typename T::reverse_iterator>>
	: std::true_type {};

template<typename T>
inline constexpr bool has_reverse_iterator_v = has_reverse_iterator<T>::value;

static_assert(has_reverse_iterator_v<std::vector<char>>);

static_assert(!has_reverse_iterator_v<std::forward_list<char>>);
英文:

This is a fairly straightforward application of SFINAE, has_reverse_iterator&lt;T&gt; will evaluate to true if T defines a reverse_iterator member type.

#include &lt;type_traits&gt;
#include &lt;vector&gt;
#include &lt;forward_list&gt;

template&lt;typename T, typename=void&gt;
struct has_reverse_iterator : std::false_type {};

template&lt;typename T&gt;
struct has_reverse_iterator&lt;T,
			    typename std::void_t&lt;typename T::reverse_iterator&gt;&gt;
	: std::true_type {};

template&lt;typename T&gt;
inline constexpr bool has_reverse_iterator_v=has_reverse_iterator&lt;T&gt;::value;

static_assert(has_reverse_iterator_v&lt;std::vector&lt;char&gt;&gt;);

static_assert(!has_reverse_iterator_v&lt;std::forward_list&lt;char&gt;&gt;);

答案2

得分: 1

一个_可逆容器_是一个具有满足_Either LegacyBidirectionalIterator or LegacyRandomAccessIterator 要求的迭代器的容器。

因此,您可以通过使用std::bidirectional_iterator concept 来检查容器的迭代器是否是双向迭代器:

#include <iterator>
#include <ranges>

template <class C>
class Foo {
    static_assert(std::bidirectional_iterator<std::ranges::iterator_t<C>>);
};
int main() {
    Foo<std::vector<int>> x;  // 可行
    Foo<int[10]> y;           // 可行
    // Foo<std::istream> z;   // 错误
}
英文:

> A ReversibleContainer is a Container that has iterators that meet the requirements of either LegacyBidirectionalIterator or LegacyRandomAccessIterator.

You could therefore check if the container's iterator is a bidirectional iterator by using the std::bidirectional_iterator concept:

#include &lt;iterator&gt;
#include &lt;ranges&gt;

template &lt;class C&gt;
class Foo {
    static_assert(std::bidirectional_iterator&lt;std::ranges::iterator_t&lt;C&gt;&gt;);
};
int main() {
    Foo&lt;std::vector&lt;int&gt;&gt; x;  // ok
    Foo&lt;int[10]&gt; y;           // ok
    // Foo&lt;std::istream&gt; z;   // error
}

答案3

得分: 1

In C++20,我们可以使用concept来定义这个要求:

template<typename T>
concept has_reverse_iterator = requires
{
    typename T::reverse_iterator;
};

static_assert(has_reverse_iterator<std::vector<char>>);
static_assert(has_reverse_iterator<const std::vector<char>>);
static_assert(!has_reverse_iterator<std::forward_list<char>>);
static_assert(!has_reverse_iterator<const std::forward_list<char>>);

Live Demo

英文:

In C++20, we can use a concept to define this requirement:

template&lt;typename T&gt;
concept has_reverse_iterator = requires
{
    typename T::reverse_iterator;
};
static_assert(has_reverse_iterator&lt;std::vector&lt;char&gt;&gt;);
static_assert(has_reverse_iterator&lt;const std::vector&lt;char&gt;&gt;);
static_assert(!has_reverse_iterator&lt;std::forward_list&lt;char&gt;&gt;);
static_assert(!has_reverse_iterator&lt;const std::forward_list&lt;char&gt;&gt;)

Live Demo

huangapple
  • 本文由 发表于 2023年7月17日 18:27:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76703568.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定