模板元编程,以避免演员表

时间:2018-01-18 17:02:12

标签: c++ templates metaprogramming

请考虑以下代码:

#include <utility>
#include <tuple>
#include <map>
using namespace std;
enum class Type { D1, D2 };

struct Base { 
 virtual ~Base() = default;
 virtual void doSth() = 0;
 virtual Type getType() = 0; 
};

struct D1 : Base { 
 Type getType() override { return Type::D1; } 
 void doSth() override { }
};

struct BaseExt : Base {
    virtual void doSth2() = 0;
};

struct D2 : BaseExt { 
 Type getType() override { return Type::D2; }
 void doSth() override { }
 void doSth2() override {}  
};

template <typename... Deriveds>
struct Manager
{
    Manager(Deriveds... ds) {
        _t = tuple<Deriveds...>(ds...); 
       // MAGIC NEEDED HERE TO POPULATE _mapOfTypes
    } 

    void go(Type /* t */) {
        // MAGIC NEEDED HERE
        //std::get<_mapOfTypes[t]>(_t)->doSth();
    }

    void go2()
    {
       // std::get<_mapOfTypes[Type::D2]>(_t)->doSthD2(); // THIS IS WHAT I WANT TO ACHIEVE
    }

    tuple<Deriveds...> _t;
    map<Type, int> _mapOfTypes;
};

int main()
{
   D1 d1;
   D2 d2;
   Manager<D1,D2> m(d1,d2);
   m.go(Type::D1);
   m.go2();
}

此代码的链接: 的 https://wandbox.org/permlink/Jr5HJWimrL1wvZbs

我知道我可以在Manager中存储指向Base的指针,这很简单,oldschool。但是当我需要从BaseExt调用方法时(在go2方法中),我必须从Base *到BaseExt *进行static_cast。

我在想是否有可能以模板元编程的方式做到这一点。我想在没有任何强制转换的情况下调用方法doSth2。因为我有一个实现Base或Base2的具体类型的元组,并且我在编译时知道哪个对象在元组中的哪个位置,所以我想在不使用Base或Base2接口的情况下调用此对象。

我试过实现这个但是我卡住了。我知道我可以在一个元组中存储parameter_pack,然后使用index_sequence对这个元组进行操作。但是我填充_mapOfTypes时遇到问题。是否有可能做到这一点?

0 个答案:

没有答案