Инициализация класса массивом

117
28 октября 2019, 14:20

у меня есть следующий класс со следующим конструктором:

template<class Type>
class Matrix4x4 
{ 
public:
    ...
    Matrix4x4(const Type* array) noexcept;
    ...
private:
    Type mElements[MATRIX_SIZE] = { 
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
    };
}
template<class Type>
Matrix4x4<Type>::Matrix4x4(const Type* array) noexcept
{
    for (std::uint8_t i = 0; i < MATRIX_SIZE; i += ROW_SIZE)
    {
        mElements[i] = array[i];
        mElements[i + 1] = array[i + 1];
        mElements[i + 2] = array[i + 2];
        mElements[i + 3] = array[i + 3];
    }
}

И когда я хочу сделать вот так:

Math::Matrix4x4f matrix({
    mx.getX(), mx.getY(), mx.getZ(), -dot(mx, eye),
    my.getX(), my.getY(), my.getZ(), -dot(my, eye),
    mz.getX(), mz.getY(), mz.getZ(), -dot(mz, eye),
    0.0,       0.0,       0.0,       1.0
});

Я получаю следующую ошибку(VS2017):

Error   C2664   'Math::Matrix4x4<float>::Matrix4x4(Math::Matrix4x4<float> &&) noexcept': cannot convert argument 1 from 'initializer list' to 'const Type *'

Как видно из ошибки он ожидает, что конструктор принимает initializer_list. Вопрос заключается в следующем, можно ли как-то привести тип к массиву, либо указателю, чтобы не передавать initializer_list с этим новым синтаксисом инициализации?

Answer 1

Не меняя кода - нет, нельзя.

Создать временный массив при помощи {}-инициализатора можно, если завернуть его тип в "однословное" имя

using FA = float[MATRIX_SIZE];
...
FA{
  mx.getX(), mx.getY(), mx.getZ(), -dot(mx, eye),
  my.getX(), my.getY(), my.getZ(), -dot(my, eye),
  mz.getX(), mz.getY(), mz.getZ(), -dot(mz, eye),
  0.0,       0.0,       0.0,       1.0
}

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

А вот если вы переведете свой конструктор на использование ссылки

Matrix4x4(const Type (&array)[MATRIX_SIZE]) noexcept;

то все становится возможным

using FA = float[MATRIX_SIZE];
Math::Matrix4x4f matrix(FA{
  mx.getX(), mx.getY(), mx.getZ(), -dot(mx, eye),
  my.getX(), my.getY(), my.getZ(), -dot(my, eye),
  mz.getX(), mz.getY(), mz.getZ(), -dot(mz, eye),
  0.0,       0.0,       0.0,       1.0
});

Хотя я поспешил со своим "не меняя кода - нет, нельзя". Вы можете сохранить конструктор в его нынешнем виде и использовать std::array в качестве промежуточного типа

Math::Matrix4x4f matrix(
  std::array<float, MATRIX_SIZE>{
    mx.getX(), mx.getY(), mx.getZ(), -dot(mx, eye),
    my.getX(), my.getY(), my.getZ(), -dot(my, eye),
    mz.getX(), mz.getY(), mz.getZ(), -dot(mz, eye),
    0.0,       0.0,       0.0,       1.0
  }.data()
);
READ ALSO
Socket Android Java

Socket Android Java

Пишу серверное приложениеУ меня сервер написан на java а клиент android приложение

127
Сумирование значений в postgresql

Сумирование значений в postgresql

Хочу просумировать значения в JPA таким образом:

129
Парсинг строки arduino

Парсинг строки arduino

Передаю строку из андроид приложения

138