英文:
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<???, container::reverse_iterator, container::iterator>;
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<T>
will evaluate to true
if T
defines a reverse_iterator
member type.
#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>>);
答案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 <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; // ok
Foo<int[10]> y; // ok
// Foo<std::istream> 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>>);
英文:
In C++20, we can use a concept to define this requirement:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论