--- src/doxygen.cpp.orig	Tue Dec 27 11:04:39 2005
+++ src/doxygen.cpp	Fri Feb 17 16:19:53 2006
@@ -3860,9 +3861,12 @@
 
         }
         bool isATemplateArgument = templateNames!=0 && templateNames->find(biName)!=0;
+        // make templSpec canonical
+        templSpec = getCanonicalTemplateSpec(cd, cd->getFileDef(), templSpec);
+
         if (found)
         {
-          Debug::print(Debug::Classes,0,"    Documented class `%s' templSpec=%s\n",biName.data(),templSpec.data());
+          Debug::print(Debug::Classes,0,"    Documented class `%s' templSpec=%s\n",biName.data(),templSpec.isEmpty()?"":templSpec.data());
           // add base class to this class
 
           // if templSpec is not empty then we should "instantiate"
--- src/util.h.orig	Tue Dec 27 11:04:41 2005
+++ src/util.h	Fri Feb 17 16:04:45 2006
@@ -152,6 +152,8 @@
 
 void writePageRef(OutputDocInterface &od,const char *cn,const char *mn);
 
+QCString getCanonicalTemplateSpec(Definition *d,FileDef *fs,const QCString& spec);
+
 bool matchArguments2(Definition *srcScope,FileDef *srcFileScope,ArgumentList *srcAl,
                      Definition *dstScope,FileDef *dstFileScope,ArgumentList *dstAl,
                      bool checkCV
--- src/util.cpp.331511	Fri Feb 17 09:52:13 2006
+++ src/util.cpp	Fri Feb 17 16:03:13 2006
@@ -2750,13 +2750,24 @@
   return s;
 }
 
+// forward decl for circular dependencies
+static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type);
+
+QCString getCanonicalTemplateSpec(Definition *d,FileDef *fs,const QCString& spec)
+{
+   QCString templSpec = spec.stripWhiteSpace();
+   if (templSpec.isEmpty() || templSpec.at(0) != '<') return templSpec;
+   return "< " + extractCanonicalType(d,fs,templSpec.right(templSpec.length()-1));
+}
+
+
 static QCString getCanonicalTypeForIdentifier(
                   Definition *d,FileDef *fs,const QCString &word,
                   QCString *tSpec)
 {
   QCString symName,scope,result,templSpec,tmpName;
   //DefinitionList *defList=0;
-  if (tSpec) templSpec = stripDeclKeywords(*tSpec);
+  if (tSpec) templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,*tSpec));
 
   if (word.findRev("::")!=-1 && !(tmpName=stripScope(word)).isEmpty())
   {
@@ -2776,7 +2787,7 @@
   bool isTemplInst = cd && !templSpec.isEmpty();
   if (!cd && !templSpec.isEmpty())
   {
-     // class template instance no known, look up class template
+     // class template specialization not known, look up class template
     cd = getResolvedClass(d,fs,word,&mType,&ts,TRUE);
   }
 
@@ -2834,21 +2845,9 @@
   return result;
 }
 
-static QCString extractCanonicalType(Definition *d,FileDef *fs,const Argument *arg)
+static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type)
 {
-  QCString type = arg->type.stripWhiteSpace();
-  QCString name = arg->name;
-  //printf("extractCanonicalType(type=%s,name=%s)\n",type.data(),name.data());
-  if ((type=="const" || type=="volatile") && !name.isEmpty()) 
-  { // name is part of type => correct
-    type+=" ";
-    type+=name;
-  } 
-  if (name=="const" || name=="volatile")
-  { // name is part of type => correct
-    if (!type.isEmpty()) type+=" ";
-    type+=name;
-  }
+  type = type.stripWhiteSpace();
 
   // strip const and volatile keywords that are not relevant for the type
   stripIrrelevantConstVolatile(type);
@@ -2861,7 +2860,7 @@
   type.stripPrefix("typename ");
 
   type = removeRedundantWhiteSpace(type);
-  //printf("extractCanonicalTyp2(type=%s,name=%s)\n",type.data(),name.data());
+  //printf("extractCanonicalType(type=%s,name=%s)\n",type.data(),name.data());
 
   static QRegExp id("[a-z_A-Z][:a-z_A-Z0-9]*");
   
@@ -2900,6 +2899,25 @@
   return removeRedundantWhiteSpace(canType);
 }
 
+static QCString extractCanonicalArgType(Definition *d,FileDef *fs,const Argument *arg)
+{
+  QCString type = arg->type.stripWhiteSpace();
+  QCString name = arg->name;
+  //printf("extractCanonicalArgType(type=%s,name=%s)\n",type.data(),name.data());
+  if ((type=="const" || type=="volatile") && !name.isEmpty()) 
+  { // name is part of type => correct
+    type+=" ";
+    type+=name;
+  } 
+  if (name=="const" || name=="volatile")
+  { // name is part of type => correct
+    if (!type.isEmpty()) type+=" ";
+    type+=name;
+  }
+
+  return extractCanonicalType(d,fs,type);
+}
+
 static bool matchArgument2(
                    Definition *srcScope,FileDef *srcFileScope,Argument *srcA,
                    Definition *dstScope,FileDef *dstFileScope,Argument *dstA
@@ -2939,11 +2957,11 @@
 
   if (srcA->canType.isEmpty())
   {
-    srcA->canType = extractCanonicalType(srcScope,srcFileScope,srcA);
+    srcA->canType = extractCanonicalArgType(srcScope,srcFileScope,srcA);
   }
   if (dstA->canType.isEmpty())
   {
-    dstA->canType = extractCanonicalType(dstScope,dstFileScope,dstA);
+    dstA->canType = extractCanonicalArgType(dstScope,dstFileScope,dstA);
   }
   
   if (srcA->canType==dstA->canType)
