C++ 有人能帮我用Boost::MPL创建一个变量容器吗?
我创建了一个物理系统,可以处理任何碰撞对象到任何碰撞对象,如下所示:C++ 有人能帮我用Boost::MPL创建一个变量容器吗?,c++,templates,metaprogramming,boost-mpl,C++,Templates,Metaprogramming,Boost Mpl,我创建了一个物理系统,可以处理任何碰撞对象到任何碰撞对象,如下所示: namespace Collision { template <typename T, typename U> inline void Check(T& t, U& u) { if(u.CheckCollision(t.GetCollider())) { u.HitBy(t); t.Hit(u);
namespace Collision
{
template <typename T, typename U>
inline void Check(T& t, U& u)
{
if(u.CheckCollision(t.GetCollider()))
{
u.HitBy(t);
t.Hit(u);
}
}
}
命名空间冲突
{
模板
在线无效检查(T&T、U&U)
{
如果(u.CheckCollision(t.GetCollister()))
{
u、 希比(t);
t、 Hit(u);
}
}
}
还有其他几个辅助对象可以使其易于使用,但要点是需要针对静态对象和其他动态对象对动态对象进行测试,但不需要检查静态对象
我想要的是这样的:
void func()
{
PhysicsWorld world;
shared_ptr<CSphere> ballPhysics(new CSphere(0,0,ballSprite->Width()));
BallCommand ballBehavior;
CBounds bounds(0, 0, 640, 480);
CBox obstacle(200, 150, 10, 10);
Collision::Collidable<CBounds> boundC(bounds);
Collision::Collidable<std::shared_ptr<CSphere>, BallCommand&> ballC(ballPhysics, ballBehavior);
Collision::Collidable<CBox> obstC(obstacle);
world.addStatic(boundC);
world.addDynamic(ballC);
world.addStatic(obstC);
...
...
world.Update();
...
...
}
void func()
{
物理世界;
共享的球物理(新CSphere(0,0,ballSprite->Width());
球指挥球行为;
c边界(0,060480);
CBox障碍物(200、150、10、10);
碰撞::可碰撞边界c(边界);
碰撞:可碰撞的球(球物理,球行为);
碰撞:可碰撞obstC(障碍物);
addStatic(boundC);
world.addDynamic(ballC);
addStatic(obstC);
...
...
world.Update();
...
...
}
我想通过add函数推断容器,这样使用系统会自动更新类型列表。我想我知道如何使用模板函数生成类型列表,但不知道如何在需要的地方获得它,或者在编译的什么时候完成
如果不是这样,那么一些系统会使用两个类型列表,然后在内部编写更新函数来迭代所有列表,并将它们配对
我读过一些boost MPL的书,也读过Andrei的书好几次。但是,我似乎被它的工作原理所困扰,并没有真正将其转化为我如何使用它。我希望他们在MPL书中有更多关于现实世界例子的章节
我已经能够让游戏引擎的所有部分以通用方式与渲染、物理、碰撞(我将检测与反应分离)、输入、网络、声音等进行交互。现在我只需要用一种通用的方式来掌握所有的东西。在完成了所有的泛型工作之后,仅仅为了在容器中保存某些内容而要求继承是愚蠢的,我不想手工编写所有可能的集合代码,因为这是泛型编程的最大好处之一
我看到Jalf表示,他/她使用MPL做了类似的事情,但没有深入到足够的细节,让我弄清楚。如果有人知道一个实际使用的例子,或者我在哪里可以得到更多关于使用MPL的信息,我将不胜感激
再次感谢
更新
boost MPL和boost Fusion似乎都能满足我的要求,但这两个库在现实生活中的良好示例似乎很少。MPL的文档只不过是这个模板做了这件事,希望您能理解其中的含义。“这是一个例子,但它只是冰山一角!”Fusion的效果要好一点
典型的boost MPL示例是has_xxx。他们在示例中使用了XXX和XXX,因此很难看出XXX(所需文本)和Test或CheckType或任何更易区分的用户类型在哪里可以代替XXX。另外,没有提到这一切都不在名称空间中。现在我知道为什么斯科特·梅耶斯把这和《心理战》中的淋浴场景相比较了
真的很遗憾,因为我所得到的很少的编译和理解确实有用,但很难弄清楚,如果我是在一个运输产品上,我永远不会花这么多的精力
如果有人知道真实世界的例子或更好的参考资料、解释或教程,我将不胜感激
更新
以下是更多代码:
template <typename T, typename V = VictimEffect, typename M = MenaceEffect>
class Collidable
{
T m_Collider;
V m_HitBy;
M m_Hit;
public:
Collidable(T collide, V victim, M menace) : m_Collider(collide), m_HitBy(victim), m_Hit(menace) {;}
Collidable(T collide) : m_Collider(collide) {;}
Collidable(T collide, V victim) : m_Collider(collide), m_HitBy(victim) {;}
T& GetCollider()
{
return m_Collider;
}
template <typename V>
void HitBy(V& menace)
{
m_HitBy.HitBy(menace.GetCollider());
}
template <typename V>
void Hit(V& victim)
{
m_Hit.Hit(victim.GetCollider());
}
template <typename V>
bool CheckCollision(V& menace)
{
return m_Collider.CheckCollision(menace);
}
};
模板
类可碰撞
{
T m_对撞机;
V m_HitBy;
M_Hit;
公众:
可碰撞(T碰撞,V受害者,M威胁):M_碰撞机(碰撞),M_HitBy(受害者),M_命中(威胁){;}
可碰撞(T碰撞):m_碰撞器(碰撞){;}
可碰撞(T碰撞,V受害者):m_碰撞机(碰撞),m_HitBy(受害者){;}
T&GetCollider()
{
返回m_对撞机;
}
模板
无效命中(V和威胁)
{
m_HitBy.HitBy(威胁.GetCollider());
}
模板
无效命中(V和受害者)
{
m_Hit.Hit(受害者.GetCollider());
}
模板
布尔检查碰撞(V和威胁)
{
返回m_碰撞器。检查碰撞(威胁);
}
};
然后我用它来做这个
Collidable<Boundary, BallCommand> boundC(boundary, ballBehavior);
Collidable<CollisionBox> ballC(circle);
可碰撞边界c(边界、行为);
可对撞球c(圆);
然后,我只需要调用collide with我的所有主动可碰撞对象与我的所有主动和被动对象进行碰撞
我没有使用std::function,因为添加函数名使代码更清晰。但也许这只是传统思维。如果我理解正确,您的问题是:
class manager {
public:
template<typename T>
void add(T t);
private:
/* ??? */ data;
/* other members? */
};
manager m;
some_type1 s1;
some_type2 s2;
m.add(s1);
m.add(s2);
/* m should hold its copies of s1 and s2 */
这确实是MPL+Fusion可以帮助解决的问题。然而,这在编译时世界中仍然非常固定:您能想象编写模板void insert(Iter first,Iter last)
只是为了将容器的内容复制到管理器中吗
请允许我假设您的需求是这样的,事实上,管理器
必须以一种更加流畅的方式使用,就像我最初对您的问题的表述一样。(对于物理世界
,我不认为这是一个很大的想象空间)。还有一种选择,我认为更合适,更不冗长,更易于维护:类型擦除。(这项技术的名称可能有点不幸,在第一次使用时可能会产生误导。)
类型擦除的一个很好的例子是std::function:
std::function<void()> func;
func = &some_func; /* this just looks like that internally std::function stores a void(*)() */
func = some_type(); /* but here we're storing a some_type! */
std::function func;
func=&some_func;/*这看起来就像内部std::函数存储了一个void(*)()*/
func=some_type();/*但这里我们存储的是某种类型的*/
类型擦除是一种技术
std::function<void()> func;
func = &some_func; /* this just looks like that internally std::function stores a void(*)() */
func = some_type(); /* but here we're storing a some_type! */
#include <boost\mpl\vector.hpp>
#include <boost\mpl\fold.hpp>
#include <boost\mpl\for_each.hpp>
#include <boost\mpl\inherit.hpp>
#include <boost\mpl\inherit_linearly.hpp>
#include <iostream>
#include <vector>
using namespace boost::mpl::placeholders;
typedef boost::mpl::vector<short, long, char, int> member_types;
template <typename T>
struct wrap
{
std::vector<T> value;
};
typedef boost::mpl::inherit_linearly<member_types, boost::mpl::inherit<wrap<_2>, _1> >::type Generate;
class print
{
Generate generated;
public:
template <typename T>
void operator()(T)
{
std::cout << *static_cast<wrap<T>&>(generated).value.begin() << std::endl;
}
template <typename T>
void Add(T const& t)
{
static_cast<wrap<T>&>(generated).value.push_back(t);
}
};
void main()
{
print p;
short s = 5;
p.Add(s);
long l = 555;
p.Add(l);
char c = 'c';
p.Add(c);
int i = 55;
p.Add(i);
boost::mpl::for_each<member_types>(p);
}
template <typename TL>
class print
{
template <typename T>
struct wrap
{
std::vector<T> value;
};
typedef typename boost::mpl::inherit_linearly<TL, boost::mpl::inherit<wrap<_2>, _1> >::type Generate;
Generate generated;
public:
void Print()
{
boost::mpl::for_each<TL>(*this);
}
template <typename T>
void operator()(T)
{
std::cout << *static_cast<wrap<T>&>(generated).value.begin() << std::endl;
}
template <typename T>
void Add(T const& t)
{
static_cast<wrap<T>&>(generated).value.push_back(t);
}
};