From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2002-04-25 18:51:50


> > struct Y {
> > template<class> class nested { }; // i.e. nested is a template, not a
type
> > };
>
> I believe Comeau C++ is right here. A type is a different "meta-type"
> than a template, and the language really differentiates those.
> (Note the "typename" and "template" keywords required to help
> the compiler with that in template definitions.)
>
> Similar for the reverse.

That was not my point exactly. Obviously, a template is not a type and
therefore should not match. In fact, the relative part of the standard says
(paraphrased) use of a given member that is not a type when a type is required
should cause template type deduction to fail. The problem with Comeau C++ is
that it is not 'failing' template type deduction (which it should) nor is it
emitting a normal error. Instead, it is emitting a compiler assertion failure
in 'template.c' at line <such and such>. Take the following example:

----- sample 1 -----

#include <iostream>

typedef char small_t;
typedef char (& large_t)[256];

template<class T> class has_nested_type {
   private:
      template<class U> static small_t check(typename U::type*);
      template<class U> static large_t check(...);
   public:
      static const bool value = sizeof(check<T>(0)) == sizeof(small_t);
};

template<class T> const bool has_nested_type<T>::value;

struct X { // 'type' is a template
   template<class> struct type { };
};

int main(int argc, char* argv[]) {
   std::cout << has_nested_type<X>::value << &std::endl;
   return 0;
}

----- output -----

"test2.cpp", line 49: internal error: assertion failed at: "templates.c", line
5623
    static const bool value = sizeof(check<T>(0)) == sizeof(small_t);
                                     ^
----- remarks -----

According to 14.8.2/2 (bullet 3, sub-bullet 3), which says type deduction should
fail...

"Attempting to use a type in the qualifier portion of a qualified name that
names a type when that type does not contain the specified member, or if the
specified member is not a type where a type is required."

... in the case of 'X', 'type' is *not* a type where a type is required.
Therefore, the function should have failed template type deduction and not been
added to the candidate set.

----- sample 2 -----

#include <iostream>

typedef char small_t;
typedef char (& large_t)[256];

template<class T> class has_template_type {
   private:
      template<class U> static small_t check(typename U::template type<int>*);
      template<class U> static small_t check(typename U::template type<int,
int>*);
      template<class U> static small_t check(typename U::template type<int, int,
int>*);
         // etc.
      template<class U> static large_t check(...);
   public:
      static const bool value = sizeof(check<T>(0)) == sizeof(small_t);
};

template<class T> const bool has_template_type<T>::value;

struct Y { // 'type' is *not* a template
   struct type { };
};

int main(int argc, char* argv[]) {
   std::cout << has_template_type<Y>::value << &std::endl;
   return 0;
}

----- output -----

"test2.cpp", line 51: error: more than one instance of overloaded function
  "has_template_type<T>::check [with T=Y]" matches the argument list:
    function template
        "has_template_type<T>::check(U::type<int> *) [with T=Y]"
    function template "has_template_type<T>::check(U::type<int, int>
        *) [with T=Y]"
    function template "has_template_type<T>::check(U::type<int, int,
        int> *) [with T=Y]"
    argument types are: (int)
        static const bool value = sizeof(check<T>(0)) == sizeof(small_t);
                                                 ^
    detected during instantiation of class
        "has_template_type<T> [with T=Y]" at line 67

----- remarks -----

There doesn't seem to be anything in the 14.8.2 list that directly refers to
this, however the 'error' that Comeau C++ gives in clearly erroneous. None of
the said functions match the argument list. Comeau seems to be ignoring the
explicit 'template' keyword in the function declarations.

Paul Mensonides