“模型”是定义每个派生模型必须具有的数据结构和方法的基类。“Filter”是一个基类,它使用模型的数据结构和方法(都具有模型基类中定义的相同接口)。将有多个派生模型和多个派生过滤器。每个派生的过滤器应该能够作用于任何派生的模型。模型独立于过滤器。由于速度很重要,我正在尝试使用奇怪重复模板模式 (CRTP) 的静态多态性。理想情况下,Filter 使用的 Model 中的方法应该是可内联的。此类设计的起点是:
template <typename DerivedModel>
class Model {
public:
Model() {}
double f(const double x) {
return static_cast<DerivedModel*>(this)->f(x);
} // f
}; // Model
class Model1 : Model<Model1> {
// Curiously Recurring Template Pattern
public:
Model1() : Model() {}
double f(const double x) { return x; }
}; // Model1
template <typename DerivedFilter>
class Filter {
public:
double b_;
Filter(const double b) : b_(b) {}
double step() {
return static_cast<DerivedFilter*>(this)->step();
} // step
}; // Filter
现在我们需要一种机制来允许过滤器访问模型。尝试多重继承,看看它是否编译:
template <typename DerivedModel>
class Filter2A : public Filter<Filter2A>, public DerivedModel {
}; // Filter2A
这失败了(使用 gcc 4.7.1,没有特殊开关):
error: type/value mismatch at argument 1 in template parameter list for ‘template<class DerivedFilter> class Filter’
expected a type, got ‘Filter2A’
基于阅读相关的 stackoverflow 帖子,让我们改用模板模板参数。此外,我将在过滤器的新代码中放置一个模型,而不是 MI:
template<typename DerivedModel, template<class> class DerivedFilter>
class Filter {
public:
DerivedModel myModel; // Filter "has a" Model
double b_;
Filter(const double b) : b_(b) {}
double step() {
return static_cast<DerivedFilter*>(this)->step(); // ERROR
} // step
}; // Filter
template<typename DerivedModel>
class Filter1 : public Filter< DerivedModel, Filter1 > { // CRTP
public:
Filter1(const double b) : Filter< DerivedModel, Filter1 >(b) {}
double step() { return b_; } // "b_ was not declared in this scope"
}; // Filter1
这有效 - 除了 static_cast 行:
In member function ‘double Filter<DerivedModel, DerivedFilter>::step()’:
error: expected type-specifier before ‘DerivedFilter’
expected ‘>’ before ‘DerivedFilter’
...
那么模板模板参数 DerivedModel 需要不同的语法来访问 Model 的方法吗?是否有一个 typedef 可以解决这个问题(尝试了一些事情但没有成功)。
另外,我不明白第二个问题 - 即使一切都是公开的,Filter1 中的过滤器 b_ 也不再可访问。(可以通过将 b_ 替换为 Filter< DerivedModel, Filter1 >::b_ 来修复)。对于更简单的 CRTP 代码示例,这不是必需的。