例如,考虑一些假设的to_upper_iterator
迭代一系列字符,为std::toupper
返回operator*
。这些迭代器别名对我有意义:
template <typename CharT>
struct to_upper_iterator
{
using value_type = CharT;
using reference = CharT;
using difference_type = std::ptrdiff_t;
using iterator_category = std::random_access_iterator_tag;
};
没有有意义的是pointer
别名应该/可以使用的内容。我试着把它关掉,但果然我有编译错误。似乎这是由于C ++中的添加17。 en.cppreference.com为std::iterator_traits
类型汇总:
如果
Iterator
没有五种成员类型difference_type
,value_type
,pointer
,reference
和iterator_category
,那么此模板没有任何成员的名字(std::iterator_traits
是SFINAE友好的)
所以问题是:对于这样的类型,我应该将pointer
定义为某些 - 我最喜欢的是void
或void*
- 或者做一些像special std::iterator_traits<to_upper_iterator>
这样的事情更有意义,因此它不包含pointer
的别名。
答案 0 :(得分:4)
OutputIterator
的标准c ++模型将全部定义为void
。
示例:http://en.cppreference.com/w/cpp/iterator/back_insert_iterator
对于那些在迭代器类型的上下文中没有意义的类型,我倾向于这样做。
你的这个迭代器看起来像是在建模适配器的概念。在这种情况下,我可能倾向于从这些方面开始:
#include <algorithm>
#include <string>
#include <iterator>
#include <utility>
#include <iostream>
template <typename BaseIter>
struct to_upper_iterator
{
using value_type = typename std::iterator_traits<BaseIter>::value_type;
using reference = std::add_lvalue_reference_t<std::add_const_t<value_type>>;
using pointer = std::add_pointer_t<std::add_const_t<value_type>>;
using difference_type = typename std::iterator_traits<BaseIter>::difference_type;
using iterator_category = typename std::iterator_traits<BaseIter>::iterator_category;
to_upper_iterator(BaseIter iter = BaseIter()) : iter_(iter) {}
value_type operator*() const { return std::toupper(*underlying()); }
to_upper_iterator& operator++()
{
iter_++;
return *this;
}
to_upper_iterator operator++(int)
{
auto copy = *this;
iter_++;
return copy;
}
bool operator!=(const to_upper_iterator& other) const {
return iter_ != other.iter_;
}
// etc. use enable_if to enable functionality depending on iterator_category
private:
BaseIter& underlying() { return iter_; }
BaseIter const& underlying() const { return iter_; }
BaseIter iter_;
};
template<class Iter>
auto make_upper_iterator(Iter iter)
{
return to_upper_iterator<Iter>(iter);
}
int main()
{
std::string a = "abcdef";
auto first = make_upper_iterator(a.begin());
auto last = make_upper_iterator(a.end());
std::copy(first, last, std::ostream_iterator<char>(std::cout));
std::cout << std::endl;
const char b[] = "abcdef";
std::copy(make_upper_iterator(std::begin(b)),
make_upper_iterator(std::end(b) - 1),
std::ostream_iterator<char>(std::cout));
std::cout << std::endl;
}
答案 1 :(得分:2)
to_upper_iterator::pointer
应该是一种可以指向value_type
的类型,并标记您无法修改应该使其成为常量的值,即const CharT*
答案 2 :(得分:0)
添加我自己的答案,但假设SO不强迫我,不会将其标记为答案。似乎相关的措辞在§27.4.1
中27.4.1迭代器特征[iterator.traits]
要仅根据迭代器实现算法,通常需要确定值和差异 与特定迭代器类型对应的类型。因此,如果
Iterator
是类型,则需要 迭代器,类型iterator_traits<Iterator>::difference_type iterator_traits<Iterator>::value_type iterator_traits<Iterator>::iterator_category
分别定义为迭代器的差异类型,值类型和迭代器类别。除此之外 类型
iterator_traits<Iterator>::reference iterator_traits<Iterator>::pointer
应定义为迭代器的引用和指针类型,即对于迭代器对象
a
,类型相同 分别为*a
和a->
的类型。在输出迭代器的情况下,类型iterator_traits<Iterator>::difference_type iterator_traits<Iterator>::value_type iterator_traits<Iterator>::reference iterator_traits<Iterator>::pointer
可以定义为
void
。
在我的情况下,operator->
没有意义,因为我只是返回字符类型,所以我可能会因为@Richard Hodges的建议而逃脱void
。我认为一般情况下的“正确”答案是定义一些pointer_proxy<T>
类型(假设STL中尚不存在这样的东西),其中包含T
并定义operator->
返回T*
并将其用于迭代器的pointer
类型