奇怪的循环模板和模板参数依赖子类化问题 [英] Curiously Recurring Template and Template parameter dependent subclassing issues

查看:108
本文介绍了奇怪的循环模板和模板参数依赖子类化问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想让以下代码工作

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;
Problem is, the compiler claims not to be able to find the symbol Object inside the Derived class while deducing the second template parameter for the Base class. The same error is also generated by the commented version.

我试图在Eigen3代码的灵感下,特别是CRTP(奇怪的循环模板模式)以避免使用虚拟函数。 Eigen3实际上使用一个 traits 类,但我不知道如何模仿这种情况。
任何人有任何建议吗?提前感谢!

I am trying to do this under inspiration of Eigen3 code, particularly the CRTP (Curiously Recurring Template Pattern) they use in order to avoid use of virtual functions. Eigen3 actually uses a traits class but I can't figure out how to imitate that for the present case. Anyone has any suggestion about this? Thanks in advance!

推荐答案

通常,如果你希望A继承B,那么B不能知道A的任何东西,声明:

Normally, if you want A to inherit from B, then B cannot know anything about A other than it's declaration:

template < class __object >
struct Derived;

不幸的是,你想获得更多,所以你必须使用类型trait: p>

Unfortunately, you want to get more, so you'll have to use a type trait:

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 c $ c> Base_traits 所有它想要的,因为traits不检查 B

The Base class can inspect the Base_traits all it wants, because the traits don't inspect B at all.

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;



不相关的前导双下划线不允许由凡人使用,请使用单个前导下划线后跟小写字母。


Unrelated, leading double underscores are disallowed for use by mortals, use a single leading underscore followed by a lowercase letter. Alternatively, use a trailing underscore.

此外,语法

void function(Object o) { return Derived::function(s); }

无法工作,因为这种符号不能用于upcasts,只能用于downcasts。 Ergo,你必须在上使用 static_cast 。因为那是丑陋的,我把它放在一个函数后面:

Won't work, because that notation cannot be used for upcasts, only downcasts. Ergo, you have to use static_cast on the this. Since that's vaguely ugly, I put it behind a function:

    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

这篇关于奇怪的循环模板和模板参数依赖子类化问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