Topic: Dependent names in typeid expressions


Author: llewelly.at@xmission.dot.com (llewelly)
Date: Sat, 3 Jul 2004 00:03:39 +0000 (UTC)
Raw View
"Sergiy Kanilo" <skanilo@artannlabs.com> writes:

> "Scott Meyers" <Usenet@aristeia.com> wrote in message
> news:MPG.1b4dd2218cba25ee98975f@news.hevanet.com...
>> Dependent type names must always be preceded by "typename", right?  So
>> consider:
>>
>>   template<typename T>
>>   void foo()
>>   {
>>     if (typeid(std::list<T>::iterator) == typeid(int));
>>   }
>>
>> gcc 3.2 issues a warning about the lack of "typename" in front of
>> std::list<T>::iterator, but VC7.1 and Comeau 4.3.3 accept the code without
>> complaint.

Como 4.3.3 at least accepts the code with typename as well as
    without, so maybe with typename is more portable. :-)

>> Is there something special going on here, are VC7.1 and Comeau
>> simply wrong, or is my understanding of typename and dependent names
>> wanting?
>
> 14.6.2.2
> /4 Expressions of the following forms are never type-dependent
> ..
> typeid ( expression )
> typeid ( typeid )

I don't understand why this is relevant. The code GCC wants is this:

    template<typename T>
    void foo()
    {
      if (typeid(typename std::list<T>::iterator) == typeid(int));
    }

Nobody is suggesting that typeid be prefixed with typename!

I look at 14.6/3, and I see:

#    3 A qualified-id that refers to a type and in which the
#      nested-name-specifier depends on a template-parameter (14.6.2)
#      shall be prefixed by the keyword typename to indicate that the
#      qualified-id denotes a type, forming an
#      elaborated-type-specifier (7.1.5.3).
#
#         elaborated-type-specifier:
#             ...
#             typename ::opt nested-name-specifier identifier
#             typename ::opt nested-name-specifier templateopt template-id

It's about whether the nested-name-specifier is type-dependent, not
    about whether typeid is type-dependent.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Michiel.Salters@logicacmg.com (Michiel Salters)
Date: Sat, 3 Jul 2004 00:03:49 +0000 (UTC)
Raw View
Scott Meyers <Usenet@aristeia.com> wrote in message news:<MPG.1b4dd2218cba25ee98975f@news.hevanet.com>...
> Dependent type names must always be preceded by "typename", right?  So
> consider:
>
>   template<typename T>
>   void foo()
>   {
>     if (typeid(std::list<T>::iterator) == typeid(int));
>   }
>
> gcc 3.2 issues a warning about the lack of "typename" in front of
> std::list<T>::iterator, but VC7.1 and Comeau 4.3.3 accept the code without
> complaint.  Is there something special going on here, are VC7.1 and Comeau
> simply wrong, or is my understanding of typename and dependent names
> wanting?

You're making assumptions based on what you know about
std::list<T>::iterator, the compiler can't do that.

Let's write a similar example

template<typename T>
class A {
  typedef T* iterator;
};
template< >
class A<void> {
  static const iterator = 0;
};
template< typename T>
void foo()
{
  if(typeid(A<T>::iterator) == typeid(int));
}

Should A<T>::iterator be typename A<T>::iterator instead?

Regards,
Michiel Salters

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: AlbertoBarbati@libero.it (Alberto Barbati)
Date: Sat, 3 Jul 2004 01:23:05 +0000 (UTC)
Raw View
Sergiy Kanilo wrote:
> "Scott Meyers" <Usenet@aristeia.com> wrote in message
> news:MPG.1b4dd2218cba25ee98975f@news.hevanet.com...
>
>>Dependent type names must always be preceded by "typename", right?  So
>>consider:
>>
>>  template<typename T>
>>  void foo()
>>  {
>>    if (typeid(std::list<T>::iterator) == typeid(int));
>>  }
>>
>>gcc 3.2 issues a warning about the lack of "typename" in front of
>>std::list<T>::iterator, but VC7.1 and Comeau 4.3.3 accept the code without
>>complaint.  Is there something special going on here, are VC7.1 and Comeau
>>simply wrong, or is my understanding of typename and dependent names
>>wanting?
>
>
> 14.6.2.2
> /4 Expressions of the following forms are never type-dependent
> ..
> typeid ( expression )
> typeid ( typeid )
> ..
>

This is irrelevant to OP question, which relates only to the argument of
the typeid operator only, not to the entire typeid(...) expression.

The meaning of 14.6.2.2 is simply that a typeid(...) expression is never
dependent even if it may have a dependent subexpression (its argument,
in this case). That's fairly obvious because the type of the whole
expression is type_info whatever the argument is.

According to 14.6/2 and 14.6/3 the typename keyword is required, so I
believe that gcc is right and the others is wrong. Even if a compiler
adopted a relaxed parsing rule, the typename keyword cannot be avoided
in such context, as the argument of typeid is allowed to be an
expression. Consider the expression:

   typeid(mytemplate<T>::mytype*)

