当没有任何意义时,如何使用“Iterator::pointer”?

Dun*_*can 5 c++

例如,考虑一些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;
};
Run Code Online (Sandbox Code Playgroud)

没有意义的是别名应该/可以使用什么pointer。我尝试将其关闭,但果然出现了编译错误。这似乎是由于 C++17 中的添加所致。en.cppreference.com总结的类型std::iterator_traits

如果Iterator不具有五种成员类型difference_typevalue_typepointerreferenceiterator_category,则此模板没有任何这些名称的成员(std::iterator_traits对 SFINAE 友好)

所以问题是:对于这样的类型,我应该只定义pointer一些东西- 我最喜欢的东西是voidvoid*- 或者做一些像专门化这样的事情更有意义,std::iterator_traits<to_upper_iterator>这样它就不包含pointer.

Ric*_*ges 4

标准 C++ 模型OutputIterator全部定义为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;
}
Run Code Online (Sandbox Code Playgroud)