Can a class member function template be virtual?

前端 未结 13 941
旧时难觅i
旧时难觅i 2020-11-22 03:29

I have heard that C++ class member function templates can\'t be virtual. Is this true?

If they can be virtual, what is an example of a scenario in which one would

13条回答
  •  广开言路
    2020-11-22 04:02

    There is a workaround for 'virtual template method' if set of types for the template method is known in advance.

    To show the idea, in the example below only two types are used (int and double).

    There, a 'virtual' template method (Base::Method) calls corresponding virtual method (one of Base::VMethod) which, in turn, calls template method implementation (Impl::TMethod).

    One only needs to implement template method TMethod in derived implementations (AImpl, BImpl) and use Derived<*Impl>.

    class Base
    {
    public:
        virtual ~Base()
        {
        }
    
        template 
        T Method(T t)
        {
            return VMethod(t);
        }
    
    private:
        virtual int VMethod(int t) = 0;
        virtual double VMethod(double t) = 0;
    };
    
    template 
    class Derived : public Impl
    {
    public:
        template 
        Derived(TArgs&&... args)
            : Impl(std::forward(args)...)
        {
        }
    
    private:
        int VMethod(int t) final
        {
            return Impl::TMethod(t);
        }
    
        double VMethod(double t) final
        {
            return Impl::TMethod(t);
        }
    };
    
    class AImpl : public Base
    {
    protected:
        AImpl(int p)
            : i(p)
        {
        }
    
        template 
        T TMethod(T t)
        {
            return t - i;
        }
    
    private:
        int i;
    };
    
    using A = Derived;
    
    class BImpl : public Base
    {
    protected:
        BImpl(int p)
            : i(p)
        {
        }
    
        template 
        T TMethod(T t)
        {
            return t + i;
        }
    
    private:
        int i;
    };
    
    using B = Derived;
    
    int main(int argc, const char* argv[])
    {
        A a(1);
        B b(1);
        Base* base = nullptr;
    
        base = &a;
        std::cout << base->Method(1) << std::endl;
        std::cout << base->Method(2.0) << std::endl;
    
        base = &b;
        std::cout << base->Method(1) << std::endl;
        std::cout << base->Method(2.0) << std::endl;
    }
    

    Output:

    0
    1
    2
    3
    

    NB: Base::Method is actually surplus for real code (VMethod can be made public and used directly). I added it so it looks like as an actual 'virtual' template method.

提交回复
热议问题