【发布时间】:2017-06-30 15:17:35
【问题描述】:
我想使用 CRTP 惯用语来使用静态多态性,同时能够在运行时选择要使用的实现。我举个例子:
我有一些类负责计算东西:
template<typename Implementation>
class FooInterface {
public:
void compute(){
(static_cast<Implementation*>(this))->compute();
}
};
class FooForward : public FooInterface<FooForward> {
public:
void compute(){
//do stuff
}
};
class FooBackward : public FooInterface<FooBackward> {
public:
void compute(){
//do other stuff
}
};
和
template<typename Implementation>
class BarInterface {
public:
void eval(){
(static_cast<Implementation*>(this))->eval();
}
};
class BarForward : public BarInterface<BarForward> {
public:
void eval(){
//do something
}
};
class BarBackward : public BarInterface<BarBackward> {
public:
void eval(){
//do something else
}
};
现在我想将这些对象用作另一个类的成员,我们称之为Model,并在循环中使用它们:
template<typename Foo, typename Bar>
class Model {
private:
Foo* foo_;
Bar* bar_;
int max_iter_;
public:
Model<Foo, Bar>(int max_iter) : max_iter_(max_iter){
foo_ = new Foo();
bar_ = new Bar();
}
void solve(){
for(int i = 0; i < max_iter_; ++i){
foo_->compute();
bar_->eval();
}
}
};
请注意,函数 Model::solve() 在我的应用程序中执行大量迭代,性能至关重要,因此使用 CRTP 而不是动态多态性来避免虚函数调用并启用编译器的函数内联。
现在,当我想让用户决定在运行时使用 FooInterface 和 BarInterface 的哪个实现时,我的问题就出现了。在我的main.cpp 我有:
int main(int argc, char** argv){
/*
* Here an input file is read into a map which looks like this
* std::map<std::string, std::string> settings
*/
// Here I need a way to choose, based on settings, what will Foo and Bar be
Model<Foo, Bar> model;
model.solve();
}
我曾想过一种可以返回正确 Model 的工厂,但我不知道返回类型可能是什么,而且我想象的方式并不方便,因为在我的应用程序中我有超过 2 个模板参数然后组合的数量变得非常大
class Factory{
/*type?*/ createModel(std::map<std::string, std::string> settings){
if ((settings["foo"] == "fwd") && (settings["bar"] == "fwd")){
Model<FooForward, BarForward>* model = new Model<FooForward, BarForward>();
return model;
}
else if ((settings["foo"] == "fwd") && (settings["bar"] == "bwd")){
Model<FooForward, BarBackward>* model = new Model<FooForward, BarBackward>();
return model;
}
else if ((settings["foo"] == "bwd") && (settings["bar"] == "fwd")){
Model<FooBackward, BarForward>* model = new Model<FooBackward, BarForward>();
return model;
}
else {
Model<FooBackward, BarBackward>* model = new Model<FooBackward, BarBackward>();
return model;
}
}
};
按照我的想象,所有模板组合都将被编译,用户可以在运行时选择使用哪一个。有没有办法使用 CRTP 来实现这一点?
【问题讨论】: