tags:

views:

140

answers:

2

I have a number of class, all with exactly the same interface. This interface defines a few methods, some of which are templated (the class itself may or may not be).

So the interface looks something like this

class MyClass
{
public:
  void Func1();

  template <typename T>
  void Func2(T param);
};

I have a number of functions which take various objects which conform to this interface but want to avoid having to know the exact implementation at compile time.

Obviously, the default C++ solution would be to have a base type that all these classes derive from and pass around a pointer to that and have polymorphism do all the work.

The problem is that templated member functions cannot be virtual so this method cannot be used. I also want to avoid changing the current set of classes that follow this interface because there are a large number of them, some of which are defined outside the scope of my project.

The other solution is to template the functions that use these objects so they specialise for the right type. This could be a solution but due to legacy requirements templating a large number functions may not be possible (this is something I cannot do anything about as the client code isn't something I have responsibility for).

My initial thought was to provide some kind of carrier class which is type neutral and in effects wraps the common interface here and has a base interface class to pass around the internal type.

Something along the lines of

class MyInterface
{
public:   
 virtual void Func1() = 0;
};

template <typename T>
class MyImplementation
{
public:
  virtual void Func1()
  {
    m_impl->Func1();
  }

private:
  T* m_impl;
};

But again the templated member functions seem to block this approach.

I looked at the boost::any and boost::function classes which I thought might offer some kind of solution but they don't seem to give me the right answer.

So, does anyone have any suggestions or work around on how to make this possible, if indeed it is? Personally I'm leaning towards having to template the various functions that require these objects - since that's the functionality templates provide - but thought it worth investigating first.

Thanks in advance

+1  A: 

If you use templates you need to know AT COMPILE TIME which type(s) you're using. That's just the nature of templates (templates look like code that's dynamic at runtime, but in reality it's just shorthand that tells the compiler what versions of the function to compile and include in the object code). Best case senario is something like this:

template <class T>
void DoSomethingWithMyInterface(MyInterface<T> X)
{
    //do something
}

...

switch (MyObject.GetTypeCode())
{
case TYPE1: DoSomethingWithMyInterface<type1>(MyObject); break;
case TYPE2: DoSomethingWithMyInterface<type2>(MyObject); break;
case TYPE3: DoSomethingWithMyInterface<type3>(MyObject); break;
case TYPE4: DoSomethingWithMyInterface<type4>(MyObject); break;
}

I actually use this situation a lot. I write templated c++ code that does the processing for a dynamically typed language. That means that the top level language doesn't know the data types until run time, but I need to know them at compile time. So I create this "TypeSwitch" (I actually have a fancy reusable one). That looks at the datatypes at run time and then figures out which of the already compiled template functions to run.

Note - that this requires me knowing all the types I'm going to support before hand (and I do) and the switch statement actually causes the compiler to generate all of the code that could ever be executed. Then at runtime the right one is selected.

miked
This is an interesting solution and one I think may solve the problem in this case. The client is working with a small subset of the various objects which wouldn't require a massive switch statement.
Lee Winder
+2  A: 

What's not entirely clear to me is how you're resolving the parameter T to Func2, do you need some kind of dynamic dispatch on that too, or is it known at compile time at the call site?

In the former case, it sounds like multimethods. In the latter, how about this variation on your interface idea:

#include <iostream>

template<class T> struct generic_delegate
{
  virtual void call(T param) = 0;
};

template<class U, class T> class fn_delegate : public generic_delegate<T>
{
  U* obj;
  void (U::*fn)(T);

public:
  fn_delegate(U* o, void (U::*f)(T)) :
    obj(o), fn(f)
  {}

  virtual void call(T param)
  {
    (obj->*fn)(param);
  }
};


class A
{
public:
  template<class T> void fn(T param)
  {
    std::cout << "A: " << param << std::endl;
  }
};

class B
{
public:
  template<class T> void fn(T param)
  {
    std::cout << "B: " << param << std::endl;
  }
};


template<class T, class U> generic_delegate<T>* fn_deleg(U* o)
{
  return new fn_delegate<U, T>(o, &U::template fn<T>);
}


int main()
{
  A a;
  B b;

  generic_delegate<int>* i = fn_deleg<int>(&a);
  generic_delegate<int>* j = fn_deleg<int>(&b);

  i->call(4);
  j->call(5);
}

Obviously, the thing you'd be passing around are the generic delegate pointers.

pmjordan