简体   繁体   English

从基非模板类调用派生模板类方法

[英]Calling derived template class method from base non-template class

I'm trying to create the following flow:我正在尝试创建以下流程:

Having a 'Base' class, with no params or functionality, just so i can hold Base pointers in a method.有一个“Base”类,没有参数或功能,这样我就可以在方法中保存 Base 指针。

Its derived class, is a template, which implements operator() on given template argument object type.它的派生类是一个模板,它在给定的模板参数对象类型上实现 operator()。

I'm trying, by using a pointer to base class, call the derived class operator(), in run-time.我正在尝试通过使用指向基类的指针,在运行时调用派生类 operator()。

I've tried implementing it using CRTP ( https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern ) But that doesn't seem to work the-other-way-around - when the derived class is a class template.我已经尝试使用 CRTP ( https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern ) 实现它,但这似乎不起作用 - 当派生类是类模板时。

Here is my code:这是我的代码:

class Base {};

template<typename Ref_Obj, typename Obj_Type>
class Derived : public Base {
    private:
        typedef bool (Ref_Obj::*Func_p)(Obj_Type) const;
        Func_p m_func;
        const Ref_Obj& m_db;

    public:
        Derived<Ref_Obj, Obj_Type>(const Ref_Obj& db, Func_p func): m_db(base), m_func(filter) {}

        inline bool operator()(const Obj_Type& obj) const {
            return (m_db.*m_func)(obj);
        }
}

Now, usage is in another class template, that contains vector of Base class pointers, as follows, and have its own operator() :现在,用法是在另一个类模板中,它包含基类指针的向量,如下所示,并有自己的 operator() :

template<typename Obj_Type2> /* Upon usage, Obj_Type2 is the same as Obj_Type, this is just to differ the two in the code here */
class BlaBla {
    private:
        std::vector<const Base *> m_vec;

    public:
        /* relevant constructors ... */

        inline bool operator()(const Obj_Type2 &obj) const {
            for(std::vector<const Base *>::const_iterator it = m_vec.begin(); it != m_vec.end(); ++it) {

                /*** This is the problematic line V ***/
                if( (*it).operator()(obj) ) { /* DO SOMETHING */ }                    
        }
}

Of course the compiler is complaining that there is no matching function to call for in the problematic line that is marked in the code below, but i can't figure out a way to do the relevant call.当然,编译器抱怨在下面的代码中标记的有问题的行中没有匹配的函数可以调用,但我无法找到进行相关调用的方法。

1st Solution that came to mind, is to create a virtual operator()(...) , with a specific object type eg virtual operator()(const uint32_t &obj) in Base class, which works, but my intention is that operator()(...) will receive a variety of object types, and stating a virtual method for each of them is not elegant and seems to break all the template concept i want to implement here.想到的第一个解决方案是创建一个虚拟 operator()(...) ,在基类中具有特定的对象类型,例如 virtual operator()(const uint32_t &obj) ,它有效,但我的意图是 operator( )(...) 将收到各种对象类型,并且为每个对象声明一个虚拟方法并不优雅,似乎打破了我想在这里实现的所有模板概念。

2nd Solution that came to mind, is somehow passing Ref_Obj and Obj_Type typenames to Base class, to be used in sort of interface method, that will use static_cast to call the appropriate Derived operator (As in CRTP) - But that doesn't seem to work because Derived class is a class template, and also BlaBla class doesn't directly know Ref_Obj typename.想到的第二个解决方案是以某种方式将Ref_ObjObj_Type类型名传递给基类,以用于某种接口方法,这将使用 static_cast 来调用适当的派生运算符(如在 CRTP 中)-但这似乎不是工作是因为派生类是一个类模板,而且 BlaBla 类不直接知道Ref_Obj类型名。

Is there any other way to make the appropriate call to Deriver operator()有没有其他方法可以对 Deriver operator() 进行适当的调用

There is no clear clean way to do this.没有明确干净的方法来做到这一点。 The fundamental problem is that there is no such thing as a virtual template method.根本问题是没有虚拟模板方法这样的东西。

The cleanest way I can think of doing this that implements complete type erasure is with a dynamic cast, and a virtual method:我能想到的实现完整类型擦除的最干净的方法是使用动态转换和虚拟方法:

class Base {
public:

    virtual bool operator()(const Base &) const=0;
};

template<typename Ref_Obj, typename Obj_Type>
class Derived : public Base {
    private:
        typedef bool (Ref_Obj::*Func_p)(Obj_Type) const;
        Func_p m_func;
        const Ref_Obj& m_db;

    public:
        Derived<Ref_Obj, Obj_Type>(const Ref_Obj& db, Func_p func): m_db(base), m_func(filter) {}

        inline bool operator()(const Base& obj) const override {
            const Obj_Type *derived_obj=dynamic_cast<const Obj_Type *>(&obj);

            if (!derived_obj)
            {
                  throw; // Or maybe return false, or something...
            }
            return (m_db.*m_func)(*derived_obj);
        }
};

Obj_Type must also be derived from Base . Obj_Type也必须从Base派生。 This gets the job done at runtime, but there is no compile-time type-checking.这在运行时完成工作,但没有编译时类型检查。

The other approach is to bite the bullet, and forego 100% type erasure:另一种方法是硬着头皮,放弃 100% 类型擦除:

template<typename Obj_Type>
class Base {
public:

    virtual bool operator()(const Obj_Type &) const=0;
};

template<typename Ref_Obj, typename Obj_Type>
class Derived : public Base<Obj_Type> {
    private:
        typedef bool (Ref_Obj::*Func_p)(Obj_Type) const;
        Func_p m_func;
        const Ref_Obj& m_db;

    public:
        Derived<Ref_Obj, Obj_Type>(const Ref_Obj& db, Func_p func): m_db(base), m_func(filter) {}

        inline bool operator()(const Obj_Type& obj) const override {
            return (m_db.*m_func)(obj);
        }
};

So, you can still abstract away operator() on some object to its pure interface, and define the details in the subclass.因此,您仍然可以将某个对象上的operator()抽象到其纯接口,并在子类中定义详细信息。

Or, another alternative would be a combination of the two:或者,另一种选择是两者的结合:

class SuperBase {
public:

    virtual bool operator()(const Base &) const=0;
};

template<typename Obj_Type>
class Base : public SuperBase {
public:

    virtual bool operator()(const Obj_Type &) const=0;

    bool operator()(const Base &obj) const override
    {
          // Do the dynamic cast check, and forward it to the other
          // operator().
    }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在从模板化中介派生的 class 中调用非模板基 class 构造函数 - Calling non-template base class constructor in class derived from templated intermediary 从非模板基 class 指针调用模板派生 class 方法的方法 - Invoke a method of templated derived class method from non-template base class pointer 从非模板类调用专门的模板方法 - Calling specialized template method from non-template class 从非模板基类派生的模板类:无法访问基类变量? - Template Class derived from Non-template base class: No access to base class variables? 如何将模板派生类的方法提取到非模板基类中 - how to extract template derived class's method into non-template base class 派生类中非模板方法的模板方法 - Template method over non-template method in derived class 继承的非模板类的范围问题(模板基,非模板派生) - Scope problems with inherited non-template class (template base, non-template derived) 将非模板基类向下转换为模板化派生类:是否可能? - Downcasting non-template base class to templated derived class: is it possible? 从模板派生类访问非模板基类虚函数 - accessing non-template base class virtual function from template derived class 从非模板库中派生模板类 - Deriving a template class from a non-template base
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM