[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

Returning nested class within template class from member function.

jason.cipriani@gmail.com

12/2/2008 3:52:00 AM

I have some code like this that won't compile:

template <typename T> class MyClass {
public:
class Nested { };
Nested f ();
};

template <typename T> MyClass<T>::Nested f () { // <---problem
return Nested();
}

"Nested" is a non-template class, nested inside the template class
"MyClass". The MyClass member function f() returns a "Nested", and is
defined outside of the class declaration. I receive the following
error from Comeau (and similar errors from other compilers):

"ComeauTest.c", line 7: error: nontype "MyClass<T>::Nested [with T=T]"
is not a
type name
template <typename T> MyClass<T>::Nested f () {

What is the correct syntax to use here? I can't figure out how to make
this work (or if it's just not possible). Putting the definition of f
() right in the class declaration does work fine, but I'd like to keep
it outside, but mostly I'm curious about the syntax.

Thanks,
JC
19 Answers

jason.cipriani@gmail.com

12/2/2008 4:43:00 AM

0

On Dec 1, 10:52 pm, "jason.cipri...@gmail.com"
<jason.cipri...@gmail.com> wrote:
> I have some code like this that won't compile:
>
> template <typename T> class MyClass {
> public:
>         class Nested { };
>         Nested f ();
>
> };
>
> template <typename T> MyClass<T>::Nested f () { // <---problem
>         return Nested();
>
> }
>
> "Nested" is a non-template class, nested inside the template class
> "MyClass". The MyClass member function f() returns a "Nested", and is
> defined outside of the class declaration. I receive the following
> error from Comeau (and similar errors from other compilers):
>
> "ComeauTest.c", line 7: error: nontype "MyClass<T>::Nested [with T=T]"
> is not a
>           type name
>   template <typename T> MyClass<T>::Nested f () {
>
> What is the correct syntax to use here? I can't figure out how to make
> this work (or if it's just not possible). Putting the definition of f
> () right in the class declaration does work fine, but I'd like to keep
> it outside, but mostly I'm curious about the syntax.

Oops, I totally screwed that up! Forgot the "MyClass<T>::" before "f
()"... I got it figured out. This is correct:

template <typename T> MyClass<T>::Nested MyClass<T>::f () {
return Nested();
}

All right, but now that I've fixed *my* stupid mistake, Comeau
compiles it fine, except MS's VC++ 2008 compiler choked on it:

1>warning C4346: 'MyClass<T>::Nested' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>error C2143: syntax error : missing ';' before 'MyClass<T>::f'

But adding a "typename" in the middle there made it happy for some
reason:

template <typename T> typename MyClass<T>::Nested MyClass<T>::f () {
return Nested();
}

Jason






> Thanks,
> JC

Hendrik Schober

12/2/2008 8:18:00 AM

0

jason.cipriani@gmail.com wrote:
> [...]
> All right, but now that I've fixed *my* stupid mistake, Comeau
> compiles it fine, except MS's VC++ 2008 compiler choked on it:
>
> 1>warning C4346: 'MyClass<T>::Nested' : dependent name is not a type
> 1> prefix with 'typename' to indicate a type
> 1>error C2143: syntax error : missing ';' before 'MyClass<T>::f'
>
> But adding a "typename" in the middle there made it happy for some
> reason:
>
> template <typename T> typename MyClass<T>::Nested MyClass<T>::f () {
> return Nested();
> }

I'd say the 'typename' is necessary ('Nested' is a nested identifier
depending on a template parameter, after all), but this seems to
counter all my experience regarding whether Comeau or VC is right,
whenever they disagree.
Am I wrong here, or would this really be a bug in Comeau??

> Jason

Schobi

olekk

12/2/2008 8:47:00 AM

0



jason.cipriani@gmail.com wrote:
> On Dec 1, 10:52?pm, "jason.cipri...@gmail.com"
> <jason.cipri...@gmail.com> wrote:
> > I have some code like this that won't compile:
> >
> > template <typename T> class MyClass {
> > public:
> > ? ? ? ? class Nested { };
> > ? ? ? ? Nested f ();
> >
> > };
> >
> > template <typename T> MyClass<T>::Nested f () { // <---problem
> > ? ? ? ? return Nested();
> >
> > }
> >
> > "Nested" is a non-template class, nested inside the template class
> > "MyClass". The MyClass member function f() returns a "Nested", and is
> > defined outside of the class declaration. I receive the following
> > error from Comeau (and similar errors from other compilers):
> >
> > "ComeauTest.c", line 7: error: nontype "MyClass<T>::Nested [with T=T]"
> > is not a
> > ? ? ? ? ? type name
> > ? template <typename T> MyClass<T>::Nested f () {
> >
> > What is the correct syntax to use here? I can't figure out how to make
> > this work (or if it's just not possible). Putting the definition of f
> > () right in the class declaration does work fine, but I'd like to keep
> > it outside, but mostly I'm curious about the syntax.
>
> Oops, I totally screwed that up! Forgot the "MyClass<T>::" before "f
> ()"... I got it figured out. This is correct:
>
> template <typename T> MyClass<T>::Nested MyClass<T>::f () {
> return Nested();
> }
>
> All right, but now that I've fixed *my* stupid mistake, Comeau
> compiles it fine, except MS's VC++ 2008 compiler choked on it:
>
> 1>warning C4346: 'MyClass<T>::Nested' : dependent name is not a type
> 1> prefix with 'typename' to indicate a type
> 1>error C2143: syntax error : missing ';' before 'MyClass<T>::f'
>
> But adding a "typename" in the middle there made it happy for some
> reason:
>
> template <typename T> typename MyClass<T>::Nested MyClass<T>::f () {
> return Nested();
> }

As compiler informs you - MyClass<T>::Nested is dependent name and
should be prefixed with typename keyword

template <typename T> typename MyClass<T>::Nested MyClass<T>::f () {
return Nested();
}

Regards

Triple-DES

12/2/2008 10:09:00 AM

0

On 2 Des, 09:18, Hendrik Schober <spamt...@gmx.de> wrote:
> jason.cipri...@gmail.com wrote:
> > [...]
> > All right, but now that I've fixed *my* stupid mistake, Comeau
> > compiles it fine, except MS's VC++ 2008 compiler choked on it:
>
> > 1>warning C4346: 'MyClass<T>::Nested' : dependent name is not a type
> > 1>        prefix with 'typename' to indicate a type
> > 1>error C2143: syntax error : missing ';' before 'MyClass<T>::f'
>
> > But adding a "typename" in the middle there made it happy for some
> > reason:
>
> > template <typename T> typename MyClass<T>::Nested MyClass<T>::f () {
> >    return Nested();
> > }
>
>   I'd say the 'typename' is necessary ('Nested' is a nested identifier
>   depending on a template parameter, after all), but this seems to
>   counter all my experience regarding whether Comeau or VC is right,
>   whenever they disagree.
>   Am I wrong here, or would this really be a bug in Comeau??

Yes, typename is required here (14.6/3), so it would be non-conformant
to compile this without a diagnostic.

James Kanze

12/2/2008 1:31:00 PM

0

On Dec 2, 9:18 am, Hendrik Schober <spamt...@gmx.de> wrote:
> jason.cipri...@gmail.com wrote:
> > [...]
> > All right, but now that I've fixed *my* stupid mistake,
> > Comeau compiles it fine, except MS's VC++ 2008 compiler
> > choked on it:

> > 1>warning C4346: 'MyClass<T>::Nested' : dependent name is not a type
> > 1> prefix with 'typename' to indicate a type
> > 1>error C2143: syntax error : missing ';' before 'MyClass<T>::f'

> > But adding a "typename" in the middle there made it happy
> > for some reason:

> > template <typename T> typename MyClass<T>::Nested MyClass<T>::f () {
> > return Nested();
> > }

> I'd say the 'typename' is necessary ('Nested' is a nested
> identifier depending on a template parameter, after all),
> but this seems to counter all my experience regarding
> whether Comeau or VC is right, whenever they disagree.

> Am I wrong here, or would this really be a bug in Comeau??

Check the options it was invoked with. Comeau is a very
professional product, which means that it doesn't go around
breaking existing code if it can help it. So it almost
certainly has modes which accept this code, and others which
don't.

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Hendrik Schober

12/2/2008 2:33:00 PM

0

James Kanze wrote:
> On Dec 2, 9:18 am, Hendrik Schober <spamt...@gmx.de> wrote:
>> jason.cipri...@gmail.com wrote:
>>> [...]
>>> All right, but now that I've fixed *my* stupid mistake,
>>> Comeau compiles it fine, except MS's VC++ 2008 compiler
>>> choked on it:
>
>>> 1>warning C4346: 'MyClass<T>::Nested' : dependent name is not a type
>>> 1> prefix with 'typename' to indicate a type
>>> 1>error C2143: syntax error : missing ';' before 'MyClass<T>::f'
>
>>> But adding a "typename" in the middle there made it happy
>>> for some reason:
>
>>> template <typename T> typename MyClass<T>::Nested MyClass<T>::f () {
>>> return Nested();
>>> }
>
>> I'd say the 'typename' is necessary ('Nested' is a nested
>> identifier depending on a template parameter, after all),
>> but this seems to counter all my experience regarding
>> whether Comeau or VC is right, whenever they disagree.
>
>> Am I wrong here, or would this really be a bug in Comeau??
>
> Check the options it was invoked with. Comeau is a very
> professional product, which means that it doesn't go around
> breaking existing code if it can help it. So it almost
> certainly has modes which accept this code, and others which
> don't.

Good thought, however, it does accept this

template <typename T> class MyClass {
public:
class Nested { };
Nested f ();
};

template <typename T> MyClass<T>::Nested MyClass<T>::f()
{
return Nested();
}

as

Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ noC++0x_extensions

so it seems indeed this is a bug in Comeau.

Schobi

jason.cipriani@gmail.com

12/3/2008 12:27:00 AM

0

On Dec 2, 9:33 am, Hendrik Schober <spamt...@gmx.de> wrote:
> James Kanze wrote:
> > On Dec 2, 9:18 am, Hendrik Schober <spamt...@gmx.de> wrote:
> >>jason.cipri...@gmail.com wrote:
> >>> [...]
> >>> All right, but now that I've fixed *my* stupid mistake,
> >>> Comeau compiles it fine, except MS's VC++ 2008 compiler
> >>> choked on it:
>
> >>> 1>warning C4346: 'MyClass<T>::Nested' : dependent name is not a type
> >>> 1>        prefix with 'typename' to indicate a type
> >>> 1>error C2143: syntax error : missing ';' before 'MyClass<T>::f'
>
> >>> But adding a "typename" in the middle there made it happy
> >>> for some reason:
>
> >>> template <typename T> typename MyClass<T>::Nested MyClass<T>::f () {
> >>>    return Nested();
> >>> }
>
> >>   I'd say the 'typename' is necessary ('Nested' is a nested
> >>   identifier depending on a template parameter, after all),
> >>   but this seems to counter all my experience regarding
> >>   whether Comeau or VC is right, whenever they disagree.
>
> >>   Am I wrong here, or would this really be a bug in Comeau??
>
> > Check the options it was invoked with.  Comeau is a very
> > professional product, which means that it doesn't go around
> > breaking existing code if it can help it.  So it almost
> > certainly has modes which accept this code, and others which
> > don't.
>
>   Good thought, however, it does accept this
>
>     template <typename T> class MyClass {
>     public:
>       class Nested { };
>       Nested f ();
>     };
>
>     template <typename T> MyClass<T>::Nested MyClass<T>::f()
>     {
>       return Nested();
>     }
>
>   as
>
>     Comeau C/C++ 4.3.10.1 (Oct  6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
>     Copyright 1988-2008 Comeau Computing.  All rights reserved.
>     MODE:strict errors C++ noC++0x_extensions
>
>   so it seems indeed this is a bug in Comeau.

Weird, I just immediately assumed that VS was the broken one. I did
not try with any other compiler besides VS and Comeau. I will report
the bug to Comeau and see what they say.

Jason

James Kanze

12/3/2008 9:15:00 AM

0

On Dec 2, 3:33 pm, Hendrik Schober <spamt...@gmx.de> wrote:
> James Kanze wrote:
> > On Dec 2, 9:18 am, Hendrik Schober <spamt...@gmx.de> wrote:
> >> jason.cipri...@gmail.com wrote:
> >>> [...]
> >>> All right, but now that I've fixed *my* stupid mistake,
> >>> Comeau compiles it fine, except MS's VC++ 2008 compiler
> >>> choked on it:

> >>> 1>warning C4346: 'MyClass<T>::Nested' : dependent name is not a type
> >>> 1> prefix with 'typename' to indicate a type
> >>> 1>error C2143: syntax error : missing ';' before 'MyClass<T>::f'

> >>> But adding a "typename" in the middle there made it happy
> >>> for some reason:

> >>> template <typename T> typename MyClass<T>::Nested MyClass<T>::f () {
> >>> return Nested();
> >>> }

> >> I'd say the 'typename' is necessary ('Nested' is a nested
> >> identifier depending on a template parameter, after all),
> >> but this seems to counter all my experience regarding
> >> whether Comeau or VC is right, whenever they disagree.

> >> Am I wrong here, or would this really be a bug in Comeau??

> > Check the options it was invoked with. Comeau is a very
> > professional product, which means that it doesn't go around
> > breaking existing code if it can help it. So it almost
> > certainly has modes which accept this code, and others which
> > don't.

> Good thought, however, it does accept this

> template <typename T> class MyClass {
> public:
> class Nested { };
> Nested f ();
> };

> template <typename T> MyClass<T>::Nested MyClass<T>::f()
> {
> return Nested();
> }

> as

> Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
> Copyright 1988-2008 Comeau Computing. All rights reserved.
> MODE:strict errors C++ noC++0x_extensions

> so it seems indeed this is a bug in Comeau.

I don't think so. The typename here is optional, since Nested
is not a dependent name, but a locally declared name. If you
used MyClass<T>::Nested in the definition of another template,
the typename would be necessary, but not here. But IMHO, the
standard is far from clear about this. It goes into detail with
regards to when an expression is dependant, but it really
doesn't say much about names in declarations. About the only
really relevant text I can find is right at the start of §14.6,
where it says that "Three kinds of names can be used[...]", and
places names declared within the template itself in the same
category as the name of the template, i.e. locally declared. So
while Nested in MyClass<T>::Nested obviously depends on T, it
doesn't depend on T in the sense of the standard. (This makes
sense, of course, in that the compiler can easily determine that
Nested is a type; in the definition of template members, it
doesn't have to worry about specializations.)

FWIW: both g++ and Sun CC require the typename as well.

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Triple-DES

12/3/2008 11:48:00 AM

0

On 3 Des, 10:15, James Kanze <james.ka...@gmail.com> wrote:
> On Dec 2, 3:33 pm, Hendrik Schober <spamt...@gmx.de> wrote:
> > Good thought, however, it does accept this
> > template <typename T> class MyClass {
> > public:
> > class Nested { };
> > Nested f ();
> > };
> > template <typename T> MyClass<T>::Nested MyClass<T>::f()
> > {
> > return Nested();
> > }
> > as
> > Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
> > Copyright 1988-2008 Comeau Computing. All rights reserved.
> > MODE:strict errors C++ noC++0x_extensions
> > so it seems indeed this is a bug in Comeau.
>
> I don't think so. The typename here is optional, since Nested
> is not a dependent name, but a locally declared name. If you
> used MyClass<T>::Nested in the definition of another template,
> the typename would be necessary, but not here. But IMHO, the
> standard is far from clear about this. It goes into detail with
> regards to when an expression is dependant, but it really
> doesn't say much about names in declarations. About the only
> really relevant text I can find is right at the start of §14.6,
> where it says that "Three kinds of names can be used[...]", and
> places names declared within the template itself in the same
> category as the name of the template, i.e. locally declared. So
> while Nested in MyClass<T>::Nested obviously depends on T, it
> doesn't depend on T in the sense of the standard. (This makes
> sense, of course, in that the compiler can easily determine that
> Nested is a type; in the definition of template members, it
> doesn't have to worry about specializations.)

Nevertheless, even locally declared names are considered dependent if
the name is qualified, per the current standard [14.6.2.1/1],
[14.6/6].

Consider:

template <typename T>
struct MyClass
{
class Nested { };
Nested f () const; // ok
MyClass<T>::Nested f(); // ill-formed, 'typename' required
};

Note that Comeau online seems to accept this in 'strict' mode, which
is not conforming to C++03.

But according to issue 224:
The decision on whether a name is dependent or non-dependent should be
based on lookup, not on the form of the name: if the name can be
looked up in the definition context and cannot be anything else as the
result of specialization, the name should be non-dependent.

Vidar Hasfjord

12/3/2008 12:52:00 PM

0

On Dec 3, 9:15 am, James Kanze <james.ka...@gmail.com> wrote:
> On Dec 2, 3:33 pm, Hendrik Schober <spamt...@gmx.de> wrote:
> > [...]
> >     template <typename T> class MyClass {
> >     public:
> >       class Nested { };
> >       Nested f ();
> >     };
> >     template <typename T> MyClass<T>::Nested MyClass<T>::f()
> >     {
> >       return Nested();
> >     }
> >  [...]
>
> I don't think so.  The typename here is optional, since Nested
> is not a dependent name, but a locally declared name.  If you
> used MyClass<T>::Nested in the definition of another template,
> the typename would be necessary, but not here.

IOW, the member function template definition for f will only be
matched and instatiated for the MyClass base template, not any
(partial) specializations of MyClass, so the declaration of Nested is
fixed and typename should be implicit.

> But IMHO, the standard is far from clear about this.

Maybe the standard should give compilers some leeway on this. As far
as usage is concerned, requiring 'typename' here has little
consequence.

BTW, if I'm not mistaken the return part of the new C++0x style
function syntax is in the same scope as the function, and the above
can then be simplified to

template <typename T>
auto MyClass <T>::f () -> Nested {return Nested ();}

Regards,
Vidar Hasfjord