C++ 从一个CRTP子类访问另一个CRTP子类的数据/方法

C++ 从一个CRTP子类访问另一个CRTP子类的数据/方法,c++,class,templates,crtp,C++,Class,Templates,Crtp,“模型”是一个基类,定义了每个派生模型必须具有的数据结构和方法。“过滤器”是一个基类,它使用模型的数据结构和方法(都具有在模型基类中定义的相同接口)。将有多个衍生模型和多个衍生过滤器。每个派生过滤器应该能够作用于任何派生模型。模型独立于滤波器。由于速度很重要,我尝试使用奇怪的循环模板模式(CRTP)进行静态多态性。理想情况下,过滤器使用的模型中的方法应该是可内联的。本课程设计的起点是: template <typename DerivedModel> class Model { p

“模型”是一个基类,定义了每个派生模型必须具有的数据结构和方法。“过滤器”是一个基类,它使用模型的数据结构和方法(都具有在模型基类中定义的相同接口)。将有多个衍生模型和多个衍生过滤器。每个派生过滤器应该能够作用于任何派生模型。模型独立于滤波器。由于速度很重要,我尝试使用奇怪的循环模板模式(CRTP)进行静态多态性。理想情况下,过滤器使用的模型中的方法应该是可内联的。本课程设计的起点是:

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替换为过滤器::b_u来修复)。对于更简单的CRTP代码示例,这是不必要的。

只要正确输入类名,您的第一次尝试可能会成功:

class Filter2A : public Filter<Filter2A<DerivedModel> >, public DerivedModel {
在这些情况下,您需要命名特定的类型,而不是提及编译器无法转换为实际类型的模板名称。模板名称本身(没有解析为特定类型的所有参数)不会向编译器提供解析实际类型所需的信息(计算布局信息、查找符号等所需的信息)


关于查找
b
符号,这是一个继承类型的成员,该类型是一个依赖类型(意味着编译器在声明模板时不知道该类型)。您需要给编译器一个提示,这个符号是一个依赖符号,必须在实例化时查找。尝试使用
this->b_
而不是仅仅使用
b_
。或者,使用类命名空间限定符。然后,编译器会将该符号视为从属符号,并在模板实例化时而不是在模板定义时解析它。

尽管投票数很低,但仍感谢彻底的解决方案。为了解析这些符号,为了方便起见,我添加了行“typedef FilterF;”,然后可以键入“F::b_”等。
class Filter2A : public Filter<Filter2A<DerivedModel> >, public DerivedModel {
    return static_cast<DerivedFilter<DerivedModel>*>(this)->step();