C++ 从一个CRTP子类访问另一个CRTP子类的数据/方法
“模型”是一个基类,定义了每个派生模型必须具有的数据结构和方法。“过滤器”是一个基类,它使用模型的数据结构和方法(都具有在模型基类中定义的相同接口)。将有多个衍生模型和多个衍生过滤器。每个派生过滤器应该能够作用于任何派生模型。模型独立于滤波器。由于速度很重要,我尝试使用奇怪的循环模板模式(CRTP)进行静态多态性。理想情况下,过滤器使用的模型中的方法应该是可内联的。本课程设计的起点是:C++ 从一个CRTP子类访问另一个CRTP子类的数据/方法,c++,class,templates,crtp,C++,Class,Templates,Crtp,“模型”是一个基类,定义了每个派生模型必须具有的数据结构和方法。“过滤器”是一个基类,它使用模型的数据结构和方法(都具有在模型基类中定义的相同接口)。将有多个衍生模型和多个衍生过滤器。每个派生过滤器应该能够作用于任何派生模型。模型独立于滤波器。由于速度很重要,我尝试使用奇怪的循环模板模式(CRTP)进行静态多态性。理想情况下,过滤器使用的模型中的方法应该是可内联的。本课程设计的起点是: template <typename DerivedModel> class Model { p
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
模板
类模型{
公众:
模型(){}
双f(常数双x){
返回静态_cast(this)->f(x);
}//f
}; // 模型
类别Model1:模型{
//奇怪的重复模板模式
公众:
Model1():Model(){}
双f(常数双x){返回x;}
}; // 模型1
模板
类过滤器{
公众:
双b_;
过滤器(常数双b):b_b(b){
双步骤(){
返回static_cast(this)->step();
}//步骤
}; // 滤器
现在我们需要一种机制来允许过滤器访问模型。尝试多重继承以查看它是否编译:
template <typename DerivedModel>
class Filter2A : public Filter<Filter2A>, public DerivedModel {
}; // Filter2A
模板
类别过滤器2a:公共过滤器,公共衍生模型{
}; // 过滤器2a
此操作失败(使用gcc 4.7.1,无特殊开关):
错误:“模板类筛选器”的模板参数列表中参数1的类型/值不匹配
应为类型,获得“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
模板
类过滤器{
公众:
DerivedModel myModel;//过滤器“具有”模型
双b_;
过滤器(常数双b):b_b(b){
双步骤(){
返回静态_cast(this)->step();//错误
}//步骤
}; // 滤器
模板
类过滤器1:公共过滤器{//CRTP
公众:
过滤器1(常数双b):过滤器(b){}
double step(){return b_;}/“未在此范围内声明b_2;”
}; // 过滤器1
这项工作-除静态_铸造线外:
In member function ‘double Filter<DerivedModel, DerivedFilter>::step()’:
error: expected type-specifier before ‘DerivedFilter’
expected ‘>’ before ‘DerivedFilter’
...
成员函数“双过滤器::步骤()”中的:
错误:“DerivedFilter”之前需要类型说明符
“DerivedFilter”之前应为“>”
...
所以模板参数DerivedModel需要不同的语法来访问模型的方法?是否有一个typedef可以修复此问题(尝试了一些方法,但没有成功)
另外,我不明白第二个问题-过滤器的b_2;在过滤器1中不再可访问,即使所有内容都是公开的。(可以通过将b_u替换为过滤器
class Filter2A : public Filter<Filter2A<DerivedModel> >, public DerivedModel {
在这些情况下,您需要命名特定的类型,而不是提及编译器无法转换为实际类型的模板名称。模板名称本身(没有解析为特定类型的所有参数)不会向编译器提供解析实际类型所需的信息(计算布局信息、查找符号等所需的信息)
关于查找
b
符号,这是一个继承类型的成员,该类型是一个依赖类型(意味着编译器在声明模板时不知道该类型)。您需要给编译器一个提示,这个符号是一个依赖符号,必须在实例化时查找。尝试使用this->b_
而不是仅仅使用b_
。或者,使用类命名空间限定符。然后,编译器会将该符号视为从属符号,并在模板实例化时而不是在模板定义时解析它。尽管投票数很低,但仍感谢彻底的解决方案。为了解析这些符号,为了方便起见,我添加了行“typedef Filterclass Filter2A : public Filter<Filter2A<DerivedModel> >, public DerivedModel {
return static_cast<DerivedFilter<DerivedModel>*>(this)->step();