模拟std::vector和const元素的混合

Simulate std::vector with mixed const and non-const elements

本文关键字:元素 const 混合 std vector 模拟      更新时间:2023-10-16

我想模拟一个混合了常量和非常量元素的std::向量。更具体地说,我希望函数对向量进行运算,并允许查看整个向量,但只能写入特定元素。可以写入和不能写入的元素将在运行时确定,并且可能在运行时更改。

一种解决方案是创建一个容器,其中包含一个元素数组和一个大小相等的布尔数组。所有的非常量访问都将通过一个函数进行,如果写入有效,该函数将检查布尔数组,否则将抛出异常。这样做的缺点是每次写入都要添加一个条件。

第二种解决方案可能是使用相同的容器,但这次写访问是通过将数组编辑函数传递给容器的成员函数来完成的。容器成员函数会让数组编辑函数访问数组,然后检查它是否没有写入不可写的元素。这样做的缺点是,数组编辑函数可能很狡猾,会向数组元素传递非常数指针,让容器函数检查是否一切正常,然后写入不可写的元素。

最后一个问题似乎很难解决。提供直接可写访问似乎意味着我们必须始终假设直接可写的访问。

有更好的解决方案吗?

编辑:本的评论有一个很好的观点,我应该在这个问题上解决:为什么不使用常量向量和非常量向量?

问题是,我想到的场景是,我们的元素在概念上是一个数组的一部分。它们在数组中的位置是有意义的。要使用常量和非常量向量,需要将概念中存在的单个数组映射到将实现它的两个向量。此外,如果可写元素的列表发生变化,则需要移动两个向量中的元素或指针。

我认为您可以通过下面的类来实现您想要的,为了说明主要概念,这个类经过了非常简化。

template <typename T>
struct Container
{
   void push_back(bool isconst, T const& item)
   {
      data.push_back(std::make_pair(isconst, item));
   }
   T& at(size_t index)
   {
      // Check whether the object at the index is const.
      if ( data[index].first )
      {
         throw std::runtime_error("Trying to access a const-member");
      }
      return data[index].second;
   }
   T const& at(size_t index) const
   {
      return data[index].second;
   }
   T const& at(size_t index, int dummy) // Without dummy, can't differentiate
                                        // between the two functions.
   {
      return data[index].second;
   }
   T const& at(size_t index, int dummy) const // Without dummy, can't differentiate
                                              // between the two functions.
   {
      return data[index].second;
   }
   std::vector<std::pair<bool, T> > data;
};

这是一个测试程序及其输出。

#include <stdio.h>
#include <iostream>
#include <utility>
#include <stdexcept>
#include <vector>
//--------------------------------
// Put the class definition here.
//--------------------------------
int main()
{
   Container<int> c;
   c.push_back(true, 10);
   c.push_back(false, 20);
   try
   {
      int value = c.at(0); // Show throw exception.
   }
   catch (...)
   {
      std::cout << "Expected to see this.n";
   }
   int value = c.at(0, 1); // Should work.
   std::cout << "Got c[0]: " << value << "n";
   value = c.at(1); // Should work.
   std::cout << "Got c[1]: " << value << "n";
   value = c.at(1, 1); // Should work.
   std::cout << "Got c[1]: " << value << "n";
   // Accessing the data through a const object.
   // All functions should work since they are returning
   // const&.
   Container<int> const& cref = c;
   value = cref.at(0); // Should work.
   std::cout << "Got c[0]: " << value << "n";
   value = cref.at(0, 1); // Should work.
   std::cout << "Got c[0]: " << value << "n";
   value = cref.at(1); // Should work.
   std::cout << "Got c[1]: " << value << "n";
   value = cref.at(1, 1); // Should work.
   std::cout << "Got c[1]: " << value << "n";
   // Changing values ... should only work for '1'
   try
   {
      c.at(0) = 100; // Show throw exception.
   }
   catch (...)
   {
      std::cout << "Expected to see this.n";
   }
   c.at(1) = 200; // Should work.
   std::cout << "Got c[1]: " << c.at(1) << "n";
}

运行程序输出:

期望看到此。得到c[0]:10得到c[1]:20得到c[1]:20得到c[0]:10得到c[0]:10得到c[1]:20得到c[1]:20期望看到此。得到c[1]:200