0
template <class VertexType>
class GraphMatrix
{
};

template <class GraphType>
class Graph
{
 typedef typename GraphType::VertexType VertexType;
 GraphType* graph_;
 void addVertex(VertexType vertex)
 {
 }
 //...
};
int main()
{
    Graph <GraphMatrix <int> > graph;
    return 0;
}

See if I would add typedef VertexType VertexType;//A line to GraphMatrix class this code will pass compilation and will work, otherwise it gives compile error. Error:C2039: 'VertexType' : is not a member of 'GraphMatrix'. My question is follows 'is there a way (syntax) to make above code work without adding this stupid line //A'?

Mihran Hovsepyan
  • 10,810
  • 14
  • 61
  • 111

4 Answers4

1

You could always write the fully qualified name of VertexType, the typedef is merely a shortcut for you, which brings that name into scope and lets you write cleaner code.

So, no in this circumstance, there is no other way.

When using inheritance however you can using BaseClass::something to bring it into scope.

Marcus Borkenhagen
  • 6,536
  • 1
  • 30
  • 33
1

My question is follows 'is there a way (syntax) to make above code work without adding this stupid line //A

I don't think so.

However there are a few problems with your code. GraphType is a dependent-name and to indicate that GraphType::VertexType is a type you need to add typename before it.

However when the class template is instantiated for GraphType = GraphMatrix <int> the compiler couldn't find GraphMatrix <int>::VertexType so you get another error.

So in order to fix the errors change the definition of GraphMatrix to

template <class TVertexType>
class GraphMatrix
{
    public:
    typedef TVertexType VertexType;    
};

or something similar.

Complete working code here

Community
  • 1
  • 1
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
  • Oh I just have forgotten about typename. This is the cause of that I have not copy-past my code, but write here - in forum textarea :) So as I understand from all answers there is no way to avoid typedefing in GraphMatrix. Thanks to all for answers :) – Mihran Hovsepyan Dec 12 '10 at 15:22
0

If you want to get the argument of a templated class passed by a template-parameter, you must confine the allowable types for GraphType. You do this by specialization:

template <class GraphType>
class Graph;

template <template <class> class GraphType, class VertexType>
class Graph<GraphType<VertexType> >
{
  ... // use GraphType<VertexType> as your graph, VertexType as your vertex type
};

You can even create a helper struct that will unpack the args for you:

template <class T> struct get_arg;

template <template <class> class Tpl, class Arg>
struct get_arg<Tpl<Arg> >
{
  typedef Arg type;
};

Note however, that this solution is quite inflexible - it only allows templates with one parameter as arguments for your Graph class template (imagine what you would have done if you added a parameter to your GraphMatrix template). So it is not normally used.

The ordinary solution is either adding typedefs to your classes (as you do with your "stupid line"), or even better, using traits classes and specializing these.

jpalecek
  • 47,058
  • 7
  • 102
  • 144
-1

I doubt so.

From the point of view of the Graph template, the GraphType template parameter is just a type name (so in this case, "a class"). So if Graph is instantiated with GraphType = GraphMatrix<int>, then Graph cannot even check whether it has received a template instance or a "regular" class. Therefore, it cannot access its template parameters - because GraphType doesn't even need to have any template parameters.

Introducing the typedef into GraphType enriches every instance of template GraphMatrix with the public information about the exact type it was instantiated with - which is exactly what you want to achieve.

Kos
  • 70,399
  • 25
  • 169
  • 233
  • Not true - `Graph` can check that `GraphType` is a template with one parameter through specialization. – jpalecek Dec 12 '10 at 20:42
  • But shouldn't - it's better for an implementation to rely on a constract "I'm going to be instantiated with classes which have a typedef `VertexType`" than "I'm going to be instantiated only with template classes which always happen to have their first template parameter as a VertexType". Using specialization here seems hackish to me and violates the least astonishment principle, IMHO. I rest my case. – Kos Dec 12 '10 at 21:25