Задать вопрос
Dyikot
@Dyikot

Reinterpret_cast вектора типа double в T неопределенное или определенное поведение?

Для примера такой код:
std::vector<double> v = { 0, 1, 2, 3, 4 };
std::vector<Time> t = reinterpret_cast<std::vector<Time>&>(v);

где Time класс содержащий только одно поле double.

Вы наверное задаетесь вопрос а зачем данное чудо. Проблема такая:
Есть классы интерполяторы. Например для линейной интерполяции. Для разных методов и размерностей у меня их получается 7. Сделаны для double все работает хорошо. Но вот возникает такая потребность сделать для едениц измерения. Т.е как в примере Time, а будет еще там например Mass и таких еще много. И вот чтобы не городить шаблонные интерполяторы под каждый тип по сути представляющий из себя double. И вот думаю как можно оптимизировать данное. И вот думаю использовать reinterpret_cast. Сначало думал pointer + size, должно быть безопасно. Но что на счет вектора? Вроде у типа тот же size и alignment. Что может пойти не так? Проверил на Debug и Release вроде ошибок нету и все точно копируется.
  • Вопрос задан
  • 58 просмотров
Подписаться 1 Простой 4 комментария
Помогут разобраться в теме Все курсы
  • Нетология
    Разработчик на C++
    12 месяцев
    Далее
  • Skillbox
    Профессия Разработчик С++
 с нуля + ИИ
    7 месяцев
    Далее
  • Яндекс Практикум
    Разработчик C++ расширенный
    12 месяцев
    Далее
Решения вопроса 1
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
Это Undefined behavior, конечно. Пока луна не в скорпионе, оно даже может работать, потому что расположение в памяти Time и double одинаковое, и вроде как даже vector для этих двух типов будут в памяти одинаковы.

Тут проблема даже не reinterpret_cast, кастовать-то можно: пункт 6, а потом пункт 5.

Обращаться к этому потом нельзя.
Тут нарушение strict aliasing. Нельзя к данным vector<Time> обращаться через указатель на vector<double>. Компилятор в праве посчитать, что вы к вектору v вообще не обращаетесь нигде и оптимизировать его нафиг из программы и памяти.

Раз расположение в памяти идентичное, вы можете выделить вектор Time нужного размера и скопировать туда данные через memcpy:
memcpy(&t[0], &v[0], sizeof(double)*v.size());

Или напишите свою функцию в виде шаблона.
template <typename T> 
std::vector<T>Interpolate(vector<T> data) {
  // ...
}


Тогда она может и double и Time принимать без проблем.

Или напишите конструкторы для Time, И можно его инициализировать через список инициализации:
struct Time {
        Time() : x(0) {}
        Time(double a) : x(a) {}
        double x;
    };

std::vector<Time> v = {1,2,3};


С такими конструкторами можно даже скопировать vector<double> в vector<Time>:
std::copy(a.begin(), a.end(), std::back_inserter(v));


Edit: ну, и наоборот, если вы хотите из вектора Time получить вектор double, вы должны определить operator double() у вашего Time. И оттуда уже можно будет копировать в дабловый вектор. И работать это будет даже если класс Time содержит еще чего-то кроме double.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы