我正在尝试使以下代码正常工作
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
类,但我无法弄清楚如何模仿当前的情况。
有人对此有任何建议吗?提前谢谢!
答案 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);}
};