Curiously Recurring Template and Template parameter dependent subclassing issues
我正在尝试使以下代码工作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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) { ... } } |
我通过声明
1 | Derived<double> obj; |
问题是,编译器声称在推导
我试图在Eigen3代码的启发下做到这一点,特别是他们为了避免使用虚拟函数而使用的CRTP(奇怪的重复模板模式)。Eigen3实际上使用了一个
通常,如果您希望a从b继承,那么b除了声明之外,不能知道关于a的任何信息:
1 2 | template < class __object > struct Derived; |
不幸的是,你想得到更多,所以你必须使用一个类型特征:
1 2 3 4 5 6 7 8 | 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. }; |
1 2 3 4 5 6 | 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; |
不相关的前导双下划线不允许凡人使用,请使用一个前导下划线,后跟一个小写字母。或者,使用尾随下划线。
另外,语法
1 | void function(Object o) { return Derived::function(s); } |
不起作用,因为这个符号不能用于倒推,只能用于倒推。因此,你必须在
1 2 3 4 5 | 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