Topic: Typename keyword for return value


Author: "Michel Michaud" <micm19@removethis.mail2.cstjean.qc.ca>
Date: 1998/10/21
Raw View
Jerry Leichter wrote:
>
> | ... Anyway I can bite the bullet and add typename everywhere. I do
> | like uniformity...
>
> Prepare to be disappointed.  When it comes to type names, there are
> three kinds of contexts in the standard:
>
>    1. Those where typename before the name of a type is required;
>    2. Those where typename before the name of a type is optional;
>    3. Those where typename before the name of a type is forbidden.
I'm not sure about the rest of your post, but let me be more
specific : I can use typename before member types in templates... for
a start, that's not really everywhere!

[...]

> While these kinds of things are of trivial import for class (and struct
> and enum), if something like this had been done for typename, it would
> have been possible to remove an annoying context-dependency that C++
> long ago inherited from C:  *If* you write your code with typename
> before everything that is indeed a type name, then you can write easier
> tools to analyze your code, and all kinds of potential ambiguities that
> are resolved in difficult-to-see fashions go away.

Are we talking about templates here? Are you saying this is
correct (no typename needed, in fact they would be prohibited):

template <typename T>
class T::something Function(class T::somethingelse s)
{
class T::anothertype* p;
//...
}

If this is what you're saying, the need for typename as a new
keyword is very weak, as class could well have been interpreted
as "any type" like in template <class T>. Or would it be that
in the context of this template, class would forbid "something"
"somethingelse", "anothertype" to be struct or built-in types?

This dirt is getting muddier by the minute...
--
Michel Michaud (micm19@removethis.mail2.cstjean.qc.ca)
http://www3.sympatico.ca/michel.michaud
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: ncm@nospam.cantrip.org (Nathan Myers)
Date: 1998/10/16
Raw View
Michel Michaud<micm19@removethis.mail2.cstjean.qc.ca> wrote:
>
>Consider the following template function (disregarding any
>problems with the logic or design):
>
>template <typename C>
>C::value_type SmallestOf(const C& c);
>
>... is it necessary to add typename before the return
>[type]? Like:
>
>template <typename C>
>typename C::value_type SmallestOf(const C& c);

