简体   繁体   English

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

[英]Simulate std::vector with mixed const and non-const elements

I'd like to simulate a std::vector that has mixed const and non-const elements. 我想模拟具有混合const和非const元素的std :: vector。 More specifically, I want to have functions that operate on a vector and are allowed to see the entire vector but may only write to specific elements. 更具体地说,我想拥有对向量进行操作并允许看到整个向量但只能写入特定元素的函数。 The elements that can and cannot be written will be determined at runtime and may change during runtime. 可以写入和不能写入的元素将在运行时确定,并可能在运行时更改。

One solution is to create a container that holds an array of elements and an equal sized array of booleans. 一种解决方案是创建一个容纳元素数组和相等大小的布尔数组的容器。 All non-const access would be through a function that checks against the boolean array if the write is valid and throws an exception otherwise. 所有非常量访问都将通过一个函数进行,该函数将检查布尔数组,如果写入有效,否则将引发异常。 This has the downside of adding a conditional to every write. 这样做的缺点是在每次写入时都添加了条件。

A second solution might be to have the same container but this time write access is done by passing an array editing function to a member function of the container. 第二种解决方案可能是使用相同的容器,但是这次通过将数组编辑函数传递给容器的成员函数来完成写访问。 The container member function would let the array editing function go at the array and then check that it didn't write to the non-writable elements. 容器成员函数将让数组编辑函数进入数组,然后检查它是否未写入不可写元素。 This has the downside that the array editing function could be sneaky and pass around non-const pointers to the array elements, let the container function check that all is well, and then write to non-writable elements. 不利之处在于,数组编辑功能可能会偷偷摸摸,并将非const指针传递给数组元素,让容器函数检查一切是否正常,然后再写入不可写元素。

The last issue seems difficult to solve. 最后一个问题似乎很难解决。 It seems like offering direct writable access ever means we have to assume direct writable access always. 提供直接可写访问似乎意味着我们必须始终假设直接可写访问。

Are there better solutions? 有更好的解决方案吗?

EDIT: Ben's comment has a good point I should have addressed in the question: why not a vector of const and a vector of non-const? 编辑:本的评论有一个好点,我应该在这个问题中解决:为什么不使用const向量和非const向量呢?

The issue is that the scenario I have in mind is that we have elements that are conceptually part of one single array. 问题在于,我想到的场景是,我们从概念上讲是一个数组的一部分。 Their placement in that array is meaningful. 它们在该阵列中的位置是有意义的。 To use vectors of const and non-const requires mapping the single array that exist in concept to the two vectors that would implement it. 要使用const和非const向量,需要将概念上存在的单个数组映射到将实现它的两个向量。 Also, if the list of writable elements changes then the elements or pointers in the two vectors would need to be moved about. 同样,如果可写元素列表发生变化,则两个向量中的元素或指针将需要移动。

I think you can accomplish what you wish with the following class, which is very simplified to illustrate the main concept. 我认为您可以通过下面的课程来完成您想要的事情,该课程非常简化以说明主要概念。

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

Here's a test program and its output. 这是一个测试程序及其输出。

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

Output from running the program: 运行程序的输出:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM