tags:

views:

99

answers:

3

When I've got a template with certain type parameters, is it allowed for a function to return an object of this same template, but with different types? In other words, is the following allowed?

template<class edgeDecor, class vertexDecor, bool dir>
Graph<edgeDecor,int,dir> Graph<edgeDecor,vertexDecor,dir>::Dijkstra(vertex s, bool 
print = false) const
{
    /* Construct new Graph with apropriate decorators */
    Graph<edgeDecor,int,dir> span = new Graph<edgeDecor,int,dir>();    

    /* ... */

    return span;
};

If this is not allowed, how can I accomplish the same kind of thing?

A: 

Its certainly possible. To me the above code appears valid

hype
+1  A: 

Allowed. Some corrections to your code sample:

template<class edgeDecor, class vertexDecor, bool dir>
Graph<edgeDecor,int,dir> *Graph<edgeDecor,vertexDecor,dir>::Dijkstra(vertex s, bool 
print = false) const
{
    /* Construct new Graph with apropriate decorators */
    Graph<edgeDecor,int,dir> *span = new Graph<edgeDecor,int,dir>();    

    /* ... */

    return span;
};
Vulcan Eager
@agnel-kurian Is it not OK to return-by-value a copy of the Graph? Or is it that I must always use a pointer with the `new` keyword?
nieldw
You must use a pointer with the `new` keyword. Returning a copy is fine.
Vulcan Eager
@agnel Returning a local pointer is a bad idea. I think better is still return a copy, but create new graph like that:Graph<edgeDecor,int,dir> span = Graph<edgeDecor,int,dir>::Graph<edgeDecor,int,dir>();
Draco Ater
@agnel-kurian: So if I use new, I HAVE TO do it the way you are suggesting?
nieldw
@draco-ater: Would that be equivalent to saying `Graph<edgeDecor,int,dir>::Graph<edgeDecor,int,dir> span();` ? Or even just saying `Graph<edgeDecor,int,dir>::Graph<edgeDecor,int,dir> span;` ?
nieldw
@nieldw, `new` returns a pointer is what I am suggesting. Unless `Graph<edgeDecor,int,dir>` has a constructor accepting a pointer to it, I don't see how your code can work (or even compile).
Vulcan Eager
@draco ater, Yes, returning a copy is good. But since we are using dynamic allocation, there must be a good reason for returning the pointer.
Vulcan Eager
@nieldw yes, you are right. That are the short forms.
Draco Ater
@agnel But we will have to delete that pointer manually after. But it's just the matter of liking, I understand. I try to avoid pointers when I can :)
Draco Ater
A: 

In fact, you can return whatever you want. You can even return something that depends on the template parameters:

namespace result_of
{
  template <class T>
  struct method { typedef T type; };

  template <class T>
  struct method<T&> { typedef T type; }

  template <class T>
  struct method<T*> { typedef T type; }

  template <class T, class A>
  struct method< std::vector<T,A> > { typedef T type; }
}

template <class T>
typename result_of::method<T>::type method(const T&) { /** **/ };
Matthieu M.