Yes, "typename" is required here.  The language grammar is not
even smart enough to allow you to leave it off in typedef
statements, never mind function declarations.  (Some compilers
are a bit smarter than the grammar, but warn about it missing
from typedef statements because such code's not portable.)

--
Nathan Myers
ncm@nospam.cantrip.org  http://www.cantrip.org/
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Michel Michaud <m.michaud@cstjean.qc.ca>
Date: 1998/10/16
Raw View
Nathan Myers wrote:

> Michel Michaud<micm19@removethis.mail2.cstjean.qc.ca> wrote:
> >
> >... is it necessary to add typename before the return
> >[type]? Like:
> >
> >template <typename C>
> >typename C::value_type SmallestOf(const C& c);

> Yes, "typename" is required here.  The language grammar is not
> even smart enough to allow you to leave it off in typedef
> statements, never mind function declarations.  (Some compilers
> are a bit smarter than the grammar, but warn about it missing
> from typedef statements because such code's not portable.)

I can understand the rule but why is it so? Surely it is possible
to write a smarter compiler, so why isn't it the rule? I can
see many other places where we need a smart compiler, much
smarter than knowing that a typedef needs a type!

The only answer seems to be uniformity. At least we would have
it in one place in C++! That leaves only a few hundred places
where we don't have it... :)

Michel Michaud micm19@removethis.mail2.cstjean.qc.cq
http://www3.sympatico.ca/michel.michaud


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Michel Michaud <m.michaud@cstjean.qc.ca>
Date: 1998/10/17
Raw View
Steve Clamage wrote:
>
> "Michel Michaud" <micm19@removethis.mail2.cstjean.qc.ca> writes:
>
> >template <typename C>
> >C::value_type SmallestOf(const C& c)
> >    {
> >    typename C::const_iterator it= c.begin();
> >    typename C::const_iterator itSmall= it;
> >    while (++it != c.end())
> >        if (*it < *itSmall) itSmall= it;
> >    return *itSmall; // c must not be empty...
> >    }
>
> >I do understand the need for "typename" in the declaration
> >of it and itSmall, A Standard conforming compiler should
> >interpret C::const_iterator as a non-type without it.
>
> No, the compiler must reject the code.
Don't you mean "Yes, and in this case it will reject the code" ?

The "classic" example is

C::something*var;

where it is not an error IF C::something is a member variable.
So the template would be parsed without error...

> > But then, is it necessary to add typename before the return
> >value? Like:
>
> >template <typename C>
> >typename C::value_type SmallestOf(const C& c)
> >....
>
> Yes.  The rule is that a name that depends on a template parameter
> is not a type unless it is declared to be a type with "typename".
> Without the "typename", the compiler must assume C::value_type is
> not the name of a type. (See 14.6 "Name resolution" in the final
> standard. Details have changed since CD2.)
Is there a specific example of this (as return type)? Because
(see my other post) I don't see the rational of it. It won't
help the compiler in any way, but it will fool most programmers!

Michel Michaud micm19@removethis.mail2.cstjean.qc.ca
http://www3.sympatico.ca/michel.michaud
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1998/10/19
Raw View
Michel Michaud <m.michaud@cstjean.qc.ca> writes:

>Steve Clamage wrote:

>> "Michel Michaud" <micm19@removethis.mail2.cstjean.qc.ca> writes:

>> >template <typename C>
>> >C::value_type SmallestOf(const C& c)
>> >    {
>> >    typename C::const_iterator it= c.begin();
>> >    typename C::const_iterator itSmall= it;
>> >    while (++it != c.end())
>> >        if (*it < *itSmall) itSmall= it;
>> >    return *itSmall; // c must not be empty...
>> >    }

>> >I do understand the need for "typename" in the declaration
>> >of it and itSmall, A Standard conforming compiler should
>> >interpret C::const_iterator as a non-type without it.
>>
>> No, the compiler must reject the code.

>Don't you mean "Yes, and in this case it will reject the code" ?

Um, I meant to say "Yes, and the compiler in this case must
issue a diagnostic message." Compilers are not required to
reject code; they are required to complain about invalid
code. :-)

>> Yes.  The rule is that a name that depends on a template parameter
>> is not a type unless it is declared to be a type with "typename".
>> Without the "typename", the compiler must assume C::value_type is
>> not the name of a type. (See 14.6 "Name resolution" in the final
>> standard. Details have changed since CD2.)

>Is there a specific example of this (as return type)? Because
>(see my other post) I don't see the rational of it. It won't
>help the compiler in any way, but it will fool most programmers!

As I explained elsewhere, the compiler doesn't need typename
at all. But to enable detection of common sorts of errors
in the template code itself, the compiler at a minimum
needs to know which names are type names.

The compiler can't figure out it's looking at the return type of
a function declaration unless it knows the name is indeed the name
of a type. Example:
 A B ( C ) ;
If A and C are types, we have a declaration of function B.
If A is a type and C is not, we have a definition of object B
of type A, initialized with value C.
If A is not a type, the code is invalid.

It's very hard for a compiler to report an error and continue
parsing when it doesn't know what it's looking at. The purpose
of adding "typename" was to enable some error detection in template
code before instantiation.  Hence, the simple rule that a name
is not a type name unless it is somehow declared to be a type name.

--
Steve Clamage, stephen.clamage@sun.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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Michel Michaud" <micm19@removethis.mail2.cstjean.qc.ca>
Date: 1998/10/19
Raw View
Steve Clamage wrote in <70e717$4e4$1@engnews1.eng.sun.com>...
>It's very hard for a compiler to report an error and continue
>parsing when it doesn't know what it's looking at. The purpose
>of adding "typename" was to enable some error detection in template
>code before instantiation.  Hence, the simple rule that a name


Well!!! that's quite different than the reason I had in mind. I
though typename was there so programmers could force something
to be a type, so that if by mistake a name refer to a member
instead of a type, the compiler would catch it -AT- instantiation
even if it would be syntactically valid. I'm quite sure I didn't
think of this myself. I'll have to reread all my books to find out
who told me that!

Anyway I can bite the bullet and add typename everywhere. I
do like uniformity... I just hope I will get a compiler to
accept it soon...

Michel Michaud micm19@removethis.mail2.cstjean.qc.ca
http://www3.sympatico.ca/michel.michaud



[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Jerry Leichter <leichter@smarts.com>
Date: 1998/10/20
Raw View
| ... Anyway I can bite the bullet and add typename everywhere. I do
| like uniformity...

Prepare to be disappointed.  When it comes to type names, there are
three kinds of contexts in the standard:

 1. Those where typename before the name of a type is required;
 2. Those where typename before the name of a type is optional;
 3. Those where typename before the name of a type is forbidden.

In this way, if follows that tradition of "class" or "struct".  At least
for those (well, for struct, but you wouldn't want struct and class to
have different rules), the existence of contexts of at least types 1 and
2 was necessary for backwards-compatibility with C, since the type 2
contexts arose from adding what is, in effect, an implicit typedef for T
whenever struct or class T is declared.  However, there was never a
*need* for contexts of type 3 - code like:

 class A::class A(class A& other) { ... }

or even

 typedef class CommonName class AlternateName;

my look weird but it's unambiguous.  You might need to allow parentheses
to disambiguate things for nested classes:

 (class A)::B vs. class (A::B)

(in the first, A is asserted to be a class, but B might or might not be
a class; in the latter, A might be a class or a namespace, but B is
asserted to be a class.)

While these kinds of things are of trivial import for class (and struct
and enum), if something like this had been done for typename, it would
have been possible to remove an annoying context-dependency that C++
long ago inherited from C:  *If* you write your code with typename
before everything that is indeed a type name, then you can write easier
tools to analyze your code, and all kinds of potential ambiguities that
are resolved in difficult-to-see fashions go away.

*Would* anyone write code this way?  I don't know, but we'll never find
out. since the standard as written makes such a style impossible.  Keep
in mind that there are people seriously proposing that all references to
members be preceeded with an explicit "this->", exactly to avoid
ambiguities and unexpected interpretations.  Since a method or variable
is likely to be referred to many more times than it is declared, you're
going to by typing "this->" much more often than you'd be typing
"typename".
       -- Jerry


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Michel Michaud" <micm19@removethis.mail2.cstjean.qc.ca>
Date: 1998/10/14
Raw View
Consider the following template function (disregarding any
problems with the logic or design):

template <typename C>
C::value_type SmallestOf(const C& c)
    {
    typename C::const_iterator it= c.begin();
    typename C::const_iterator itSmall= it;
    while (++it != c.end())
        if (*it < *itSmall) itSmall= it;
    return *itSmall; // c must not be empty...
    }

I do understand the need for "typename" in the declaration
of it and itSmall, A Standard conforming compiler should
interpret C::const_iterator as a non-type without it. But
then, is it necessary to add typename before the return
value? Like:

template <typename C>
typename C::value_type SmallestOf(const C& c)
....

VC 5 does not like that! But as it does not need the
two others either, I tried CD2 (I don't have my copy
of the standard yet, it is coming), Stroustrup, etc.
but there is no such example, and the text may not be
clear (to me it seems it would be necessary).

If it not necessary, because the compiler may
understand that the return value is always a type, then
this comes down to why typename is mandatory (at
least in the function) even when the compiler could
understand that the identifier is a type. Is the
compiler supposed to get dumber when it gets inside
the function?

Any idea?

Michel Michaud micm19@removethis.mail2.cstjean.qc.ca
http://www3.sympatico.ca/michel.michaud




[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Michel Michaud <micm19@removethis.mail2.cstjean.qc.ca>
Date: 1998/10/15
Raw View
I think I understand better now, so I guess typename would not
be necessary for the return value because it would not add
anything. The use of typename is to help the compiler catch
errors that would otherwise go unnoticed. But if the return
value is not a type it will be caugth by the compiler anyway.
Inside the function, in some rare cases, a type would have
different (valid) semantic than a value so the compiler would
not catch the error.

Now the question become, is typename valid (for uniformity)
for the return value? And why is typename mandatory even
if there is no way something could be interpreted other
than a type? (for uniformity?!)

--
Michel Michaud (micm19@removethis.mail2.cstjean.qc.ca)
http://www3.sympatico.ca/michel.michaud

Michel Michaud wrote :

> Consider the following template function (disregarding any
> problems with the logic or design):

> template <typename C>
> C::value_type SmallestOf(const C& c)
>     {
>     typename C::const_iterator it= c.begin();
>     typename C::const_iterator itSmall= it;
>     while (++it != c.end())
>         if (*it < *itSmall) itSmall= it;
>     return *itSmall; // c must not be empty...
>     }

> I do understand the need for "typename" in the declaration
> of it and itSmall, A Standard conforming compiler should
> interpret C::const_iterator as a non-type without it. But
> then, is it necessary to add typename before the return
> value? Like:

> template <typename C>
> typename C::value_type SmallestOf(const C& c)
> ....

> VC 5 does not like that! But as it does not need the
> two others either, I tried CD2 (I don't have my copy
> of the standard yet, it is coming), Stroustrup, etc.
> but there is no such example, and the text may not be
> clear (to me it seems it would be necessary).

> If it not necessary, because the compiler may
> understand that the return value is always a type, then
> this comes down to why typename is mandatory (at
> least in the function) even when the compiler could
> understand that the identifier is a type. Is the
> compiler supposed to get dumber when it gets inside
> the function?

> Any idea?


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1998/10/16
Raw View
"Michel Michaud" <micm19@removethis.mail2.cstjean.qc.ca> writes:

>template <typename C>
>C::value_type SmallestOf(const C& c)
>    {
>    typename C::const_iterator it= c.begin();
>    typename C::const_iterator itSmall= it;
>    while (++it != c.end())
>        if (*it < *itSmall) itSmall= it;
>    return *itSmall; // c must not be empty...
>    }

>I do understand the need for "typename" in the declaration
>of it and itSmall, A Standard conforming compiler should
>interpret C::const_iterator as a non-type without it.

No, the compiler must reject the code.

> But then, is it necessary to add typename before the return
>value? Like:

>template <typename C>
>typename C::value_type SmallestOf(const C& c)
>....

Yes.  The rule is that a name that depends on a template parameter
is not a type unless it is declared to be a type with "typename".
Without the "typename", the compiler must assume C::value_type is
not the name of a type. (See 14.6 "Name resolution" in the final
standard. Details have changed since CD2.)


>VC 5 does not like that! But as it does not need the
>two others either,

That just means it is not fully implementing the rules about
typename in the final standard. Not surprising, since VC5
came out before the standard, and in any event Microsoft is
not yet attempting to fulfill all requirements of the standard.

--
Steve Clamage, stephen.clamage@sun.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://reality.sgi.com/austern_mti/std-c++/faq.html              ]