实现 C++20 bidirectional_iterator 概念
Implement C++20 bidirectional_iterator concept
Forward_iterator 编译正常!
#include <concepts>
#include <iterator>
// #include <iterator_concept>
using namespace std;
template<typename T>
// struct my_iterator : std::forward_iterator_tag{
struct my_iterator : std::bidirectional_iterator_tag {
T& operator*()const{
return *pointer;
}
my_iterator& operator++(){
++pointer;
return *this;
}
my_iterator operator++(int){
auto copy = *this;
++pointer;
return copy;
}
// my_iterator& operator--(){
// --pointer;
// return *this;
// }
// my_iterator operator--(int){
// auto copy = *this;
// --pointer;
// return copy;
// }
using difference_type = ptrdiff_t;
using value_type = T;
// auto operator<=>(const my_iterator&) const = default;
bool operator==(const my_iterator& other)const{
return pointer == other.pointer;
}
bool operator!=(const my_iterator& other)const{
return pointer != other.pointer;
}
private:
T*pointer;
};
// template<class T> constexpr bool always_false = false;
// static_assert(always_false<std::iter_reference_t<my_iterator<int>>>, "asd");
// typedef typename std::iter_reference_t<my_iterator<int>>::something_made_up X;
// static_assert(std::weakly_incrementable<my_iterator<int>>);
// static_assert(std::equality_comparable<my_iterator<int>>);
static_assert(std::forward_iterator<my_iterator<int>>);
// static_assert(std::bidirectional_iterator<my_iterator<int>>);
int main()
{
my_iterator<int> i1;
}
但双向没有。我试过 g++ v10 和 clang++ v11。两者给出几乎相同的编译时错误。
#include <concepts>
#include <iterator>
using namespace std;
template<typename T>
// struct my_iterator : std::forward_iterator_tag{
struct my_iterator : std::bidirectional_iterator_tag {
T& operator*()const{
return *pointer;
}
my_iterator& operator++(){
++pointer;
return *this;
}
my_iterator operator++(int){
auto copy = *this;
++pointer;
return copy;
}
my_iterator& operator--(){
--pointer;
return *this;
}
my_iterator operator--(int){
auto copy = *this;
--pointer;
return copy;
}
using difference_type = ptrdiff_t;
using value_type = T;
// auto operator<=>(const my_iterator&) const = default; // Why this does not work
bool operator==(const my_iterator& other)const{
return pointer == other.pointer;
}
bool operator!=(const my_iterator& other)const{
return pointer != other.pointer;
}
private:
T*pointer;
};
// template<class T> constexpr bool always_false = false;
// static_assert(always_false<std::iter_reference_t<my_iterator<int>>>, "asd");
// typedef typename std::iter_reference_t<my_iterator<int>>::something_made_up X;
// static_assert(std::weakly_incrementable<my_iterator<int>>);
// static_assert(std::equality_comparable<my_iterator<int>>);
static_assert(std::forward_iterator<my_iterator<int>>);
// static_assert(std::bidirectional_iterator<my_iterator<int>>);
int main()
{
my_iterator<int> i1;
}
In file included from <source>:2:
In file included from /opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/iterator:61:
In file included from /opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/stl_iterator_base_types.h:71:
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:409:52: error: ambiguous partial specializations of '__cat<my_iterator<int>>'
using iterator_category = typename __detail::__cat<_Iterator>::type;
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/stl_iterator_base_types.h:178:14: note: in instantiation of template class 'std::__iterator_traits<my_iterator<int>, void>' requested here
: public __iterator_traits<_Iterator> { };
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:182:71: note: in instantiation of template class 'std::iterator_traits<my_iterator<int>>' requested here
= __is_base_of(__iterator_traits<_Iter, void>, iterator_traits<_Iter>);
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:182:4: note: while substituting template arguments into constraint expression here
= __is_base_of(__iterator_traits<_Iter, void>, iterator_traits<_Iter>);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:189:16: note: while checking the satisfaction of concept '__primary_traits_iter<my_iterator<int>>' requested here
requires __primary_traits_iter<_Iter>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:189:16: note: while substituting template arguments into constraint expression here
requires __primary_traits_iter<_Iter>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:195:7: note: (skipping 10 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
using __iter_traits = typename __iter_traits_impl<_Iter, _Tp>::type;
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:564:30: note: while checking the satisfaction of concept 'input_or_output_iterator<my_iterator<int>>' requested here
concept input_iterator = input_or_output_iterator<_Iter>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:564:30: note: while substituting template arguments into constraint expression here
concept input_iterator = input_or_output_iterator<_Iter>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:575:32: note: while checking the satisfaction of concept 'input_iterator<my_iterator<int>>' requested here
concept forward_iterator = input_iterator<_Iter>
^~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:575:32: note: while substituting template arguments into constraint expression here
concept forward_iterator = input_iterator<_Iter>
^~~~~~~~~~~~~~~~~~~~~
<source>:52:15: note: while checking the satisfaction of concept 'forward_iterator<my_iterator<int>>' requested here
static_assert(std::forward_iterator<my_iterator<int>>);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:369:14: note: partial specialization matches [with _Iter = my_iterator<int>]
struct __cat<_Iter>
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:375:14: note: partial specialization matches [with _Iter = my_iterator<int>]
struct __cat<_Iter>
^
<source>:52:1: error: static_assert failed
static_assert(std::forward_iterator<my_iterator<int>>);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:52:20: note: because 'my_iterator<int>' does not satisfy 'forward_iterator'
static_assert(std::forward_iterator<my_iterator<int>>);
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:575:32: note: because 'my_iterator<int>' does not satisfy 'input_iterator'
concept forward_iterator = input_iterator<_Iter>
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:564:30: note: because 'my_iterator<int>' does not satisfy 'input_or_output_iterator'
concept input_iterator = input_or_output_iterator<_Iter>
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:544:5: note: because 'my_iterator<int>' does not satisfy 'weakly_incrementable'
&& weakly_incrementable<_Iter>;
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:198:7: note: because 'typename iter_difference_t<_Iter>' would be invalid: no type named 'difference_type' in 'std::iterator_traits<my_iterator<int>>'
using __iter_diff_t = typename
^
2 errors generated.
Compiler returned: 1
x86-64 clang 11.0.0
1
更多问题:
为什么auto operator<=>(const my_iterator&) const = default;
不提供==
和!=
?
可能是这样,但 static_assert(std::forward_iterator<my_iterator<int>>);
希望 operator== 明确。
有没有办法明确地说这个结构应该满足概念的要求和约束,比如
template<typename T>
struct my_iterator implements forward_iterator {};
目前我需要用static_assert(std::forward_iterator<my_iterator<int>>);
检查一下。
这个:
struct my_iterator : std::bidirectional_iterator_tag {
不是您为迭代器指示迭代器类别的方式。您不从标签类型继承,而是将其作为成员类型别名。
像这样:
struct iterator {
using iterator_category = std::bidirectional_iterator_tag;
};
虽然这实际上不是必需的。即使没有这个标签(并且 definitely 没有继承),这个迭代器也应该算作双向迭代器,因为你满足了其他要求。它实际上是一个libstdc++ bug,它在那个时候没有编译。
Why auto operator<=>(const my_iterator&) const = default;
does not provide ==
and !=
?
确实如此。只是您从不可比较的类型(迭代器标记)继承,因此默认比较被定义为已删除。
Is there a way to explicitly say this struct should meet the requirements and constraints of the concept
没有。
Forward_iterator 编译正常!
#include <concepts>
#include <iterator>
// #include <iterator_concept>
using namespace std;
template<typename T>
// struct my_iterator : std::forward_iterator_tag{
struct my_iterator : std::bidirectional_iterator_tag {
T& operator*()const{
return *pointer;
}
my_iterator& operator++(){
++pointer;
return *this;
}
my_iterator operator++(int){
auto copy = *this;
++pointer;
return copy;
}
// my_iterator& operator--(){
// --pointer;
// return *this;
// }
// my_iterator operator--(int){
// auto copy = *this;
// --pointer;
// return copy;
// }
using difference_type = ptrdiff_t;
using value_type = T;
// auto operator<=>(const my_iterator&) const = default;
bool operator==(const my_iterator& other)const{
return pointer == other.pointer;
}
bool operator!=(const my_iterator& other)const{
return pointer != other.pointer;
}
private:
T*pointer;
};
// template<class T> constexpr bool always_false = false;
// static_assert(always_false<std::iter_reference_t<my_iterator<int>>>, "asd");
// typedef typename std::iter_reference_t<my_iterator<int>>::something_made_up X;
// static_assert(std::weakly_incrementable<my_iterator<int>>);
// static_assert(std::equality_comparable<my_iterator<int>>);
static_assert(std::forward_iterator<my_iterator<int>>);
// static_assert(std::bidirectional_iterator<my_iterator<int>>);
int main()
{
my_iterator<int> i1;
}
但双向没有。我试过 g++ v10 和 clang++ v11。两者给出几乎相同的编译时错误。
#include <concepts>
#include <iterator>
using namespace std;
template<typename T>
// struct my_iterator : std::forward_iterator_tag{
struct my_iterator : std::bidirectional_iterator_tag {
T& operator*()const{
return *pointer;
}
my_iterator& operator++(){
++pointer;
return *this;
}
my_iterator operator++(int){
auto copy = *this;
++pointer;
return copy;
}
my_iterator& operator--(){
--pointer;
return *this;
}
my_iterator operator--(int){
auto copy = *this;
--pointer;
return copy;
}
using difference_type = ptrdiff_t;
using value_type = T;
// auto operator<=>(const my_iterator&) const = default; // Why this does not work
bool operator==(const my_iterator& other)const{
return pointer == other.pointer;
}
bool operator!=(const my_iterator& other)const{
return pointer != other.pointer;
}
private:
T*pointer;
};
// template<class T> constexpr bool always_false = false;
// static_assert(always_false<std::iter_reference_t<my_iterator<int>>>, "asd");
// typedef typename std::iter_reference_t<my_iterator<int>>::something_made_up X;
// static_assert(std::weakly_incrementable<my_iterator<int>>);
// static_assert(std::equality_comparable<my_iterator<int>>);
static_assert(std::forward_iterator<my_iterator<int>>);
// static_assert(std::bidirectional_iterator<my_iterator<int>>);
int main()
{
my_iterator<int> i1;
}
In file included from <source>:2:
In file included from /opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/iterator:61:
In file included from /opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/stl_iterator_base_types.h:71:
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:409:52: error: ambiguous partial specializations of '__cat<my_iterator<int>>'
using iterator_category = typename __detail::__cat<_Iterator>::type;
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/stl_iterator_base_types.h:178:14: note: in instantiation of template class 'std::__iterator_traits<my_iterator<int>, void>' requested here
: public __iterator_traits<_Iterator> { };
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:182:71: note: in instantiation of template class 'std::iterator_traits<my_iterator<int>>' requested here
= __is_base_of(__iterator_traits<_Iter, void>, iterator_traits<_Iter>);
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:182:4: note: while substituting template arguments into constraint expression here
= __is_base_of(__iterator_traits<_Iter, void>, iterator_traits<_Iter>);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:189:16: note: while checking the satisfaction of concept '__primary_traits_iter<my_iterator<int>>' requested here
requires __primary_traits_iter<_Iter>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:189:16: note: while substituting template arguments into constraint expression here
requires __primary_traits_iter<_Iter>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:195:7: note: (skipping 10 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
using __iter_traits = typename __iter_traits_impl<_Iter, _Tp>::type;
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:564:30: note: while checking the satisfaction of concept 'input_or_output_iterator<my_iterator<int>>' requested here
concept input_iterator = input_or_output_iterator<_Iter>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:564:30: note: while substituting template arguments into constraint expression here
concept input_iterator = input_or_output_iterator<_Iter>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:575:32: note: while checking the satisfaction of concept 'input_iterator<my_iterator<int>>' requested here
concept forward_iterator = input_iterator<_Iter>
^~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:575:32: note: while substituting template arguments into constraint expression here
concept forward_iterator = input_iterator<_Iter>
^~~~~~~~~~~~~~~~~~~~~
<source>:52:15: note: while checking the satisfaction of concept 'forward_iterator<my_iterator<int>>' requested here
static_assert(std::forward_iterator<my_iterator<int>>);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:369:14: note: partial specialization matches [with _Iter = my_iterator<int>]
struct __cat<_Iter>
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:375:14: note: partial specialization matches [with _Iter = my_iterator<int>]
struct __cat<_Iter>
^
<source>:52:1: error: static_assert failed
static_assert(std::forward_iterator<my_iterator<int>>);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:52:20: note: because 'my_iterator<int>' does not satisfy 'forward_iterator'
static_assert(std::forward_iterator<my_iterator<int>>);
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:575:32: note: because 'my_iterator<int>' does not satisfy 'input_iterator'
concept forward_iterator = input_iterator<_Iter>
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:564:30: note: because 'my_iterator<int>' does not satisfy 'input_or_output_iterator'
concept input_iterator = input_or_output_iterator<_Iter>
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:544:5: note: because 'my_iterator<int>' does not satisfy 'weakly_incrementable'
&& weakly_incrementable<_Iter>;
^
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/iterator_concepts.h:198:7: note: because 'typename iter_difference_t<_Iter>' would be invalid: no type named 'difference_type' in 'std::iterator_traits<my_iterator<int>>'
using __iter_diff_t = typename
^
2 errors generated.
Compiler returned: 1
x86-64 clang 11.0.0
1
更多问题:
为什么
auto operator<=>(const my_iterator&) const = default;
不提供==
和!=
? 可能是这样,但static_assert(std::forward_iterator<my_iterator<int>>);
希望 operator== 明确。有没有办法明确地说这个结构应该满足概念的要求和约束,比如
template<typename T> struct my_iterator implements forward_iterator {};
目前我需要用
static_assert(std::forward_iterator<my_iterator<int>>);
检查一下。
这个:
struct my_iterator : std::bidirectional_iterator_tag {
不是您为迭代器指示迭代器类别的方式。您不从标签类型继承,而是将其作为成员类型别名。
像这样:
struct iterator {
using iterator_category = std::bidirectional_iterator_tag;
};
虽然这实际上不是必需的。即使没有这个标签(并且 definitely 没有继承),这个迭代器也应该算作双向迭代器,因为你满足了其他要求。它实际上是一个libstdc++ bug,它在那个时候没有编译。
Why
auto operator<=>(const my_iterator&) const = default;
does not provide==
and!=
?
确实如此。只是您从不可比较的类型(迭代器标记)继承,因此默认比较被定义为已删除。
Is there a way to explicitly say this struct should meet the requirements and constraints of the concept
没有。