C++11 转换可变参数模板以推导类类型

标签 c++11 variadic-templates

我想从类属性列表生成类。对于每个属性,其实现都是通过模板推导出来的。

为了这个问题,我将通过尝试创建一个类来处理具有两个属性的虚拟实体来说明我的问题:治疗者和商人

#include <iostream>

// Base class for entities
class entity
{
    public:
    virtual void do_walk() { std::cout << "I like walking" << std::endl; };
};

// A class property for healer characters
class healer
{
    public:
    // interface
    virtual void do_heal() = 0;
};

// A class property for healer npcs
class merchant
{
    public:
    // interface
    virtual void do_sell() = 0;
};

// implementation of the healer property
class healer_implementation : public healer
{
    public:
    virtual void do_heal() { std::cout << "I heal people" << std::endl; }
};



// implementation of the healer property
class merchant_implementation : public merchant
{
    public:
    virtual void do_sell() { std::cout << "I sell things" << std::endl; }
};

// To deduce the implementation of a property, we'll use the template property which will be specialized for each property and reference an implementation
template<typename T>
class property
{};

template<>
class property<merchant>
{
public: typedef merchant_implementation implementation;
};

template<>
class property<healer>
{
public: typedef healer_implementation implementation;
};


// This class is a class helper to deduce the right class type from a list of property for an entity
template<typename PROPERTY0, typename PROPERTY1=void>
class factory
{
public:
    typedef typename property<PROPERTY0>::implementation base0;
    typedef typename property<PROPERTY1>::implementation base1;


    class custom : public base0, public base1, public entity {};

};

int main()
{
    entity* bob = new factory<healer, merchant>::custom();

    // bob will try to sell things
    merchant* m = dynamic_cast<merchant*>(bob);
    if (m)
        m->do_sell();

    // bob will try to heal people
    healer* h = dynamic_cast<healer*>(bob);
    if (h)
        h->do_heal();

    // and as an entity, bob can walk
    bob->do_walk();

return 1;
}

如果我执行这段代码,我会得到预期的结果:

I sell things
I heal people
I like walking

现在,如果我想创建一个只有一个属性的实体,我必须为工厂添加专门化:

template<typename PROPERTY0>
class factory<PROPERTY0, void>
{
public:
    typedef typename property<PROPERTY0>::implementation base0;

    class custom : public base0, public entity {};

};

我可以这样测试:

entity* joe = new factory<merchant>::custom();
h = dynamic_cast<healer*>(joe);
if (!h)
   std::cout << "Joe is not an healer." << std::endl;


m = dynamic_cast<merchant*>(joe);
if (m)
    m->do_sell();

然后我得到:

Joe is not an healer
I sell things

我的问题是:有没有办法用可变参数模板对类工厂进行编码来处理任意数量的属性,或者如果我需要一个具有最多 N 个属性的实体,我必须创建 N 个工厂特化?

最佳答案

如果你可以在没有 typedef base0base1 等的情况下生活,你确实可以可变地执行此操作:

template <class... Property>
class factory
{
public:
    typedef typename property<PROPERTY0>::implementation base0;
    typedef typename property<PROPERTY1>::implementation base1;


    class custom : public property<Property>::implementation..., public entity {};

};

[Live example]

关于C++11 转换可变参数模板以推导类类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28090964/

相关文章:

c++ - 在 C++ 中获取 Windows 文本?

c++ - 如何在第一个调用的构造函数中更正创建和传递对象

c++ - 将一个右值的元组转换为一个左值的元组

c++ - g++ std::is_function 实现:_ArgTypes 后跟 6 个句点是什么意思?

c++ - GCC constexpr 允许添加,但不允许使用地址进行按位或

c++ - 标准 C++ 线程 ID - 奇怪的行为

c++ - 函数参数评估的完美转发和顺序

c++ - 如何将 std::enable_if 与可变参数模板一起使用

c++ - 遍历参数包

c++ - 为什么只有有效的空可变参数包的模板格式错误?