Пользовательский итератор для представления элемента в векторе - PullRequest
1 голос
/ 04 апреля 2020

Класс элемента, который раньше хранился в векторе с другими подобными элементами.

Но теперь он был удален и перемещен в собственное поле в родительском объекте.

class OldParent {
    vector<char> OldCollection = { 'A', 'B', 'C' };
}

class NewParent {
    char A = 'A';
    vector<char> NewCollection = { 'B', 'C' };
}

Тип, который содержится в векторе, значительно сложнее, чем символ, он является вектором sh структуры.

Таким образом, фактический исходный тип будет выглядеть примерно так:

struct ActualType {
   string val1;
   int val2;
   double val3;
}

vector<vector<ActualType>> OldCollection;

// vector that has been separated out
vector<ActualType> SeparatedCollection;

Проблема заключается в том, что во многих исходных кодах используются итераторы для всей старой коллекции, и, как я думал, я мог бы Реализация этого изменения будет заключаться в создании итератора, который будет работать так, как если бы разделенное поле никогда не разделялось. Таким образом, большая часть исходного кода не должна была быть изменена.

Однако я определенно открыт и для новых идей.

Вариант использования выглядит следующим образом: изменение означает, что одно из чисел будет постоянно храниться вне вектора.

vector<int> nNums = {1,2,3};

void UseCase(int x)
{
    int toRemove = 0;
    for (auto& num : nNums)
    {
         if (num - x < 0)
         {
            toRemove++;
            x -= num;
         }
         else
         {
            num -= x;
            break;
         }
         for (int i = 0; i < toRemove; ++i)
            nNums.erase(nNums.begin());
    }
}

1 Ответ

0 голосов
/ 04 апреля 2020

Вот демонстрационный пример для пользовательского контейнера, который будет принимать указатели как на отдельный объект, так и на контейнер для остальных объектов:

#include <vector>
#include <iostream>
#include <cmath>

template <typename T>
class CustomIterator;

template <typename T>
class CustomContainer
{

public:
    CustomContainer(std::vector<T> *container, T *separated) : mContainer{container},
                                                               mSeparated{separated} {}
    std::vector<T> *GetContainer() { return mContainer; }
    T *GetSeparated() { return mSeparated; }
    inline CustomIterator<T> begin() { return CustomIterator<T>(this); }
    inline CustomIterator<T> end() { return CustomIterator<T>(this, mContainer->size() + 1); }

private:
    std::vector<T> *mContainer;
    T *mSeparated;
};

template <typename T>
class CustomIterator
{
public:
    CustomIterator(CustomContainer<T> *container) : mCustomContainer{container}, mPos{0} {}
    CustomIterator(CustomContainer<T> *container, int pos) : mCustomContainer{container}, mPos(pos) {}
    CustomIterator(const CustomIterator<T> &other) = default;
    const CustomContainer<T> *GetContainer() const { return mCustomContainer; }
    const int GetPos() const { return mPos; }
    ~CustomIterator() {}

    CustomIterator<T> &operator=(const CustomIterator<T> other)
    {
        mCustomContainer = other.GetContainer();
        mPos = other.GetPos();
    };

    bool operator==(const CustomIterator<T> &other) { return other.GetContainer() == mCustomContainer && other.mPos == mPos; }
    bool operator!=(const CustomIterator<T> &other) { return other.GetContainer() != mCustomContainer || other.mPos != mPos; }

    CustomIterator<T> operator+=(const int &movement)
    {
        if (mPos + movement > mCustomContainer->GetContainer()->size() + 1)
            mPos = mCustomContainer->GetContainer()->size() + 1;
        else
            mPos += movement;
        return CustomIterator<T>(*this);
    }
    CustomIterator<T> operator-=(const int &movement)
    {
        if (mPos - movement < 0)
            mPos = 0;
        else
            mPos -= movement;
        return CustomIterator<T>(*this);
    }
    CustomIterator<T> operator++()
    {
        const auto maxSize = mCustomContainer->GetContainer()->size() + 1;
        mPos = mPos == maxSize ? maxSize : mPos + 1;
        return CustomIterator<T>(*this);
    }
    CustomIterator<T> operator--()
    {
        mPos = mPos == 0 ? 0 : mPos - 1;
        return CustomIterator<T>(*this);
    }

    int operator-(const CustomIterator<T> &other) { return std::abs(other.GetPos() - mPos); }

    T &operator*()
    {
        const auto maxSize = mCustomContainer->GetContainer()->size() + 1;

        if (mPos == maxSize)
        {
            throw "Error: index out of bounds";
        }
        else if (mPos == 0)
        {
            return *(mCustomContainer->GetSeparated());
        }

        return (*mCustomContainer->GetContainer()).at(mPos - 1);
    }
    T &operator->() { this->operator*(); }

private:
    CustomContainer<T> *mCustomContainer;
    int mPos;
};

int main()
{
    std::vector<int> container = {5, 6};
    int separated = 4;
    auto customContainer = CustomContainer<int>(&container, &separated);

    for (auto i : customContainer)
    {
        std::cout << (i) << std::endl;
    }

    return 0;
}
...