Как мне реализовать оператор [] для этой структуры? - PullRequest
3 голосов
/ 22 ноября 2010

Я хочу иметь что-то вроде этого ниже:

template <class T>
struct Container{
 public:
  //[] operator
 private:
  T containment;
};

Предполагается, что сдерживающим элементом является массив с произвольным числом измерений, как показано ниже:

Container<int[20][4]> obj;
Container<int[5][2][6]> obj1;
//etc...

И я хочу реализовать оператор [], чтобы были возможны следующие назначения:

obj[2][3]=6;
obj1[1][1][3]=3;
//etc...

Но после нескольких попыток я застрял, как это возможно?

Ответы [ 5 ]

5 голосов
/ 22 ноября 2010

Ваш оператор подписки должен вернуть прокси-объект, который сам реализует оператор подписки.

Если мы разложим вызов на obj[2][3] = 6, это даст:

  • obj[2] -> прокси-объект
  • obj[2][6] -> ссылка на int

Глядя на obj1, вы поймете, что все, кроме последнего [], должны возвращать прокси-объект.

Обычно это происходит из-за использования шаблонного прокси с параметром «глубины» и его специализации для подходящей глубины. В вашем случае у вашего прокси будет указатель на T для первого элемента, который он может выдать, а также список измерений (в качестве параметров шаблона).

Это не тривиально, потому что вам нужно произвольное количество параметров, как кажется. В зависимости от того, поддерживает ли ваш целевой компилятор переменные шаблоны, вы действительно можете испытать некоторое горе.

3 голосов
/ 22 ноября 2010

Вы можете сделать это примерно так (хотя новый шаблон для каждой размерности).

template <class T, size_t m, size_t n>
struct Container{
 public:
  int& operator()(size_t i, size_t j)
  {
      return containment[i][j];
  }

 private:
  T containment[m][n];
};

Container<int, 3, 4> ints;
ints(0,3) = 5;

Или вы можете использовать Boost.MultiArray и сэкономить много боли.

Улучшена библиотека Boost MultiArray стандартные контейнеры C ++ с универсальный многомерный массив абстракции. Включает в себя общий шаблон класса массива и собственный массив адаптеры, которые поддерживают идиоматический массив операции и взаимодействовать с C ++ Стандартные библиотеки контейнеров и алгоритмы. Массивы имеют общий интерфейс, выраженный как общий программирование с точки зрения которого общий алгоритмы массива могут быть реализованы.

2 голосов
/ 22 ноября 2010

Сложность в том, чтобы знать тип возврата operator[].Вы можете попробовать что-то вроде этого:

template <class T, size_t N>
struct Container {
T containment[N];
T &operator[](size_t index) { return containment[index]; }
};

Container<int[2][6], 5> obj;

В качестве альтернативы вы можете определить контейнер в терминах самого себя:

Container<Container<Container<int[6]>[2]>[5]> obj;
1 голос
/ 22 ноября 2010

Кто думал, что ссылка вступит в игру здесь?я!
Благодаря Ники Йошиучи, я хочу получить точный ответ следующим образом:

template <class T, size_t N>
struct Container {
private:
 T containment[N];
public:
 T & operator[](size_t index) { return containment[index]; }
};

Container<int[3][3][3],2> obj;
obj[1][1][1][1]=7;
0 голосов
/ 22 ноября 2010

Основы создания n-мерной коллекции будут примерно такими. Предполагается, что контейнер не может быть переразмерен.

template< typename T >
class MultiDimContainer
{
   std::vector<size_t> dims;

   std::vector<T> data;

public:
   MultiDimContainer( const std::vector<size_t> dims )
   {
       // work out the product of dims and set data to that size
   }

   T& at( const std::vector<size_t> & dim )
   {
      // calculate where it lives in memory and return that element
   }
};

Как я реализовал в (), чтобы получить один параметр, вы можете использовать для этого оператор []. Вы, вероятно, захотите 2 перегрузки, одну const и одну неконстантную, и at () будет проверять границы, в то время как operator [] не будет. Возможно, вы захотите, чтобы одна вспомогательная (не шаблонная) функция вычисляла местоположение этого элемента в векторе данных.

Конечно, построение вектора является многошаговым процессом, поэтому вы можете использовать некоторый магический класс для его создания.

Вы также можете иметь оператор [] для вашего контейнера, который будет принимать один size_t и будет возвращать объект ContainerReferencer. Это не настоящий многомерный массив, а кусочек данных, хранящихся в другом месте. Еще раз могут быть константные или неконстантные версии.

Получение нескольких вызовов оператора [] для фильтрации до значения типа T или ссылки на него невозможно при использовании этой модели.

Было бы возможно использовать массив с жесткими размерами, который мог бы быть параметром шаблона. Так что, если вы знаете, что это 4-мерное измерение, вы бы назвали это

MultiDimCollection

и он всегда будет иметь 4 измерения. Затем вы можете заставить оператора [] возвращать MultiDimCollectionReference

это уменьшится до 2 и 1 (вектор), тогда это будет специализировано для возврата скаляра.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...