Аргументы многомерного массива фиксированного размера - PullRequest
2 голосов
/ 20 марта 2012

Я пишу универсальный матричный класс на С ++. Я хочу иметь возможность инициализировать матрицу из двумерного двойного массива. Поскольку я использую шаблоны и поэтому размеры матриц должны быть известны во время компиляции, я хочу убедиться, что в массив можно передать только массивы заданного размера. Выражено в коде это:

template<unsigned int M, unsigned int N>
class Matrix {
public:
    Matrix(double (&values)[M][N]);
}

Теперь вот странная часть: как и ожидалось, следующий код работает как шарм:

    double arr [3][3] = { {1,2,3},
                          {1,2,3},
                          {1,2,3} };
    Matrix<3,3>* mat3x3p = new Matrix<3,3>(arr);

Но при анонимной передаче массива код нарушается:

Matrix<3,3>* mat3x3p = new Matrix<3,3>({ {1,2,3},
                                         {1,2,3},
                                         {1,2,3} });

То же самое относится и к строительству через назначение. Точное сообщение об ошибке:

no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘double (&)[3][3]’

Ответы [ 2 ]

2 голосов
/ 20 марта 2012

Это будет связывать временную ссылку (lvalue) с не-const, и это недопустимо. Если вы измените ссылку на const, это сработает - хотя в случае с массивом это немного странно, поскольку cv -квалификаторы применяются к типу элемента, а не к самому массиву. Тем не менее, если у вас есть

Matrix(const double (&values)[M][N]);

тогда

Matrix<3, 3>({{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }})

действительно в C ++ 11, благодаря инициализации списка. Я не знаю, как заставить это работать на C ++ 03.

1 голос
/ 20 марта 2012

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

...