使用自定义迭代器封装地图的容器 class

Container class that encapsulates map with custom iterators

我想制作一个 class 来封装一个 std::map 并充当不同类型的容器,如下所示:

class Item
{
public:
    Item(int number, const char *text) :
        Number(number),
        Text(text)
    {}

    int Number;
    std::string Text;
};

class Container
{
public:

    void add(Item item)
    {
        Map.insert(std::make_pair(item.Number, item.Text));
    }

    Container::iterator begin();
    Container::iterator end();

private:
    std::map <int, string> Map;
};

我想这样用,不使用地图的firstsecond:

int main()
{
    Container container;
    container.add(Item(0, "foo"));
    container.add(Item(1, "bar"));

    for (auto &elem : container)
    {
        // elem is an Item
        cout << elem.Number << elem.Text << endl;
    }
}

我尝试实现一个封装了映射迭代器的自定义迭代器,但我卡在了 -> 运算符上,它必须 return 一个 Item 对象的地址(对吗? ) 没有 Item 对象的地址我可以 return.

你是怎么做到的?

我不确定,但看起来您正在寻找结构化绑定。

类似

std::map<int, std::string> myMap{};

for (const auto &[num, txt] : myMap) {
    // elem is an Item
    cout << num << ' ' << txt << '\n';
}

请阅读here

但是如果您真的对这种自定义容器的迭代器实现感兴趣,请看下面:

#include <iostream>
#include <string>
#include <map>
#include <iterator>
#include <utility>
#include <type_traits>

using Pair = std::pair<int, std::string>;
using Map = std::map<Pair::first_type, Pair::second_type>;

struct Item {
    Pair::first_type number{};
    Pair::second_type text{};
};

class Container {
    Map data{};
public:

    void add(Item item) { data.insert({ item.number, item.text }); }

    // Add iterator properties to class ---------------------------------------------------------------
    class iterator {                  // Local class for iterator
        Map::iterator iter{};         // This will be the internal iterator 
        Map::iterator begin{};        // For boundary checking
        Map::iterator end{};

        Item item;
    public:                                    // Define alias names necessary for the iterator functionality
        using iterator_category = std::random_access_iterator_tag;
        using difference_type = std::ptrdiff_t;
        using value_type = Item;
        using pointer = const Item* const;
        using reference = Item&;

        // Constructor
        iterator(const Map::iterator& i, const Map::iterator& ibegin, const Map::iterator& iend) : iter(i), begin(ibegin), end(iend) {};

        // Dereferencing
        value_type operator *() const { return { iter->first, iter->second }; }
        pointer operator ->() { item = { iter->first, iter->second }; return &item; }

        // Aithmetic operations
        iterator& operator ++() { if (iter != end) ++iter; return *this; }
        iterator& operator --() { if (iter != begin) --iter; return *this; }
        
        iterator operator ++(int) { iterator tmp{ *this }; ++iter; return tmp; }
        iterator operator --(int) { iterator tmp{ *this }; ++iter; return tmp; }
        iterator operator +(const difference_type& n) const { iterator tmp{ *this };  difference_type k{ n }; while (k--)++tmp; return tmp; }
        iterator& operator +=(const difference_type& n) { difference_type k{ n }; while (k--)++* this; return *this; };
        iterator operator -(const difference_type& n) const { iterator tmp{ *this };  difference_type k{ n }; while (k--)--tmp; return tmp; }
        iterator& operator -=(const difference_type& n) { difference_type k{ n }; while (k--)--* this; return *this; };
        
        // Comparison
        bool operator != (const iterator& other) const { return iter != other.iter; }
        bool operator == (const iterator& other) const { return iter == other.iter; }
        bool operator < (const iterator& other) const { return (other - *this) < 0; }
        bool operator > (const iterator& other) const { return (other - *this) > 0; }
        bool operator <= (const iterator& other) const { return (other - *this) <= 0; }
        bool operator >= (const iterator& other) const { return (other - *this) >= 0; }

        // Reference and difference. Also very questionable
        reference operator[] (const difference_type& n) {
            iterator tmp(begin, begin, end);  
            difference_type k{ n }; while (k--) ++tmp;
            item = *tmp;
            return item;
        }
        //Extermely complex and unefficient
        difference_type operator-(const iterator& other) const {
            difference_type result{};
            if (*this != other) {
                iterator tmp(iter, begin, end);

                while ((tmp.iter != other.iter) and tmp.iter != end) {
                    ++tmp;
                    ++result;
                }
                if (tmp.iter == end) {
                    result = 0;
                    iterator tmpOther(other.iter, other.begin, other.end);
                    while ((tmpOther.iter != iter) and tmpOther.iter != other.end) {
                        ++tmpOther;
                        --result;
                    }
                }
            }
            return result;
        }
    };
    iterator begin() { return iterator(data.begin(), data.begin(), data.end()); }
    iterator end() { return iterator(data.end(), data.begin(), data.end()); }
};
// Test Code
int main() {
    Container c;
    c.add({ 1,"111" });
    c.add({ 2,"222" });
    c.add({ 3,"333" });
    c.add({ 4,"444" });

    for (const Item& i : c)
        std::cout << i.number << ' ' << i.text << '\n';
}