我正在尝试使以下代码正常工作
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