without the typename keyword, the compiler must assume that mytype is
*not* a type and so the subsequent "*" is to be interpreted as a
multiplication operator, resulting in a syntax error because of the
missing right operand. Instead, with the typename keyword, the "*" is
interpred as part of the type-id.

Alberto

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Usenet@aristeia.com (Scott Meyers)
Date: Sat, 3 Jul 2004 02:17:04 +0000 (UTC)
Raw View
On Sat, 3 Jul 2004 00:03:49 +0000 (UTC), Michiel Salters wrote:
> Let's write a similar example
>
> template<typename T>
> class A {
>   typedef T* iterator;
> };
> template< >
> class A<void> {
>   static const iterator = 0;
> };
> template< typename T>
> void foo()
> {
>   if(typeid(A<T>::iterator) == typeid(int));
> }
>
> Should A<T>::iterator be typename A<T>::iterator instead?

If, as author of foo, I believe that A<T>::iterator will be a type, yes.
If I believe that A<T>::iterator will not be a type, I should not.

I understand your point, but the whole idea behind typename is for the
author of a template to tell the compiler when something ambiguous is the
name of a type.  In the particular example I posted, list<T>::iterator is
the name of a type, so my belief is that I should have to say that.

For the error to be manifest, the template must be instantiated, so
here's a complete program (less #includes):

   template<typename T>
   void foo()
   {
     if (typeid(std::list<T>::iterator) == typeid(int));
   }

   int main()
   {
     foo<int>();
   }

This causes instantiation of foo<int>, which refers to
std::list<int>::iterator, which is a type.  It should thus be preceded by
typename.  It's not, and I believe that that is an error.  As I reported
before, VC7.1 and Comeau 4.3.3 accept the code silently.  Gcc 3.2 issues a
warning.

Scott

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Sat, 3 Jul 2004 22:04:17 +0000 (UTC)
Raw View
Usenet@aristeia.com (Scott Meyers) writes:

| I understand your point, but the whole idea behind typename is for the
| author of a template to tell the compiler when something ambiguous is the
| name of a type.

The whole idea behind "typename" is to accomodate parser internals. :-)

--
                                                        Gabriel Dos Reis
                                                         gdr@cs.tamu.edu
  Texas A&M University -- Computer Science Department
 301, Bright Building -- College Station, TX 77843-3112

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Scott Meyers <Usenet@aristeia.com>
Date: Thu, 1 Jul 2004 13:57:11 CST
Raw View
Dependent type names must always be preceded by "typename", right?  So
consider:

  template<typename T>
  void foo()
  {
    if (typeid(std::list<T>::iterator) == typeid(int));
  }

gcc 3.2 issues a warning about the lack of "typename" in front of
std::list<T>::iterator, but VC7.1 and Comeau 4.3.3 accept the code without
complaint.  Is there something special going on here, are VC7.1 and Comeau
simply wrong, or is my understanding of typename and dependent names
wanting?

Thanks,

Scott

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Sergiy Kanilo" <skanilo@artannlabs.com>
Date: 1 Jul 2004 21:25:14 GMT
Raw View
"Scott Meyers" <Usenet@aristeia.com> wrote in message
news:MPG.1b4dd2218cba25ee98975f@news.hevanet.com...
> Dependent type names must always be preceded by "typename", right?  So
> consider:
>
>   template<typename T>
>   void foo()
>   {
>     if (typeid(std::list<T>::iterator) == typeid(int));
>   }
>
> gcc 3.2 issues a warning about the lack of "typename" in front of
> std::list<T>::iterator, but VC7.1 and Comeau 4.3.3 accept the code without
> complaint.  Is there something special going on here, are VC7.1 and Comeau
> simply wrong, or is my understanding of typename and dependent names
> wanting?

14.6.2.2
/4 Expressions of the following forms are never type-dependent
..
typeid ( expression )
typeid ( typeid )
..

Cheers,
Serge


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Scott Meyers <Usenet@aristeia.com>
Date: 1 Jul 2004 23:45:05 GMT
Raw View
On 1 Jul 2004 21:25:14 GMT, Sergiy Kanilo wrote:
> 14.6.2.2
> /4 Expressions of the following forms are never type-dependent
> ..
> typeid ( expression )
> typeid ( typeid )
> ..

That may be true, but I don't see anything in that section that overrules
14.6/2:

  A name used in a template declaration or definition and that is dependent
  on a template-parameter is assumed not to name a type unless the
  applicable name lookup finds a type name or the name is qualified by the
  keyword typename.

On the other hand, I don't understand the significance of type-dependent
expressions (14.6.2.2), and they're surely defined for a reason.

Scott

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Fri, 2 Jul 2004 15:12:01 +0000 (UTC)
Raw View
Scott Meyers wrote:
> Dependent type names must always be preceded by "typename", right?  So
> consider:
>
>   template<typename T> void foo()
>   { if (typeid(std::list<T>::iterator) == typeid(int)); }
>
> gcc 3.2 issues a warning about the lack of "typename" in front of
> std::list<T>::iterator, but VC7.1 and Comeau 4.3.3 accept the code without
> complaint.  Is there something special going on here, are VC7.1 and Comeau
> simply wrong, or is my understanding of typename and dependent names
> wanting?

