How to achieve “virtual template function” in C++

后端 未结 9 1661
囚心锁ツ
囚心锁ツ 2020-11-28 03:20

first off: I have read and I know now that a virtual template member function is not (yet?) possible in C++. A workaround would be to make the class a template and then use

9条回答
  •  栀梦
    栀梦 (楼主)
    2020-11-28 03:51

    Per Mikael's post, I have made another offshoot, using the CRTP and following Eigen's style of using derived() for an explicit subclass reference:

    // Adaptation of Visitor Pattern / CRTP from:
    // http://stackoverflow.com/a/5872633/170413
    
    #include 
    using std::cout;
    using std::endl;
    
    class Base {
    public:
      virtual void tpl(int x) = 0;
      virtual void tpl(double x) = 0;
    };
    
    // Generics for display
    template
    struct trait {
      static inline const char* name() { return "T"; }
    };
    template<>
    struct trait {
      static inline const char* name() { return "int"; }
    };
    template<>
    struct trait {
      static inline const char* name() { return "double"; }
    };
    
    // Use CRTP for dispatch
    // Also specify base type to allow for multiple generations
    template
    class BaseImpl : public BaseType {
    public:
      void tpl(int x) override {
        derived()->tpl_impl(x);
      }
      void tpl(double x) override {
        derived()->tpl_impl(x);
      }
    private:
      // Eigen-style
      inline DerivedType* derived() {
        return static_cast(this);
      }
      inline const DerivedType* derived() const {
        return static_cast(this);
      }
    };
    
    // Have Child extend indirectly from Base
    class Child : public BaseImpl {
    protected:
      friend class BaseImpl;
      template
      void tpl_impl(T x) {
        cout << "Child::tpl_impl<" << trait::name() << ">(" << x << ")" << endl;
      }
    };
    
    // Have SubChild extend indirectly from Child
    class SubChild : public BaseImpl {
    protected:
      friend class BaseImpl;
      template
      void tpl_impl(T x) {
        cout << "SubChild::tpl_impl<" << trait::name() << ">(" << x << ")" << endl;
      }
    };
    
    
    template
    void example(BaseType *p) {
      p->tpl(2);
      p->tpl(3.0);
    }
    
    int main() {
      Child c;
      SubChild sc;
    
      // Polymorphism works for Base as base type
      example(&c);
      example(&sc);
      // Polymorphism works for Child as base type
      example(&sc);
      return 0;
    }
    

    Output:

    Child::tpl_impl(2)
    Child::tpl_impl(3)
    SubChild::tpl_impl(2)
    SubChild::tpl_impl(3)
    SubChild::tpl_impl(2)
    SubChild::tpl_impl(3)
    

    This snippet may be found in source here: repro:c808ef0:cpp_quick/virtual_template.cc

提交回复
热议问题