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);
    }
};