If you leave out the typename, then the dependent name is assumed
to not be a type. But it's perfectly OK to take typeid of non-types!
Now, 14.6/3 says that a dependent name which denotes a type "shall"
be preceeded by typename, so this imposes a requirement on you.
Further, 14.6/4 says that if you did use typename but the name is
not a type, the program is ill-formed. But it does not say that for
the converse case, where you did not use a typename but the name is
a type. So the compilers are perfectly within their rights to say
nothing and just accept the code. That's my analysis.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Fri, 2 Jul 2004 15:14:14 +0000 (UTC)
Raw View
Scott Meyers <Usenet@aristeia.com> writes:

> Dependent type names must always be preceded by "typename", right?

Almost.  Not in base class lists and a few other places, like
qualified non-dependent names inside a template (allowed but not
required) and typename is forbidden on unqualified names like
"pair<int,T>" and on explicit template specializations.  There's an
appendix that explains all this stuff in the appendix of "C++ Template
Metaprogramming", to which you have access.

> So
> consider:
>
>   template<typename T>
>   void foo()
>   {
>     if (typeid(std::list<T>::iterator) == typeid(int));
>   }
>
> gcc 3.2 issues a warning about the lack of "typename" in front of
> std::list<T>::iterator, but VC7.1 and Comeau 4.3.3 accept the code without
> complaint.  Is there something special going on here, are VC7.1 and Comeau
> simply wrong, or is my understanding of typename and dependent names
> wanting?

Recall what typeid is about: it helps the parser distinguish the names
of types from those of objects.  At the point foo is parsed, the
compiler doesn't know whether std::list<X> is defined this way:

   template <>
   struct list<X>
   {
      typedef int iterator; // a type
      ...
   };

or this way:

   template <>
   struct list<X>
   {
      static int iterator; // an object
      ...
   };

Even though the compiler has seen the primary template, a
specialization could come along later and change the meaning of
std::list<X>::iterator for any given X.  It so happens that typeid
works on both types and on expressions, so either one would be
valid.

Comeau doesn't seem to warn if you instantiate foo<int> later either,
but that's because EDG only uses the first phase of template
compilation (the one where typename takes effect) to issue
diagnostics.  In order to maintain a "broken compiler with only
one-phase lookup" mode they have to be able to do all the work at the
point of instantiation anyway, so that's what they always do.  If they
were saving the parse tree from phase 1 you'd get an error at
instantiation time when std::list<T>::iterator turned out to be a
type.

HTH,

--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Fri, 2 Jul 2004 19:48:04 +0000 (UTC)
Raw View
"Sergiy Kanilo" <skanilo@artannlabs.com> writes:

> 14.6.2.2
> /4 Expressions of the following forms are never type-dependent
> ..
> typeid ( expression )
> typeid ( typeid )
> ..
>
> Cheers,
> Serge

True, but irrelevant IMO.  The fact that typeid( xxxx ) is not
type-dependent doesn't mean that xxxx itself isn't type-dependent.
The situation is no different from:

    template <class T>
    struct foo
    {
        enum { value = sizeof(typename std::list<int>::iterator) };
    };

Where typename is indeed required.

--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: skanilo@artannlabs.com ("Sergiy Kanilo")
Date: Fri, 2 Jul 2004 19:48:21 +0000 (UTC)
Raw View
"Scott Meyers" <Usenet@aristeia.com> wrote in message
news:MPG.1b4e3c0463c81af0989760@news.hevanet.com...
> On 1 Jul 2004 21:25:14 GMT, Sergiy Kanilo wrote:
> > 14.6.2.2
> > /4 Expressions of the following forms are never type-dependent
> > ..
> > typeid ( expression )
> > typeid ( typeid )
> > ..
>
> That may be true, but I don't see anything in that section that overrules
> 14.6/2:
>
>   A name used in a template declaration or definition and that is
dependent
>   on a template-parameter is assumed not to name a type unless the
>   applicable name lookup finds a type name or the name is qualified by the
>   keyword typename.
>
> On the other hand, I don't understand the significance of type-dependent
> expressions (14.6.2.2), and they're surely defined for a reason.

Yes, I probably misinterpreted 14.6.2 /1 :(

In your code dependent name could be name of type or name of value,
and construction is syntactically correct in either case.
There are several other examples

int q=0;
template<typename T> void h();
template<int I> void h();

template<typename T>
void f(){   T::f(q);  }

template<typename T>
int g(){  return (T::f)-1; }

struct A {
  typedef int f;
};

struct B {
  static int f(int);
};

struct C {
  static int const f =1;
};

template<typename T>
void e()
{
  h<T::f>();
}

int main() {
  f<A>();
  f<B>();
  g<A>();
  g<C>();
  e<A>();
  e<C>();
}

Cheers,
Serge


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]