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

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类,但在当前情况下我不知道如何模仿它。
有人对此有任何建议吗?提前致谢!

最佳答案

通常,如果您希望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

10-07 13:16
查看更多