奇怪的重复模板和模板参数依赖子类问题

时间:2014-06-17 23:36:55

标签: c++ templates subclassing crtp

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

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;

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

我试图在Eigen3代码的启发下做到这一点,特别是他们使用的CRTP(奇怪的重复模板模式),以避免使用虚函数。 Eigen3实际上使用的是traits类,但我无法弄清楚如何模仿当前的情况。 有人对此有任何建议吗?提前谢谢!

1 个答案:

答案 0 :(得分:4)

通常情况下,如果你希望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); }

不会工作,因为这种符号不能用于向上传播,只能用于向下传播。因此,您必须在static_cast上使用this。由于那个模糊不清,我把它放在一个功能之后:

    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