Иногда возникает необходимость иметь класс Vector3f
, который имеет элементы x
, y
и z
и может быть индексирован как массив float[3]
одновременно (здесь, в SO, уже есть несколько вопросов по этому поводу).
Что-то вроде:
struct Vector3f {
float data[3];
float &x = data[0];
float &y = data[1];
float &z = data[2];
};
С этим мы можем написать это:
Vector3f v;
v.x = 2.0f;
v.y = 3.0f;
v.z = 4.0f;
glVertex3fv(v.data);
Но эта реализация плохая, потому что ссылки занимают место в struct
(что весьма прискорбно. Я не вижу причин, по которым ссылки нельзя удалить в данном конкретном случае, возможно, это упущенная оптимизация со стороны компилятора).
Но с [[no_unique_address]]
у меня возникла такая идея:
#include <new>
template <int INDEX>
class Vector3fProperty {
public:
operator float() const {
return propertyValue();
}
float &operator=(float value) {
float &v = propertyValue();
v = value;
return v;
}
private:
float &propertyValue() {
return std::launder(reinterpret_cast<float*>(this))[INDEX];
}
float propertyValue() const {
return std::launder(reinterpret_cast<const float*>(this))[INDEX];
}
};
struct Vector3f {
[[no_unique_address]]
Vector3fProperty<0> x;
[[no_unique_address]]
Vector3fProperty<1> y;
[[no_unique_address]]
Vector3fProperty<2> z;
float data[3];
};
static_assert(sizeof(Vector3f)==12);
Итак, в основном у меня есть свойства в struct
, который обрабатывает доступ к x
, y
и z
. Эти свойства не должны занимать места, так как они пусты и имеют атрибут [[no_unique_address]]
.
Что вы думаете об этом подходе? У него есть УБ?
Обратите внимание, этот вопрос касается класса, для которого все это возможно:
Vector3f v;
v.x = 1;
float tmp = v.x;
float *c = v.<something>; // there, c points to a float[3] array
[[no_unique_address]]
означает только то, что член не должен иметь уникальный адрес, а не то, что он не должен иметь уникальный адрес. Ссылка на родительский класс из дочернего также выглядит подозрительно. - person freakish   schedule 05.09.2019float& x() const;
иvoid x(float);
. - person freakish   schedule 05.09.2019v.x()=2.0f
выглядит некрасиво.v.setX(2.0f)
не так кратко, как могло бы быть. - person geza   schedule 05.09.2019float
, а неdouble
, конкретно названныхx
,y
иz
, очень наводит на размышления о 3D-графике. Таким образом, он, вероятно, будет использоваться в контексте, где должно быть сохранено большое количествоVector3f
(для представления вершин объекта), а производительность чрезвычайно важна (потому что она должна конкурировать с другими библиотеками трехмерной графики), и, таким образом, по существу, сохранение трех указателей будет быть крайне нежелательным. - person Justin Time - Reinstate Monica   schedule 05.09.2019operator[]
концептуально, но я согласен, чтоv.x
было бы более кратким. Реализация может стать даже уродливее;), но некоторым компиляторам нравится it даже больше, чем легко один. - person Bob__   schedule 05.09.2019norm_2
не удаляется, так как это не шаблон. - person geza   schedule 05.09.2019glVertex3fv
, но это это древний API. В настоящее время данные вершин хранятся в объектах буфера вершин (VBO), где структура данных может быть намного сложнее, чем у простого массива ... - person Marco13   schedule 06.09.2019