Дано: (Код приведен к разумному минимуму)
// MemberTypes
template
<
typename SPEEDTYPE = float,
typename SIZETYPE = float,
typename ACCELERATIONTYPE = float
>
struct ParticleMemberTypes
{
typedef typename SPEEDTYPE SpeedType;
typedef typename SIZETYPE SizeType;
typedef typename ACCELERATIONTYPE AccelerationType;
};
// Свойства
template <class T>
class PSpeed
{
public:
inline const typename T::SpeedType& GetSpeed() const { return v; }
inline void SetSpeed(const typename T::SpeedType& V) { v = V; }
const static bool hasSpeed = true;
private:
typename T::SpeedType v;
};
template <class T>
class PSize
{
public:
inline const typename T::SizeType& GetSize() const { return v; }
inline void SetSize(const typename T::SizeType& V) { v = V; }
const static bool hasSize = true;
private:
typename T::SizeType v;
};
template <class T>
class PAcceleration
{
public:
inline const typename T::AccelerationType& GetAcceleration() const { return v; }
inline void SetAcceleration(const typename T::AccelerationType& V) { v = V; }
const static bool hasAcceleration = true;
private:
typename T::AccelerationType v;
};
// Пустая база и специализации
(Необходимо, чтобы каждый EmptyBase был отдельным типом, чтобы избежать наследования от одного и того же базового класса более одного раза)
template <typename P, typename T> struct EmptyBase {};
template <typename T> struct EmptyBase<PSpeed<T>, T>
{
const static bool hasSpeed = false;
};
template <typename T> struct EmptyBase<PSize<T>, T>
{
const static bool hasSize = false;
};
template <typename T> struct EmptyBase<PAcceleration<T>, T>
{
const static bool hasAcceleration = false;
};
// Базовый шаблон выбора
template <bool ENABLE, typename P, typename T> struct EnableBase;
template <typename P, typename T> struct EnableBase<true, P, T>
{
typedef P Type;
};
template <typename P, typename T> struct EnableBase<false, P, T>
{
typedef EmptyBase<P, T> Type;
};
// Класс шаблонов частиц
template
<
bool USE_SPEED = false,
bool USE_SIZE = false,
bool USE_ACCELERATION = false,
typename T = ParticleMemberTypes<>
>
struct Particle :
public EnableBase<USE_SPEED, PSpeed<T>, T>::Type,
public EnableBase<USE_SIZE, PSize<T>, T>::Type,
public EnableBase<USE_ACCELERATION, PAcceleration<T>, T>::Type
{
};
Теперь мы можем сделать:
using namespace std;
Particle<> p1;
Particle<true, true, true, ParticleMemberTypes<Vector3<double> > > p2;
cout << "p1: " << sizeof(p1) << endl;
cout << "p2: " << sizeof(p2) << endl;
Выход:
p1: 2
p1: 32
Итак, вот мои вопросы:
- Это разумный подход к автоматическому уменьшению размера класса?
- Если я наследую только от двух свойств, размер частиц равен 1, кроме того, размер увеличивается на единицу для каждого дополнительного EmptyBase, почему это так?
- Есть ли здесь какие-нибудь шаблоны, идиомы и т. Д., Которые были бы полезны?
Планируется написать шаблоны для автоматизации обработки частиц на основе имеющихся свойств.
Я, вероятно, должен упомянуть, что эта система частиц, над которой я работаю, не "в реальном времени", будет иметь дело с огромным количеством частиц, и что я буду настраивать каждый рендеринг из C ++. Кроме того, это мой первый опыт использования шаблонов.
EDIT:
В принципе, я выбрал шаблонный подход по двум причинам: одна из них - любопытство - просто узнать о шаблонах и изучить их использование. Вторая причина - скорость. Поскольку мне не нужно ничего менять во время выполнения, я подумал, что мог бы использовать шаблоны для устранения накладных расходов на виртуальные функции и неиспользуемые члены класса и т. Д.
Предполагаемое использование - это создать bazillion частиц абсолютно одинакового типа, а также обработать и визуализировать их так быстро, как только я смогу заставить код работать. :)
Идея состоит в том, чтобы иметь систему с широкими возможностями настройки, где я мог бы подключать пользовательские функторы для обработки частиц. В идеале свойства частицы должны быть включены только в том случае, если они действительно используются, но я не выяснил, возможно ли и как это возможно.