2016-03-23 8 views
0

Как перегрузить многомерные кронштейны?Перегрузка многомерных кронштейнов

Предположим, что у меня есть класс, который позволяет мне получить доступ к точкам в n -vector. Например:

class NSpaceVector { 
    private: 
     int vectorSpace[8][8][8][8][8][8][8]; 
    public:   
     const NSpaceVector operator[][][][][][][](int i, int j, int k, int l, int m, int n, int p)const {return vectorSpace[i][j][k][l][m][n][p]; } 
     NSpaceVector operator[][][][][][][](int i, int j, int k, int l, int m, int n, int p) {return vectorSpace[i][j][k][l][m][n][p]; } 
} 
unsigned long & operator [](int i) {return registers[i];} 

То, что я хотел бы сделать, это перегрузка оператора кронштейн, так что я могу индекс в это место так:

int main() { 
    NSpaceVector nsv; // Assume initializes all to 0 
    nsv[2][4][7][4][0][7][6] = 2; 
    cout << nsv[2][4][7][4][0][7][6] << endl; //-> 2 
    cout << nsv[1][4][7][4][0][7][6] << endl; //-> 0 
    return 0; 
} 

Я не могу получить эту компиляцию. Есть идеи? Thx, Keith: ^)

+3

Вы не можете перегрузить многомерную скобку, так как в C++ такого оператора нет. Вместо этого вам нужно перегрузить одну скобку для возврата своего рода прокси-объекта, поскольку каждая перегрузка одномерной скобки будет означать второй уровень индексации, который будет возвращать другой прокси-сервер ... и так далее. – SergeyA

+0

Дайте это прочитать для лучшего способа выполнить это с помощью 'operator()': https://isocpp.org/wiki/faq/operator-overloading#matrix-array-of-array – user4581301

+1

Или, альтернативно, найти другое синтаксис. Как 'nsv (1,2,3,4,5,6,7)' или 'nsv [{1,2,3,4,5,6,7}]'. –

ответ

1

Любые идеи?

Там только возможность перегружать operator[]() для каждого уровня, и пусть возвращаемые типы имеют другую operator[]() перегрузку.


Как уже упоминалось в комментариях, например, как правило, решается с перегрузкой вызов operator():

int operator()(size_t dim1, size_t dim2, ... size_t dimn); 
+0

Этот ответ меня не удовлетворяет. Любой шанс, что мы могли бы добавить это в спецификацию C++ 17? – kmiklas

+0

@kmiklas Извините, что не удовлетворил вас, рассказав факты. Нет никаких изменений в синтаксисе перегрузки оператора с помощью спецификации C++ 17 AFAIK, и я сомневаюсь, что вы убедите стандартную комиссию C++ изменить ее для этой проблемы. –

+0

@kmiklas zilch. Если у вас нет машины времени, то бесконечно малой. –

1

Стандартный ответ должен иметь каждый [] (слева направо) возвращает прокси-сервер для правильное вложенное подмножество, последнее из которых фактически возвращает ссылку на данные. В вашей схеме было бы проще всего создать шаблонные вложенные типы для автоматизации производства.

Как таинственная user4581301 упоминает, что гораздо проще обеспечить

nsv(2,4,7,4,0,7,6) 

Пример производства шаблон нужного класса, вероятно, проще, чем с использованием временного прокси-объекта:

template <size_t Width, size_t Depth, typename T=int> 
struct SubSpace; 

template <size_t Width, typename T> 
struct SubSpace<Width,0,T> { 
    std::array<T, Width> array; 

    T& operator[] (size_t i) { return array[i]; } 
    T const& operator[] (size_t i) const { return array[i]; } 
}; 

template <size_t Width, size_t Depth, typename T> 
struct SubSpace { 
    using Nested = SubSpace<Width, Depth-1, T>; 
    std::array<Nested, Width> array; 

    Nested& operator[] (size_t i) { return array[i]; } 
    Nested const& operator[] (size_t i) const { return array[i]; } 
}; 


using NSpaceVector = SubSpace<8,6>; 

int main() 
{ 
    NSpaceVector nsv; 
    nsv[2][4][7][4][0][7][6] = 2; 
    cout << nsv[2][4][7][4][0][7][6] << endl; //-> 2 
} 

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

NSpaceVector nsv {}; // value-initialize every element 
    nsv[2][4][7][4][0][7][6] = 2; 
    cout << nsv[2][4][7][4][0][7][6] << endl; //-> 2 
    cout << nsv[2][4][7][4][0][7][5] << endl; //-> 0 

отметить также, что SubSpace<8,6> дает 8x7 результат вы хотели, так как глубина заканчивается на 0. Это может быть вычищено с верхним уровнем обертки, но я неохотно оканчиваются на Depth==1 вместо этого и есть все, что идет не так, когда кто-то конкретизирует SubSpace<0,0> случайно.


Simpler еще, в зависимости от того, хотите ли вы любого поведения в классе, это:

struct OtherSpaceVector { 
    int s[8][8][8][8][8][8][8]; 

    auto operator[] (size_t i) -> decltype(s[i]) { return s[i]; } 
}; 

int main() 
{ 
    OtherSpaceVector osv{}; 
    osv[2][4][7][4][0][7][6] = 2; 
    std::cout << osv[2][4][7][4][0][7][6] << '\n'; 
    std::cout << osv[2][4][7][4][0][7][5] << '\n'; 
} 

Труднее изменять размеры и чувствует себя более хрупким, чем версия шаблона, но все еще работает для используемого вами случая.