使用混合const和非const元素模拟std :: vector

时间:2014-04-28 05:04:48

标签: c++ const

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

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

第二种解决方案可能是拥有相同的容器,但这次写入访问是通过将数组编辑功能传递给容器的成员函数来完成的。容器成员函数会让数组编辑函数进入数组,然后检查它是否写入不可写元素。这有一个缺点,即数组编辑功能可能是偷偷摸摸的,并将非常量指针传递给数组元素,让容器函数检查一切正常,然后写入不可写元素。

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

有更好的解决方案吗?

编辑:Ben的评论有一个好处,我应该在问题中解决:为什么不是const的向量和非const的向量?

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

1 个答案:

答案 0 :(得分:1)

我认为您可以通过以下课程完成您的工作,这个课程非常简化,以说明主要概念。

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

运行程序的输出:

Expected to see this.
Got c[0]: 10
Got c[1]: 20
Got c[1]: 20
Got c[0]: 10
Got c[0]: 10
Got c[1]: 20
Got c[1]: 20
Expected to see this.
Got c[1]: 200