tags:

views:

183

answers:

3

I'm working with some generated classes with broken polymorphism. For every generated class T, there are a handful of T_type_info, T_writer, T_reader classes which are only related to T conceptually.

What I'm trying to do is something like this:

template <class T> class Wrapper
{
public:
   template <class W> W topic_cast(BrokenBaseClassWriter* p);
   // other operations with the same problem ...
};

template <> class Wrapper<MyTopic>
{
public:
    template <> MyTopicWriter* topic_cast(BrokenBaseClassWriter* p) { ... }
};

So that I can do things like:

void Write(const Wrapper<T>& topic)
{
    BrokenBaseClassWriter p = not_important;
    topic.topic_cast(p)->do_stuff();
}

My T classes are generated from an IDL and are concepts that exist in application space. They don't derive from anything. In my example above, W is not really an independent parameter, it's "Something Not T that depends on T". I'm trying to keep all knowledge of T in the app, and all knowledge of T' (without knowing about T) in the backend.

The compiler however says my topic_cast function is not a template function - I think because the template occurs in the return type and it wouldn't be distinguishable from any other instantiations. I know that that (templates differ only by return type) is not legal. Only in my case it really would be unique because W is not an independent parameter. But arguing with the compiler is seldom helpful.

Can I do this, or is there another way to do this "cast as function of template type"?

+1  A: 

Could this not be achieved with a traits system?

template <typename T> struct my_traits
{
};

template <> struct my_traits<MyClass>
{
  typedef MyWriter writer_type;
};

template <typename T> struct Wrapper
{
  typename my_traits<T>::writer_type topic_cast();
};
Victor Nicollet
This is what I was attempting to arrive at with the square wheel I was building above. Wrapper is no longer needed - the type mapping was its original purpose. Thanks
swarfrat
A: 

This can't work:

topic.topic_cast(p)->do_stuff(); 

Because the compiler can not deduce the return type.
So you have to explicitly tell the compiler what return type you want:

topic.topic_cast<MyType>(p)->do_stuff();

The implementation you provide is for a specific type.
So when you use that specific type that code will be produced:

topic.topic_cast<MyTopicWriter>(p)->do_stuff();   // Use the explicit specialization
Martin York
A: 

This compiles with gcc:

class BrokenBaseClassWriter;
class MyTopic;
class MyTopicWriter;

template <class T> class Wrapper
{
public:
   template <class W> W *topic_cast(BrokenBaseClassWriter* p);
   // other operations with the same problem ...
};




template <> template<> 
MyTopicWriter *Wrapper<MyTopic>::topic_cast<MyTopicWriter>(BrokenBaseClassWriter* p)
{
  return 0;
}


int main(int argc, int argv)
{
  BrokenBaseClassWriter* p = NULL;
  Wrapper<MyTopic> caster;
  MyTopicWriter *casted = caster.topic_cast<MyTopicWriter>(p);
}

Of course, it still exposes MyTopicWriter in your main code...

Arkadiy