У меня есть обертка массива, которую я использую в качестве класса матрицы / вектора, и структура из двух чисел с плавающей точкой для представления точек.
Я не хочу снова определять все арифметические операторы для точек, когда они уже доступны для векторов, поэтому я хочу добавить неявные преобразования между ними. Я использую reinterpret_cast
, как показано во фрагменте ниже.
template <class T, size_t N>
struct Array {
T data[N];
constexpr T &operator[](size_t index) { return data[index]; }
constexpr const T &operator[](size_t index) const { return data[index]; }
};
template <class T, size_t R, size_t C>
using TMatrix = Array<Array<T, C>, R>;
template <class T, size_t R>
using TColVector = TMatrix<T, R, 1>;
struct Point {
float x;
float y;
constexpr Point(float x, float y) : x{x}, y{y} {}
constexpr Point(const TColVector<float, 2> &vec) : x{vec[0]}, y{vec[1]} {}
TColVector<float, 2> &vec() {
static_assert(sizeof(*this) == sizeof(TColVector<float, 2>));
return *reinterpret_cast<TColVector<float, 2> *>(this);
}
operator TColVector<float, 2> &() { return vec(); }
};
При использовании неявного преобразования из Point
в TColVector<float, 2>
я получаю неверные результаты. Даже более странно: результаты верны, пока я печатаю промежуточные результаты, но неверны, когда я закомментирую операторы печати. И, кажется, это всегда правильно на gcc 7.3.0 для x86, а иногда и на gcc 8.3.0 для ARMv7.
Это функция, которая дала правильный результат с инструкциями печати и неправильный результат, когда я закомментировал операторы печати:
static float distanceSquared(Point a, Point b) {
using namespace std;
// cout << "a = " << a << ", b = " << b << endl;
auto diff = a.vec() - b.vec(); // Array<T, N> operator-(const Array<T, N> &lhs, const Array<T, N> &rhs)
// cout << "diff = " << Point(diff) << endl;
auto result = normsq(diff); // auto normsq(const TColVector<T, C> &colvector) -> decltype(colvector[0] * colvector[0])
// cout << "normsq(diff) = " << result << endl;
return result;
}
Я что-то здесь не так делаю?
Решение, по-видимому, таково (даже если оно не работает как lvalue):
TColVector<float, 2> vec() const { return {x, y}; }
Я пытался изолировать проблему от остальной части моего проекта, но я не смог воспроизвести ее изолированно, поэтому я хотел бы знать, нужно ли мне продолжать поиск других проблем, даже если кажется, что хорошо пока.
Вот весь код на GitHub (похоже, проблема не показана отдельно): https://github.com/tttapa/random/blob/master/SO-reinterpret_cast.cpp