В настоящее время у меня есть свой собственный векторный класс:
template<int D, typename T = float>
class Vec
{
private:
T data[D];
public:
Vec(T initial = 0)
{
for (int i = 0; i < D; ++i)
{
data[i] = initial;
}
}
// Misc. operator overloads
};
using Vec2 = Vec<2>;
using Vec3 = Vec<3>;
using Vec4 = Vec<4>;
Я хотел бы добавить несколько переменных-членов, а именно x
, y
, z
и w
, это будет указывать на первую, вторую, третью и четвертую позиции в векторе соответственно. В идеале эти переменные были бы видимы, только если вектор был объявлен с достаточным количеством измерений. Т.е. двухмерный вектор не будет иметь доступа к Vec<D, T>::z
.
То, что я нашел для работы:
template<int D2 = D, typename T2 = typename std::enable_if<(D2 > 0), T*>::type>
T2 x(){ return &data[0];}
template<int D2 = D, typename T2 = typename std::enable_if<(D2 > 1), T*>::type>
T2 y(){ return &data[1];}
template<int D2 = D, typename T2 = typename std::enable_if<(D2 > 2), T*>::type>
T2 z(){ return &data[2];}
template<int D2 = D, typename T2 = typename std::enable_if<(D2 > 3), T*>::type>
T2 w(){ return &data[3];}
Как вы можете видеть, с ++ будет немного кризис среднего возраста, если Я пытаюсь ввести параметры шаблона D
и T
как есть, поэтому я вынужден по существу переопределить каждый из них. И я знаю, что то, что я собираюсь сказать, смешно, но я бы очень хотел, чтобы x
, y
, z
и w
были переменными вместо функций, потому что, на мой взгляд, vec.x
выглядит лучше, чем vec.x()
(сумасшедший, я знаю).
Я не могу использовать это решение, потому что переменные не могут иметь шаблонов, только классы и функции. В настоящее время я играю с этим:
typename std::conditional<(D > 0), T*, std::nullptr_t>::type x = &data[0];
typename std::conditional<(D > 1), T*, std::nullptr_t>::type y = &data[1];
typename std::conditional<(D > 2), T*, std::nullptr_t>::type z = &data[2];
typename std::conditional<(D > 3), T*, std::nullptr_t>::type w = &data[3];
Я решил использовать std::nullptr_t
в качестве запасного броска, потому что я хотел использовать тип с плавающей точкой, целые числа и так далее c. К сожалению, я пришел к выводу, что это не хорошо. Мне нужны средства для предотвращения оценки x
, y
, z
и w
до их вызова, в противном случае любой экземпляр Ve c с менее чем 4 измерениями вызовет ошибку компилятора строка, по которой оценивается w
, то есть независимо от того, пытаюсь ли я вызвать w
, она оценивается во время компиляции и выдаст ошибку.
Я ищу решение, которое либо препятствует оценке переменной, если она не вызывается (решение, которое не называется функцией), либо решение, которое позволит мне сделать переменную-член полностью невидимой вне класса при определенных c обстоятельствах.
Редактировать: у меня были дополнительные go, но безуспешно:
private:
T data[D];
auto getW(){return &data[4];};
public:
typename std::conditional<(D > 3), T*, std::nullptr_t>::type w = getW();
Это все равно вызывает ошибку компиляции для любого экземпляра class Vec
с менее чем 4 измерениями , Теперь я действительно запутался. Я получаю ошибку cannot convert ‘float*’ to ‘std::conditional<false, float*, std::nullptr_t>::type’ {aka ‘std::nullptr_t}
, но это не имеет никакого смысла, никогда не следует запускать getW()
, никогда нельзя сравнивать float*
и std::nullptr_t
...?