鉴于:(代码减少到合理的最低值)
// 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
所以这是我的问题:
计划是编写模板,根据存在的属性自动处理粒子。
我应该提一下,我正在研究的这个粒子系统不是“实时”,将处理大量的粒子,我将从C ++配置每个渲染。此外,这几乎是我第一次使用模板。
编辑: 我选择模板方法基本上有两个原因:一个是好奇心 - 只是为了了解模板并探索它们的用法。第二个原因是速度。因为我不需要在运行时更改任何内容,我想我可以使用模板来消除虚函数和未使用的类成员的开销等。
预期的用途是创建一个巨大的粒子,所有粒子都完全相同,然后处理和渲染它们,尽可能快地使代码运行。 :)
我们的想法是拥有一个高度可配置的系统,我可以插入自定义仿函数来处理粒子。理想情况下,粒子的属性只有在实际使用时才会启用,但我还没有弄清楚是否以及如何做到这一点。
答案 0 :(得分:3)
其次,你正在使用“const static bool hasSpeed = true;”很多;在我的编程中,我通常更喜欢类型为Boost::type_traits的类型特征。您可以使用它们来选择在编译时运行的函数。你可以避免做那个“EmptyBase”。
template <typename T>
struct has_size;
template <bool speed, bool accel, typename T>
struct has_size< Particle<true, speed, accel, T> > : public true_type
{ };
template <bool speed, bool accel, typename T>
struct has_size< Particle<false, speed, accel, T> > : public false_type
{ };
// given a particle typedef SomeParticle_t
has_size<SomeParticle_T>::value
第三,你在这里做的很多事情取决于你想要的最终用途;你想要粒子是分开的,那些不能相互转换的类型?如果你走这条路线,几乎每个函数都是一个模板,你可以使用boost :: enable_if来禁用不适用于给定粒子的代码。它可能会非常快(因为很多工作都发生在编译时),但是你会有一个巨大的,难以阅读的错误语句(对于模板新手来说不太容易访问)。
另一个非模板路由是继承;你将定义一组粒子需要的虚函数,然后将它们分解为你继承的类。从你的代码中可以清楚地看出你对粒子的期望是什么。错误会更容易理解,但代码可能更慢(更多的工作转移到运行时,并会使您的对象更大)
这是一个代码示例来说明差异:
// Using templates
template <typename particle>
typename boost::enable_if< has_accel<particle>, typename particle::speed_type >::type
calculate_future_speed(const particle& t)
{ /* do your acceleration calculation */ }
template <typename particle>
typename boost::enable_if< boost::and_< has_speed<particle>,
boost::not_< has_accel<particle> >,
typename particle::speed_type >::type
calculate_future_speed(const particle& t)
{ /* no acceleration, so no calculation! just return the speed*/ }
template <typename particle>
typename boost::enable_if< boost::not_< has_speed<particle>,
typename particle::speed_type >::type
calculate_future_speed(const particle& t)
{ return 0; /* Has no speed, and no acceleration */ }
答案 1 :(得分:2)
您知道不同参数的模板类型不同吗?也就是说,在您的代码中,p1和p2属于不同的类型,因此不能存储在同一个集合中,彼此分配等等。当然,您的应用程序可能不需要这样的等价。
答案 2 :(得分:1)
有一件事,你在模板定义中使用USE_SIZE两次。
您可能还会考虑使用flyweight模式,具体取决于数据的重复性。 http://www.boost.org/doc/libs/1_39_0/libs/flyweight/doc/tutorial/index.html