有人可以帮助我使用Boost :: MPL创建一个变量容器吗?

Tav*_*son 6 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

还有其他一些辅助对象使它易于使用,但要点是有动态对象需要针对静态对象和其他动态对象进行测试,但不需要检查静态对象.

我想要的是这样的:

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();
    ...
    ...
}
Run Code Online (Sandbox Code Playgroud)

我喜欢通过添加功能来推断容器,因此使用系统会自动更新类型列表.我想我得到了如何生成一个带有模板函数的类型列表,但不知道如何在需要它的地方获取它,或者在编译中它在什么时候完成.

如果不是那么那么一些系统使用两个类型列表然后在内部写入更新函数以遍历所有列表将它们彼此配对.

我已经阅读了一些推文MPL书,并多次阅读安德烈的书.但是,我似乎陷入了它的工作原理,并没有真正将其转化为我如何使用它.我希望他们在MPL书中再有一节关于真实世界的例子.

我已经能够将游戏引擎的所有部分与渲染,物理,碰撞(我将检测与反应分开),输入,网络,声音等进行交互.所有这些都是通用的方式.现在我只需要以通用方式保存所有内容.在完成所有这些通用工作之后,要求继承只是因为我可以在容器中保存一些东西并且我不想手动编写每个集合的可能性,因为这是泛型编程的一大优点,这将是愚蠢的.

我看到Jalf表示他/她使用MPL做类似的事情,但没有详细说明我能弄明白.如果有人知道实际使用示例或我可以获得有关使用MPL的更多信息,我将不胜感激.

再次感谢!

更新

提升MPL和提升Fusion似乎都做了我想做的事情,但是对于任何一个库的良好现实生活示例的方式似乎都很少.MPL的文档只是这个模板做到这一点,并且好运了解它的含义.融合更好一点"这是一个例子,但它只是冰山一角!"

典型的boost MPL示例是has_xxx.他们在示例中使用XXX和xxx,这使得很难看到XXX(所需文本)和Test或CheckType或更可区分的用户类型可用于代替xxx的区别.另外,没有提到这些都不在命名空间中.现在我知道为什么Scott meyers将它与Psycho中的淋浴场景进行了比较.

这真是一种耻辱,因为我编写和理解的东西确实很有用,但很难弄清楚,如果我在运输产品上,我将永远不会花费太多精力.

如果有人知道现实世界的例子或更好的参考,解释或教程,我将不胜感激.

更新

这里有更多代码:

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);
    }
};
Run Code Online (Sandbox Code Playgroud)

然后使用它我这样做

    Collidable<Boundary, BallCommand> boundC(boundary, ballBehavior);
    Collidable<CollisionBox> ballC(circle);
Run Code Online (Sandbox Code Playgroud)

然后我需要的是调用所有活动的可碰撞对象与我的所有主动和被动对象碰撞.

我没有使用std :: function,因为添加函数名使代码更清晰.但也许这只是传统思维.

Tav*_*son 1

这并不完整,我也没有得到我想要的一切,但现在已经足够好了。我正在输入整个解决方案,以防它对其他人有帮助。

#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);
}
Run Code Online (Sandbox Code Playgroud)

这不是我需要的最终对象,但现在我已经拥有了制作我想要的东西的所有部件。

更新

最后我明白了。

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);
    }
};
Run Code Online (Sandbox Code Playgroud)

这里 TL 是一个 boost::mpl 容器,其中包含应保存的类型。

我认为这为扩展提供了一个很好的起点,但涵盖了大部分元编程部分。

我希望这对其他人有帮助。