Question

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.

Was it helpful?

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.

OTHER TIPS

template< size_t N >
struct ops : ops< N - 1 >

This codes an endless loop. The recursion doesn't stop when N reaches 0. Add a specialization for the end case, immediately after the primary template:

template<>
struct ops<0> {}

Also, what does this do? Why not just call ops<i>::DoStuff() directly?

template< size_t i >
void Method()
{ if( i < N ) ops<i>::DoStuff(); } 

To mimic your original desire:

#define MAKE_OPS(N) template<> struct Ops<N> : Ops<N-1> { virtual void Method##N() = 0; }

template<int N>
struct Ops;

template<>
struct Ops<0> { };

MAKE_OPS(1);
MAKE_OPS(2);
template<> struct Ops<3> : Ops<2> { virtual void Method3() { std::cout << "3" << std::endl; } };
MAKE_OPS(4);
MAKE_OPS(5);
MAKE_OPS(6);

struct Test : Ops<3> {
    virtual void Method1() { std::cout << 1 << std::endl; }
    virtual void Method2() { std::cout << 2 << std::endl; }
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top