【问题标题】:Curiously Recurring Template and Template parameter dependent subclassing issues奇怪地重复出现的模板和模板参数相关的子类化问题
【发布时间】:2014-06-17 23:36:54
【问题描述】:

我正在尝试使以下代码工作

template < class __derived, class __object = typename __derived::Object >
struct Base {
    using Derived = __derived;
    using Object = __object;
    void function(Object o) { return Derived::function(s); }
}

//template < class __derived >
//struct Base {
//    using Derived = __derived;
//    using Object = typename Derived::Object;
//    void function(Object o) { return Derived::function(s); }
//}

template < class __object >
struct Derived : public Base< Derived< __Object > > {
    using Object = __object;
    void function(Object o) { ... }
}

我通过声明来实例化一个对象

Derived<double> obj;

问题是,编译器声称无法在Derived 类中找到符号Object,同时推导Base 类的第二个模板参数。注释版本也会产生同样的错误。

我试图在 Eigen3 代码的启发下执行此操作,特别是他们使用的 CRTP(Curiously Recurring Template Pattern)以避免使用虚函数。 Eigen3 实际上使用了 traits 类,但我不知道如何在当前情况下模仿它。 有人对此有什么建议吗?提前致谢!

【问题讨论】:

  • Derived 无法实例化Object,直到实例化Base,但Base 无法实例化,因为Derived::Object 尚不存在。是的,使用特征类。
  • 请不要使用带有双下划线的标识符。这些是为 C++ 实现(编译器/库)保留的。
  • 这是什么?盗梦空间的 C++ 版本?
  • @Praetorian 我认为是 IRTIP。无限循环的模板实例化模式。

标签: c++ templates subclassing crtp


【解决方案1】:

通常,如果您希望 A 从 B 继承,则 B 除了声明之外对 A 无能为力:

template < class __object >
struct Derived;

不幸的是,你想得到更多,所以你必须使用类型特征:

template<class __derived>
struct Base_traits {
    //using Object = ?????;
};
template<class __object>
struct Base_traits<Derived<__object>> {
    using Object = __object; //note, this also can't inspect B.
};

Base 类可以检查 Base_traits 所需的一切,因为特征根本不检查 B

template < class __derived, class __object = typename Base_traits<__derived>::Object >
struct Base {
    using Derived = __derived;
    using Object = typename Base_traits<__derived>::Object;
    //or        
    using Object = __object;


凡人不允许使用不相关的前导双下划线,使用单个前导下划线后跟小写字母。或者,使用尾随下划线。

还有语法

void function(Object o) { return Derived::function(s); }

不起作用,因为该符号不能用于向上转换,只能用于向下转换。因此,您必须在this 上使用static_cast。由于这有点难看,我把它放在一个函数后面:

    void foo(Object o) { self()->bar(o); }
private:
    __derived* self() {return static_cast<__derived*>(this);}
    const __derived* self() const {return static_cast<__derived*>(this);}
};

完整代码:http://coliru.stacked-crooked.com/a/81595b0fcd36ab93

【讨论】:

  • 感谢您的精彩回答!我设法让它工作!现在我专注于另一个无关的问题,所以我将发布另一个问题!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多