Search code examples
c++templatesgeneric-programming

C++, generic programming and virtual functions. How do I get what I want?


This is what I would like to do using templates:

struct op1
{
   virtual void Method1() = 0;
}

...

struct opN
{
   virtual void MethodN() = 0;
}

struct test : op1, op2, op3, op4
{
    virtual void Method1(){/*do work1*/};
    virtual void Method2(){/*do work2*/};
    virtual void Method3(){/*do work3*/};
    virtual void Method4(){/*do work4*/};
}

I would like to have a class that simply derives from a template class that provides these method declarations while at the same time making them virtual. This is what I've managed to come up with:

#include <iostream>

template< size_t N >
struct ops : ops< N - 1 >
{
protected:
    virtual void DoStuff(){ std::cout<<N<<std::endl; };
public:
    template< size_t i >
    void Method()
    { if( i < N ) ops<i>::DoStuff(); } 
    //leaving out compile time asserts for brevity
};

template<>
struct ops<0>
{
};

struct test : ops<6>
{
};

int main( int argc, char ** argv )
{
  test obj;
  obj.Method<3>(); //prints 3
  return 0;
}

However, as you've probably guessed, I am unable to override any of the 6 methods I have inherited. I'm obviously missing something here. What is my error? No, this isn't homework. This is curiosity.


Solution

  • Tested with GCC 4.3. Don't even know why I spent time on this :-/

    #include <iostream>
    
    template <std::size_t N>
    struct mark
    { };
    
    template <std::size_t N>
    struct op : op <N - 1>
    {
      virtual  void  do_method (const mark <N>&) = 0;
    };
    
    template <>
    struct op <1>
    {
      virtual  void  do_method (const mark <1>&) = 0;
    };
    
    struct test : op <2>
    {
      template <std::size_t K>
      void
      method ()
      {  do_method (mark <K> ());  }
    
      virtual  void do_method (const mark <1>&)
      {  std::cout << "1\n";  }
    
      virtual  void do_method (const mark <2>&)
      {  std::cout << "2\n";  }
    };
    
    int
    main ()
    {
      test  x;
    
      x.method <1> ();
      x.method <2> ();
    }
    

    I don't know how to move the "prettifier" method() template function out of test.