Returning nested class within template class from member function.

Discussion in 'C++' started by jason.cipriani@gmail.com, Dec 2, 2008.

  1. Guest

    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
    , Dec 2, 2008
    #1
    1. Advertising

  2. Guest

    Re: Returning nested class within template class from memberfunction.

    On Dec 1, 10:52 pm, ""
    <> 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
    , Dec 2, 2008
    #2
    1. Advertising

  3. olekk Guest

    Re: Returning nested class within template class from memberfunction.

    wrote:
    > On Dec 1, 10:52�pm, ""
    > <> 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
    olekk, Dec 2, 2008
    #3
  4. Triple-DES Guest

    Re: Returning nested class within template class from memberfunction.

    On 2 Des, 09:18, Hendrik Schober <> wrote:
    > 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.
    Triple-DES, Dec 2, 2008
    #4
  5. James Kanze Guest

    Re: Returning nested class within template class from memberfunction.

    On Dec 2, 9:18 am, Hendrik Schober <> wrote:
    > 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:
    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
    James Kanze, Dec 2, 2008
    #5
  6. Guest

    Re: Returning nested class within template class from memberfunction.

    On Dec 2, 9:33 am, Hendrik Schober <> wrote:
    > James Kanze wrote:
    > > On Dec 2, 9:18 am, Hendrik Schober <> wrote:
    > >> 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
    , Dec 3, 2008
    #6
  7. James Kanze Guest

    Re: Returning nested class within template class from memberfunction.

    On Dec 2, 3:33 pm, Hendrik Schober <> wrote:
    > James Kanze wrote:
    > > On Dec 2, 9:18 am, Hendrik Schober <> wrote:
    > >> 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:
    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
    James Kanze, Dec 3, 2008
    #7
  8. Triple-DES Guest

    Re: Returning nested class within template class from memberfunction.

    On 3 Des, 10:15, James Kanze <> wrote:
    > On Dec 2, 3:33 pm, Hendrik Schober <> 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.
    Triple-DES, Dec 3, 2008
    #8
  9. Re: Returning nested class within template class from memberfunction.

    On Dec 3, 9:15 am, James Kanze <> wrote:
    > On Dec 2, 3:33 pm, Hendrik Schober <> 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
    Vidar Hasfjord, Dec 3, 2008
    #9
  10. Guest

    Re: Returning nested class within template class from memberfunction.

    On Dec 2, 7:26 pm, ""
    <> wrote:
    > On Dec 2, 9:33 am, Hendrik Schober <> wrote:
    >
    >
    >
    > > James Kanze wrote:
    > > > On Dec 2, 9:18 am, Hendrik Schober <> wrote:
    > > >> 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.


    FWIW, GCC (3.4.5 mingw) also does not accept it without the
    "typename", although the error message is less than informative:

    $ g++ testme.cpp
    testme.cpp:7: error: expected constructor, destructor, or type
    conversion before
    "MyClass"


    Jason
    , Dec 3, 2008
    #10
  11. Guest

    Re: Returning nested class within template class from memberfunction.

    On Dec 3, 12:55 pm, ""
    <> wrote:
    > On Dec 2, 7:26 pm, ""
    >
    >
    >
    > <> wrote:
    > > On Dec 2, 9:33 am, Hendrik Schober <> wrote:

    >
    > > > James Kanze wrote:
    > > > > On Dec 2, 9:18 am, Hendrik Schober <> wrote:
    > > > >> 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.

    >
    > FWIW, GCC (3.4.5 mingw) also does not accept it without the
    > "typename", although the error message is less than informative:
    >
    > $ g++ testme.cpp
    > testme.cpp:7: error: expected constructor, destructor, or type
    > conversion before
    >  "MyClass"


    But dammit, Borland's compiler *does* accept it without complaining
    (whatever version ships with RAD Studio 2007), bringing the whole
    thing to a tie again.

    Jason
    , Dec 3, 2008
    #11
  12. James Kanze Guest

    Re: Returning nested class within template class from memberfunction.

    On Dec 3, 12:47 pm, Triple-DES <> wrote:
    > On 3 Des, 10:15, James Kanze <> wrote:
    > > On Dec 2, 3:33 pm, Hendrik Schober <> 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].


    The standard is far from clear, but the first paragraph in §4.6
    seems to say clearly that names are split up into three disjoint
    sets. And MyClass<T>::Nested is a name declared within the
    template itself, thus a locally declared name, and thus not
    dependent. Other text makes it somewhat less clear, however,
    and I can easily understand implementors interpreting the
    standard differently in this regard. (In the end, it hinges on
    the question of whether, in MyClass, MyClass<T> is a dependent
    class. §16.6.2 can be read both ways, but §14.6.1 would seem to
    clearly say no.)

    > 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.


    I don't have a copy of C++03 handy here to verify, but it seems
    legal according to C++98 and the latest draft (the two versions
    I do have handy here).

    > 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.


    In other words, even the committee isn't certain.

    --
    James Kanze (GABI Software) email:
    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
    James Kanze, Dec 3, 2008
    #12
  13. James Kanze Guest

    Re: Returning nested class within template class from memberfunction.

    On Dec 3, 1:51 pm, Vidar Hasfjord <> wrote:
    > On Dec 3, 9:15 am, James Kanze <> wrote:
    > > On Dec 2, 3:33 pm, Hendrik Schober <> 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.


    If there is a specialization (partial or otherwise) of MyClass,
    it must redeclare f (or there won't be an f in the
    specialization); this definition does not define any such
    redeclaration.

    > > 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.


    I'm a little bit worried about another issue, however. What
    happens if an expression with this type is used as an argument
    to a function. Does dependent name lookup kick in for the
    function name, or not? Could the fact that compilers apparently
    treat it differently mean that you could write legal programs
    which compiled to different semantics, depending on the
    compiler?

    --
    James Kanze (GABI Software) email:
    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
    James Kanze, Dec 3, 2008
    #13
  14. Triple-DES Guest

    Re: Returning nested class within template class from memberfunction.

    On 3 Des, 23:10, James Kanze <> wrote:
    > On Dec 3, 12:47 pm, Triple-DES <> wrote:


    > The standard is far from clear, but the first paragraph in §4.6
    > seems to say clearly that names are split up into three disjoint
    > sets.  And MyClass<T>::Nested is a name declared within the
    > template itself, thus a locally declared name, and thus not
    > dependent.  Other text makes it somewhat less clear, however,
    > and I can easily understand implementors interpreting the
    > standard differently in this regard.  (In the end, it hinges on
    > the question of whether, in MyClass, MyClass<T> is a dependent
    > class.  §16.6.2 can be read both ways, but §14.6.1 would seem to
    > clearly say no.)
    >


    The relevant paragraph is 14.6/6:
    (...)The keyword typename shall always be specified when the
    member is referred to using a qualified name, even if the qualifier is
    simply the class template name.

    [Example:
    template<class T> struct A {
    typedef int B;
    A::B b; // ill-formed: typename required before A::B
    void f(A<T>::B); // ill-formed: typename required before A<T>::B
    typename A::B g(); // OK
    };
    The keyword typename is required whether the qualified name is A or
    A<T> (...)]

    > > 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.

    >
    > I don't have a copy of C++03 handy here to verify, but it seems
    > legal according to C++98 and the latest draft (the two versions
    > I do have handy here).
    >


    This is essentialy the same example as the one in 14.6/6. Thus my
    conclusion that MyClass<T>::Nested is always dependent, even inside
    the definition of MyClass. But again, according to

    http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#224

    it should be legal C++0x.
    Triple-DES, Dec 4, 2008
    #14
  15. James Kanze Guest

    Re: Returning nested class within template class from memberfunction.

    On Dec 4, 7:55 am, Triple-DES <> wrote:
    > On 3 Des, 23:10, James Kanze <> wrote:


    > > On Dec 3, 12:47 pm, Triple-DES <> wrote:
    > > The standard is far from clear, but the first paragraph in
    > > §4.6 seems to say clearly that names are split up into three
    > > disjoint sets. And MyClass<T>::Nested is a name declared
    > > within the template itself, thus a locally declared name,
    > > and thus not dependent. Other text makes it somewhat less
    > > clear, however, and I can easily understand implementors
    > > interpreting the standard differently in this regard. (In
    > > the end, it hinges on the question of whether, in MyClass,
    > > MyClass<T> is a dependent class. §16.6.2 can be read both
    > > ways, but §14.6.1 would seem to clearly say no.)


    > The relevant paragraph is 14.6/6:
    > (...)The keyword typename shall always be specified when the
    > member is referred to using a qualified name, even if the
    > qualifier is simply the class template name.


    OK. In other words, it doesn't matter whether the name is
    dependent or not.

    This requrement doesn't really make sense to me, but then, most
    of the rules concerning two phase lookup don't make sense to me.

    > [Example:
    > template<class T> struct A {
    > typedef int B;
    > A::B b; // ill-formed: typename required before A::B
    > void f(A<T>::B); // ill-formed: typename required before A<T>::B
    > typename A::B g(); // OK};
    >
    > The keyword typename is required whether the qualified name is A or
    > A<T> (...)]
    >
    > > > 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.


    > > I don't have a copy of C++03 handy here to verify, but it
    > > seems legal according to C++98 and the latest draft (the two
    > > versions I do have handy here).


    > This is essentialy the same example as the one in 14.6/6. Thus
    > my conclusion that MyClass<T>::Nested is always dependent,
    > even inside the definition of MyClass.


    I don't think it's dependent, but according to the passage you
    just quoted, however, it doesn't matter. Dependent or not, the
    typename is required.

    --
    James Kanze (GABI Software) email:
    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
    James Kanze, Dec 4, 2008
    #15
  16. Guest

    Re: Returning nested class within template class from memberfunction.

    On Dec 2, 7:26 pm, ""
    <> wrote:
    > On Dec 2, 9:33 am, Hendrik Schober <> wrote:
    >
    >
    >
    > > James Kanze wrote:
    > > > On Dec 2, 9:18 am, Hendrik Schober <> wrote:
    > > >> 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.


    Well, I emailed them about it, and then bugged them again a week
    later, but never got a response. Maybe it *is* a Comeau issue after
    all... weird...

    Jason
    , Dec 16, 2008
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page