【问题标题】:Custom Iterator to pretend element is in vector假装元素的自定义迭代器在向量中
【发布时间】:2020-04-04 04:36:30
【问题描述】:

一类元素,过去与其他相似元素存储在一个向量中。

但现在,它已被移除并移动到父对象中自己的字段中。

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

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

向量所持有的类型比字符复杂得多,它是一个正常结构的向量。

所以实际的原始类型看起来像这样:

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());
    }
}

【问题讨论】:

  • public class OldParent... 这是什么? C#?
  • @IndianaKernick 哎呀错字了。
  • 如果我理解正确的问题,您可以创建自己的类型并重载迭代器将使用的通用运算符(如 * 和 ++)。然后你可以说“如果你到达旧集合的末尾 (OldCollection.end()) 然后返回separatedCollection 并翻转一些布尔值。然后一旦你尝试再次增加一些布尔值现在可以返回OldCollection。结尾()”。这会起作用,但不是解决问题的干净方法。您可能应该只是通过并修复旧代码。也许您也可以只使用 Old 的第一个索引来分隔?
  • 你应该添加你期望如何使用类/变量。'
  • @appleapple 它是一个存储几个字段的结构体。

标签: c++ c++11 c++14 c++17


【解决方案1】:

这是一个自定义容器的演示,它将同时指向分离的对象和其余对象的容器:

#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;
}

【讨论】:

  • 就像 Kyle Liebler 提出的那样,这不是一个优雅的解决方案,更改现有代码可能会更好。
猜你喜欢
  • 2021-02-14
  • 2019-04-07
  • 1970-01-01
  • 1970-01-01
  • 2016-10-11
  • 2020-03-08
  • 2016-04-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多