C++11 转换可变参数模板以推导 class 类型
C++11 Translating a variadic template to deduce a class type
我想从 class 属性列表中生成 classes。对于每一个属性,实现都是通过一个模板推导出来的。
为了这个问题,我将通过尝试创建一个 class 来处理具有两个属性的虚拟实体来说明我的问题:治疗师和商人
#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
我的问题是:有没有一种方法可以使用可变参数模板对 class 工厂进行编码以处理任意数量的属性,或者如果我需要一个最多具有N 个属性 ?
如果你可以不用 typedefs base0
、base1
等,你确实可以做到这一点:
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 {};
};
我想从 class 属性列表中生成 classes。对于每一个属性,实现都是通过一个模板推导出来的。
为了这个问题,我将通过尝试创建一个 class 来处理具有两个属性的虚拟实体来说明我的问题:治疗师和商人
#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
我的问题是:有没有一种方法可以使用可变参数模板对 class 工厂进行编码以处理任意数量的属性,或者如果我需要一个最多具有N 个属性 ?
如果你可以不用 typedefs base0
、base1
等,你确实可以做到这一点:
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 {};
};