1 Востаннє редагувалося Yola (28.12.2017 09:50:07)

Тема: Як створити опереатор доступу схожий на A(1,:,1) як в Matlab

Пишу клас багатовимірного масиву, вимірність задається шаблонним параметром. Потрібно реалізувати оператор який повертає ітератор на відповідний вимір, тобто для матриці

1 2
3 4

в Matlab A(:,1) повертає 1 3, а A(1,:) повертає 1 2. Мені треба якось красиво передати цю двокрапку. Я не можу вигадати нічого краще ніж

template <size_t Dim> class Mat {
template <size_t VDim>
VectorIterator getVector(const array<size_t, VDim>&, const array<size_t, Dim - VDim - 1>&);
};
...
Mat<4> mat(...);
mat.getVector<2>({1,2}, {3}); // те саме, що і A(1,2,:,3)

Чи є щось краще?

---
Насправді getVector виглядає якось так, бо std::array<T, 0> не визначений:

template <size_t VDim, typename enable_if<VDim == 0>::type* = nullptr>                  const_iterator getVector(const array<size_t, Dim - 1>& indexAfter) const;
template <size_t VDim, typename enable_if<0 < VDim && VDim < Dim - 1>::type* = nullptr> const_iterator getVector(const array<size_t, VDim>& indexBefore, array<size_t, Dim - VDim - 1>& indexAfter) const;
template <size_t VDim, typename enable_if<VDim == Dim-1>::type* = nullptr>                  const_iterator getVector(const array<size_t, Dim - 1>& indexBefore) const;

Наводжу це окремо, щоб не відтіняти основну логіку.

Подякували: koala, 0xDADA11C7, leofun013

2

Re: Як створити опереатор доступу схожий на A(1,:,1) як в Matlab

А ці : можуть бути виключно такими, чи ними можна якісь інтервали задавати? Типу

    1 2 3 4
M = 5 6 7 8
    1 2 3 4
M(2,2:3) ->{6,7} (елементи з 2 по 3 рядка 2, якщо індекси з 1)?

І чим має бути M(:,:) - це ніби ж увесь масив, як по ньому ітератор працює? Чи назва "ітератор" умовна, і не означає можливість власне ітерації?

Подякували: Yola, leofun012

3

Re: Як створити опереатор доступу схожий на A(1,:,1) як в Matlab

koala написав:

...

Гадаю, що без M(2,2:3) поки можна обійтись, бо M(2,:) повертає ітератор і я можу зробити наприклад transform(it[2], it[3]).

Так ітератор - це не просто назва, це справжній ітератор, в ньому всередині записана величина кроку, і я можу ітерувати наскрізь масиву.

4 Востаннє редагувалося koala (27.12.2017 15:53:27)

Re: Як створити опереатор доступу схожий на A(1,:,1) як в Matlab

Але ітератор завжди одновимірний, так?
Я просто думаю над варіантом

class Size
{
  bool all_;
  int value_;
  public: 
  implicit Size(int value):all_(false),value_(value){};
  Size():all_(true){}
};
const Size ALL();
template <size_t Dim>
VectorIterator getVector(const array<Size, Dim>&);
...
m.getVector({1,ALL});

Ну а далі вже getVector перевіряє, чи там число, чи ALL. Але як бути, якщо передано два ALL, а це таки ітератор, а не зріз?
Ну і звісно, тоді легко переробити під зрізи

m.getVector({Size(1,10,2),Size(5,3,-1)});

5

Re: Як створити опереатор доступу схожий на A(1,:,1) як в Matlab

Так, одновимірний.

Я думав про подібний варіант, мене зупинило, що я не можу згенерувати помилку під час компіляції, що передали два ALL в масиві.

6

Re: Як створити опереатор доступу схожий на A(1,:,1) як в Matlab

Схоже, ваш варіант близький до оптимального. Ще можна подумати, щоб передавати номер виміру, по якому ведеться ітерування, але кількість інших параметрів його і так дозволяє знайти.

Подякували: Yola1