有模板的可重用方法。這是一個普通的工廠派生類型帶有一個install
和create
方法,它可以讓你寫這樣的代碼:
int main() {
TypeVector<Base> t;
t.install<Foo>("Foo");
t.install<Bar>("Bar");
t.create("Foo")->hello();
}
注意這是一個草圖的實現。在現實世界中,您可以提供另一個模板參數來指定潛在的容器類型(對於少數類型,vector
可能比set
更有效)。
類型矢量是這樣的:
模板 類創建者;
template <typename Base>
class TypeVector {
public:
template <typename Derived>
void install (std::string const &name) ;
std::shared_ptr<Base> create (std::string const &name) const;
private:
struct Meta {
Meta(std::shared_ptr<Creator<Base>> creator, std::string const &name)
: creator(creator), name(name) {}
std::shared_ptr<Creator<Base>> creator;
std::string name;
};
std::vector<Meta> creators_;
};
我們莫名其妙地需要一種方法來店類型中的分配方式。我們不喜歡它boost::shared_ptr
,它結合了一個抽象基類和模板派生類:
template <typename Base>
class Creator {
public:
virtual ~Creator() {}
virtual std::shared_ptr<Base> create() const = 0;
};
template <typename Base, typename Derived>
class ConcreteCreator : public Creator<Base> {
public:
virtual std::shared_ptr<Base> create() const {
return std::shared_ptr<Base>{new Derived()};
}
};
的「具體的創造者」是能夠分配一個實際的對象,並返回一個指針到基地了。
最後,這裏是TypeVector::install
和TypeVector::create
的實現:
template <typename Base>
template <typename Derived>
void
TypeVector<Base>::install (std::string const &name)
{
creators_.emplace_back(
std::shared_ptr<Creator<Base>>(new ConcreteCreator<Base, Derived>()),
name);
}
template <typename Base>
std::shared_ptr<Base>
TypeVector<Base>::create (std::string const &name) const
{
for (auto m : creators_) {
if (name == m.name) return m.creator->create();
}
throw std::runtime_error("...");
}
最後,這是一個測試:
#include <iostream>
struct Base {
virtual ~Base() {}
virtual void hello() const = 0;
};
struct Foo : Base {
virtual void hello() const { std::cout << "I am a Foo\n"; }
};
struct Bar : Base {
virtual void hello() const { std::cout << "I am a Bar\n"; }
};
int main() {
TypeVector<Base> t;
t.install<Foo>("Foo");
t.install<Bar>("Bar");
t.create("Foo")->hello();
}
你可以更進一步,做任何構造函數調用像代碼.. 。
...
Bar(Color, Age, int)
...
t.create("Foo", Color::Red, Age::TooOld, 42)
......但這需要一個aw esome掌握可變參數模板參數列表,以及如何將它們摺疊成構造函數調用(可以完成並已完成,但會爆炸此答案)。
你需要'typesVec'來動態填充嗎?也就是說,你想在運行時包含或排除某些類型嗎? –
你接受答案的速度非常快...... –