如何创建可调整大小和固定大小的容器的变体

我有一类,其基础数据是std::vectorstd::unique_ptrstd::deque的变体。这显示在下面的代码中。

template<class T>
class matrix2d
{
private:
    typename std::variant<std::vector<T>,std::unique_ptr<T[]>,std::deque<T>> data;

public:
    matrix2d<T>() = delete;
    matrix2d<T>(size_t h,size_t w,int type) {
        try {
            switch (type) {
            case 0:
                data = std::vector<T>(h*w);
                break;
            case 1:
                data = std::make_unique<T[]>(h*w);
                break;
            case 2:
                data = std::deque<T>(h*w);
                break;
            default:
                throw std::runtime_error("Unrecognized type of matrix2d class data");
            }
        }
        catch (const std::exception& e) {
            std::cerr << e.what() << std::endl;
        }
    }
    auto operator[](size_t i) {
        return (std::begin(data) + i);
    }
};

int main()
{
    matrix2d<int> a2d(4,5,0);
    for (size_t i{}; i<4; ++i) {
        for (size_t j{}; j<5; ++j) {
            a2d[i][j] = 5.0;
        }
    }
}

我的问题如下:

是否可以创建unique_ptr和其他可调整大小的容器的并集?
另外,如何重载下标运算符[]使类作为二维数组起作用?

xianggujidan 回答:如何创建可调整大小和固定大小的容器的变体

该变体有效。

然而,用于访问行的用法一方面需要对std::vector<T>std::unique_ptr<T[]> 和另一方面std::deque<T> 进行不同的处理。由于vectorunique_ptr<T[]>使用连续内存,因此deque的元素不需要连续存储。

假设我们要首先仅对vector和unique_ptr实现operator []。

步骤1

我们需要向该类添加一个可以容纳行大小的成员,这是计算行号i数组中位置的必要条件。

因此,假设您添加了一个私人成员'w':

size_t w;

,然后在构造函数中对其进行初始化:

matrix2d<T>(size_t h,size_t w,int type) : w(w) {
   // ...

步骤2

现在我们正在寻找的operator []看起来像这样:

auto operator[](size_t i) {
    return std::visit([i,w = this->w](auto&& arg){return &arg[i*w];},data);
}

即使我们在std::visit管理的任何类型上使用相同的操作,也需要使用std::variant。但是,std::visit对于每种存储的类型也可以有不同的操作,请参见std::visit on cppreference

步骤3

如果我们也想支持deque,则需要不同的对待。

当前,我们的operator []返回T *,我们想保留它。

对于双端队列,我们​​不能仅获取一行中第一个元素的地址,并假设同一行中的所有元素都紧接相邻地连续存储。因此,为了允许以相同的方法使用双端队列,我们​​至少需要行是连续的。我们可以用Ts向量的双端队列来实现。在类的variant声明中可能看起来像这样:

 std::variant< std::vector<T>,std::unique_ptr<T[]>,td::deque<std::vector<T>> > data;

在构造函数中,deque的初始化为:

case 2: { // TODO: use enum instead
  auto d = std::deque<std::vector<T>>(h);
  for(auto& item : d) {
    item = std::vector<T>(w);
  }
  data = d;
}
break;

operator []现在将更改为:

auto operator[](size_t i) {
    return std::visit([i,w = this->w](auto&& arg){
        using U = std::decay_t<decltype(arg)>;
        if constexpr (std::is_same_v<U,std::deque<std::vector<T>>>) {
            return &arg[i][0];
        }
        else {
            return &arg[i*w];
        }
    },data);
}

http://coliru.stacked-crooked.com/a/192fbf6705aecc7c

本文链接:https://www.f2er.com/2921122.html

大家都在问