Я хочу написать математический шаблон вектор. У меня есть класс, который принимает тип и размер в качестве аргумента шаблона, с большим количеством методов математической операции.
Теперь я хочу написать специализации, где Vector<Например, 3> имеет элементы x, y, z в качестве членов, которые ссылаются на данные [0..3] соответственно.
Проблема в том, что я не знаю, как создать специализацию, которая наследует все от шаблона по умолчанию, не создавая ни базового класса, ни написав все дважды.
Какой самый эффективный способ сделать это?
template<class Type, size_t Size>
class Vector {
// stuff
};
template<class T>
class Vector<3,T>: public Vector {
public:
T &x, &y, &z;
Vector(): Vector<>(), x(data[0]), y(data[1]), z(data[2]){}
// and so on
};
Каким-то образом вы сможете извлечь из реализации по умолчанию, но вы специализируете экземпляр, и как? это должна быть неспециализированная версия, которую вы можете извлечь из нее. Так что все просто:
// Add one extra argument to keep non-specialized version!
template<class Type, size_t Size, bool Temp = true>
class Vector {
// stuff
};
// And now our specialized version derive from non-specialized version!
template<class T>
class Vector<T, 3, true>: public Vector<T, 3, false> {
public:
T &x, &y, &z;
Vector(): Vector<>(), x(data[0]), y(data[1]), z(data[2]){}
// and so on
};
Попробуйте сделать это немного по-другому, но цели будут достигнуты. Добавьте внешний интерфейс — я имею в виду автономные функции X (), Y (), Z ():
template<class T, size_t S>
T& x(Vector<T, S>& obj, typename std::enable_if<(S>=1)>::type* = nullptr)
{
return obj.data[0];
}
template<class T, size_t S>
T& y(Vector<T, S>& obj, typename std::enable_if<(S>=2)>::type* = nullptr)
{
return obj.data[1];
}
template<class T, size_t S>
T& z(Vector<T, S>& obj, typename std::enable_if<(S>=3)>::type* = nullptr)
{
return obj.data[2];
}
Там нет большой разницы между:
Vector<T, 3>& obj
return obj.x();
А также
Vector<T, 3>& obj
return x(obj);
В качестве бонуса — этот интерфейс работает для соответствующих размеров.