Problem with template using base class template in GCC

Discussion in 'C++' started by Walt Karas, Aug 27, 2004.

  1. Walt Karas

    Walt Karas Guest

    The following gives an error in the declaration of the
    member function x() of the class template Tpl, compiliing
    with a recent version of GCC under Solaris:

    class A { };
    class B { };

    template <typename Base>
    class Tpl : protected Base
    {
    public:
    template <typename AOrB>
    int x(void) { return(baseX<AOrB>()); }
    };

    class TheBase
    {
    public:

    template<typename AOrB>
    int baseX(void);
    };

    template<>
    inline int TheBase::baseX<A>(void) { return(1); }

    template<>
    inline int TheBase::baseX<B>(void) { return(2); }

    Tpl<TheBase> aTpl;

    But if I give 'baseX' a dummy parameter whose type is the type parameter
    to the template, making explicit naming of the type paramenter in the
    baseX call unecessary, it does compile:

    class A { };
    class B { };

    template <typename Base>
    class Tpl : protected Base
    {
    public:
    template <typename AOrB>
    int x(void) { return(baseX(AOrB())); }
    };

    class TheBase
    {
    public:

    template<typename AOrB>
    int baseX(AOrB aOrB);
    };

    template<>
    inline int TheBase::baseX<A>(A a) { return(1); }

    template<>
    inline int TheBase::baseX<B>(B b) { return(2); }

    Tpl<TheBase> aTpl;

    Is there some rule in the standard that requires this behavior?
    Or is this just a problem with the GCC compiler?

    Another thing that surprised me was that GCC gives me an error if
    I put the partial specializations of 'baseX' inside the declaration
    of the class 'TheBase'.

    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Walt Karas, Aug 27, 2004
    #1
    1. Advertising

  2. "Walt Karas" <> wrote...
    > The following gives an error in the declaration of the
    > member function x() of the class template Tpl, compiliing
    > with a recent version of GCC under Solaris:
    >
    > class A { };
    > class B { };
    >
    > template <typename Base>
    > class Tpl : protected Base
    > {
    > public:
    > template <typename AOrB>
    > int x(void) { return(baseX<AOrB>()); }


    I got it to compile by doing this:

    template <typename AOrB>
    inx x() { return this->template baseX<AOrB>(); }

    > };
    >
    > class TheBase
    > {
    > public:
    >
    > template<typename AOrB>
    > int baseX(void);
    > };
    >
    > template<>
    > inline int TheBase::baseX<A>(void) { return(1); }
    >
    > template<>
    > inline int TheBase::baseX<B>(void) { return(2); }
    >
    > Tpl<TheBase> aTpl;
    >
    > But if I give 'baseX' a dummy parameter whose type is the type parameter
    > to the template, making explicit naming of the type paramenter in the
    > baseX call unecessary, it does compile:
    >
    > class A { };
    > class B { };
    >
    > template <typename Base>
    > class Tpl : protected Base
    > {
    > public:
    > template <typename AOrB>
    > int x(void) { return(baseX(AOrB())); }
    > };
    >
    > class TheBase
    > {
    > public:
    >
    > template<typename AOrB>
    > int baseX(AOrB aOrB);
    > };
    >
    > template<>
    > inline int TheBase::baseX<A>(A a) { return(1); }
    >
    > template<>
    > inline int TheBase::baseX<B>(B b) { return(2); }
    >
    > Tpl<TheBase> aTpl;
    >
    > Is there some rule in the standard that requires this behavior?


    Yes, if the base class depends on the template type, its scope is not
    searched to resolve a dependent name.

    > Or is this just a problem with the GCC compiler?


    I don't think so. Comeau also rejected the first example.

    > Another thing that surprised me was that GCC gives me an error if
    > I put the partial specializations of 'baseX' inside the declaration
    > of the class 'TheBase'.


    That's also still prohibited. They are thinking of adding it to the
    next Standard, IIRC.

    V
    Victor Bazarov, Aug 27, 2004
    #2
    1. Advertising

  3. Walt Karas

    Paul Guest

    "Victor Bazarov" <> wrote in message news:<81yXc.316605$a24.50596@attbi_s03>...
    > "Walt Karas" <> wrote...
    > > The following gives an error in the declaration of the
    > > member function x() of the class template Tpl, compiliing
    > > with a recent version of GCC under Solaris:
    > >
    > > class A { };
    > > class B { };
    > >
    > > template <typename Base>
    > > class Tpl : protected Base
    > > {
    > > public:
    > > template <typename AOrB>
    > > int x(void) { return(baseX<AOrB>()); }

    >
    > I got it to compile by doing this:
    >
    > template <typename AOrB>
    > inx x() { return this->template baseX<AOrB>(); }
    >
    > > };
    > >
    > > class TheBase
    > > {
    > > public:
    > >
    > > template<typename AOrB>
    > > int baseX(void);
    > > };
    > >
    > > template<>
    > > inline int TheBase::baseX<A>(void) { return(1); }
    > >
    > > template<>
    > > inline int TheBase::baseX<B>(void) { return(2); }
    > >
    > > Tpl<TheBase> aTpl;
    > >
    > > But if I give 'baseX' a dummy parameter whose type is the type parameter
    > > to the template, making explicit naming of the type paramenter in the
    > > baseX call unecessary, it does compile:
    > >
    > > class A { };
    > > class B { };
    > >
    > > template <typename Base>
    > > class Tpl : protected Base
    > > {
    > > public:
    > > template <typename AOrB>
    > > int x(void) { return(baseX(AOrB())); }
    > > };
    > >
    > > class TheBase
    > > {
    > > public:
    > >
    > > template<typename AOrB>
    > > int baseX(AOrB aOrB);
    > > };
    > >
    > > template<>
    > > inline int TheBase::baseX<A>(A a) { return(1); }
    > >
    > > template<>
    > > inline int TheBase::baseX<B>(B b) { return(2); }
    > >
    > > Tpl<TheBase> aTpl;
    > >
    > > Is there some rule in the standard that requires this behavior?

    >
    > Yes, if the base class depends on the template type, its scope is not
    > searched to resolve a dependent name.
    >
    > > Or is this just a problem with the GCC compiler?

    >
    > I don't think so. Comeau also rejected the first example.
    >
    > > Another thing that surprised me was that GCC gives me an error if
    > > I put the partial specializations of 'baseX' inside the declaration
    > > of the class 'TheBase'.

    >
    > That's also still prohibited. They are thinking of adding it to the
    > next Standard, IIRC.
    >
    > V


    Firstly I'd like to say that it compiles ok with MS 2003 Compiler.

    I believe it should compile ok as I can see nothing wrong with the
    code.
    But the point made about name lookup , I have read too that base
    templates are not searched but in this case we have the rules of
    inheritance do we not. You could also try to call the base funtion
    with fully qualified name which also worked for me but was not
    required i.e: theBase::baseX<T>(T b);.
    Try making your inheritance public then you should be able to call
    baseX directly from instances of Tpl.
    I don't think it would be very good if templating a class meant we
    lost the inheritance, so I believe it's a fault with your compiler.

    And also you are speaking of partial specialization but this is not
    partial specialization it's full specialization of member function
    baseX. I'm not sure on all the rules but I can define them within the
    class and it works fine. And I don't see why you shouldn't be able too
    do so. I think member function specializations are generally defined
    out of class for clarity though.

    HTH Paul
    Paul, Aug 27, 2004
    #3
  4. Paul wrote:
    > [...]
    > Firstly I'd like to say that it compiles ok with MS 2003 Compiler.
    >
    > [...]
    > I'm not sure on all the rules but I can define them within the
    > class and it works fine. [...]


    Have you tried turning "language extensions" off?

    Here is the rule of comp.lang.c++: if it compiles with your compiler,
    it's not enough to confirm that the code is standard C++. Try to
    follow it. To help you develop a sense of right and wrong WRT C++
    language, get a copy of the Standard document.

    V
    Victor Bazarov, Aug 27, 2004
    #4
  5. Walt Karas

    Paul Guest

    [snip]

    Note: My compiler language extensions are turned off.


    HTH
    Paul
    Paul, Aug 27, 2004
    #5
  6. Walt Karas

    Walt Karas Guest

    Victor Bazarov <> wrote in message news:<gYJXc.363$09.us.to.verio.net>...
    > Paul wrote:
    > > [...]
    > > Firstly I'd like to say that it compiles ok with MS 2003 Compiler.
    > >
    > > [...]
    > > I'm not sure on all the rules but I can define them within the
    > > class and it works fine. [...]

    >
    > Have you tried turning "language extensions" off?
    >
    > Here is the rule of comp.lang.c++: if it compiles with your compiler,
    > it's not enough to confirm that the code is standard C++. Try to
    > follow it. To help you develop a sense of right and wrong WRT C++
    > language, get a copy of the Standard document.
    >
    > V


    Another good rule would be to cite a particular paragraph in
    the standard when saying that something isn't compliant, if
    at all possible.

    Why would it be desirable to impose this limitation? Does
    the compiler need to bind the referenced template to a definition
    visible in the scope where the refering template is being
    defined (in order to make instantiation context-independent)?
    Seems like the compiler could just assume the template was
    in the base class, then enforce this assumption at
    instantiation. Or, if that's too hard, require the previously
    posted suggestion of a base:: qualifier on the template.
    Walt Karas, Aug 28, 2004
    #6
  7. Walt Karas

    Paul Guest

    (Walt Karas) wrote in message news:<>...
    > Victor Bazarov <> wrote in message news:<gYJXc.363$09.us.to.verio.net>...
    > > Paul wrote:
    > > > [...]
    > > > Firstly I'd like to say that it compiles ok with MS 2003 Compiler.
    > > >
    > > > [...]
    > > > I'm not sure on all the rules but I can define them within the
    > > > class and it works fine. [...]

    > >
    > > Have you tried turning "language extensions" off?
    > >
    > > Here is the rule of comp.lang.c++: if it compiles with your compiler,
    > > it's not enough to confirm that the code is standard C++. Try to
    > > follow it. To help you develop a sense of right and wrong WRT C++
    > > language, get a copy of the Standard document.
    > >
    > > V

    >
    > Another good rule would be to cite a particular paragraph in
    > the standard when saying that something isn't compliant, if
    > at all possible.
    >
    > Why would it be desirable to impose this limitation? Does
    > the compiler need to bind the referenced template to a definition
    > visible in the scope where the refering template is being
    > defined (in order to make instantiation context-independent)?
    > Seems like the compiler could just assume the template was
    > in the base class, then enforce this assumption at
    > instantiation. Or, if that's too hard, require the previously
    > posted suggestion of a base:: qualifier on the template.


    I needed to use qualified names with extensions turned off i.e:

    return this->baseX<AOrB>();
    return Base::baseX<AOrB>();

    Both these work for me but I'm still unsure if the second is completely correct.


    Here is a link about it:
    http://www.tempest-sw.com/cpp/draft/ch07-templates.html
    Near the bottom of the page it's explained under Resolving names.

    Paul.
    Paul, Aug 28, 2004
    #7

  8. > template<>
    > inline int TheBase::baseX<A>(void) { return(1); }
    >
    > template<>
    > inline int TheBase::baseX<B>(void) { return(2); }
    >
    > Tpl<TheBase> aTpl;
    >
    > But if I give 'baseX' a dummy parameter whose type is the type parameter
    > to the template, making explicit naming of the type paramenter in the
    > baseX call unecessary, it does compile:


    Well, I'm not sure to understand what you want to do here ????
    But, from what you wrote, I guess that the compiler interpret the two
    specialized functions as two more functions in the class TheBase.
    Unfortunately, you don't explicitely make use of either class A or
    either class B,so the compiler can't decide wich one to choose.


    > class TheBase
    > {
    > public:
    >
    > template<typename AOrB>
    > int baseX(AOrB aOrB);
    > };
    >
    > template<>
    > inline int TheBase::baseX<A>(A a) { return(1); }
    >
    > template<>
    > inline int TheBase::baseX<B>(B b) { return(2); }
    >
    > Tpl<TheBase> aTpl;
    >


    Here, as you provide two functions with different input arguments,
    compiler can now assign two functions to TheBase that are :
    int TheBase::baseX(A a);
    int TheBase::baseX(B b);

    This is a common overloading rule. Remember, you can't overload function
    with the same argument.

    > Another thing that surprised me was that GCC gives me an error if
    > I put the partial specializations of 'baseX' inside the declaration
    > of the class 'TheBase'.


    Because of c++ doesn't allow template specializations inside a class ...
    More exactly specialized template should be associated with a namespace
    scope.

    Hope, all this will help !
    Probably if you tell more about what you want to do exactly, I should help
    you a bit more.

    Best regards,
    Gilles Rochefort









    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Gilles Rochefort, Aug 29, 2004
    #8
  9. Walt Karas

    Chris Vine Guest

    Walt Karas wrote:

    > The following gives an error in the declaration of the
    > member function x() of the class template Tpl, compiliing
    > with a recent version of GCC under Solaris:
    >
    > class A { };
    > class B { };
    >
    > template <typename Base>
    > class Tpl : protected Base
    > {
    > public:
    > template <typename AOrB>
    > int x(void) { return(baseX<AOrB>()); }

    ^^^^^^^^^^^^^^^^^^^^^^
    (See below)
    > };
    >
    > class TheBase
    > {
    > public:
    >
    > template<typename AOrB>
    > int baseX(void);
    > };
    >
    > template<>
    > inline int TheBase::baseX<A>(void) { return(1); }
    >
    > template<>
    > inline int TheBase::baseX<B>(void) { return(2); }
    >
    > Tpl<TheBase> aTpl;


    [snip]

    I have had to change quite a lot of code of this kind to compile with
    gcc-3.4. According to gcc-3.4, the syntax for your call in int Tpl::x() to
    a method in the templated base class is:

    int x(void) { return(Base::baseX<A0rB>()); }
    ^^^^^^
    In other words, you need to specify that baseX() is a member of the
    templated base class. Whether that is required by the standard I know not,
    but I expect it is right. gcc-3.4 is a lot stricter than gcc-3.2/3.3.

    You have set follow-ups to a group I do not read, so I will not see any
    response (not a very good idea).

    Chris.


    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Chris Vine, Aug 29, 2004
    #9
  10. Walt Karas

    Paul Guest

    <snip>
    >
    > Because of c++ doesn't allow template specializations inside a class ...
    > More exactly specialized template should be associated with a namespace
    > scope.


    Are you sure about that?

    class Test{
    public:
    template<typename T>void foo(T){}
    template<>void foo(double){}
    };

    The above compiles ok , not saying that means it's right, but are you
    ssaying this is not allowed? Is the namespace for foo here not Test?

    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Paul, Aug 29, 2004
    #10
  11. "Paul" <> wrote...
    > <snip>
    > >
    > > Because of c++ doesn't allow template specializations inside a class ...
    > > More exactly specialized template should be associated with a namespace
    > > scope.

    >
    > Are you sure about that?
    >
    > class Test{
    > public:
    > template<typename T>void foo(T){}
    > template<>void foo(double){}
    > };
    >
    > The above compiles ok , not saying that means it's right, but are you
    > ssaying this is not allowed? Is the namespace for foo here not Test?


    How many times do we have to write, "'compiles ok', doesn't necessarily
    mean 'correct code'"? Try to remember that and avoid "hey, it compiles
    OK on my compiler so it must be good code".
    Victor Bazarov, Aug 30, 2004
    #11
  12. Walt Karas

    Old Wolf Guest

    "Victor Bazarov" <> wrote:
    > "Walt Karas" <> wrote...
    > > The following gives an error in the declaration of the
    > > member function x() of the class template Tpl, compiliing
    > > with a recent version of GCC under Solaris:
    > >
    > > class A { };
    > > class B { };
    > >
    > > template <typename Base>
    > > class Tpl : protected Base
    > > {
    > > public:
    > > template <typename AOrB>
    > > int x(void) { return(baseX<AOrB>()); }

    >
    > I got it to compile by doing this:
    >
    > template <typename AOrB>
    > inx x() { return this->template baseX<AOrB>(); }
    >


    To elaborate: firstly, baseX is a dependent name because it
    depends on 'Base'. The compiler doesn't look in dependent
    base classes to resolve names. So you have go this-> or Base::
    to tell the compiler where it is.

    Secondly, it doesn't know what the symbol 'baseX' is at this
    point. In particular it could be : int baseX; in which case
    baseX<AOrB> is parsed as baseX (less-than operator) AOrB
    (syntax error). So the keyword 'template' indicates that
    baseX is the name of a template member function.
    Old Wolf, Aug 31, 2004
    #12

  13. > class Test{
    > public:
    > template<typename T>void foo(T){}
    > template<>void foo(double){}
    > };


    Yes, as I said this not allowed ...
    The above code don't compile on a recent gcc ( I tested on a 3.3.2 )
    I guess that gcc becomes lesser and lesser permissive ..

    So, now you have to write the following code to get a chance to compile.

    class Test{
    public:
    template<typename T>void foo(T){}
    };

    template<>void Test::foo(double){}

    Gilles.




    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Gilles Rochefort, Aug 31, 2004
    #13
  14. Walt Karas

    Sharad Kala Guest

    "Paul" <> wrote in message
    news:...
    > <snip>
    > >
    > > Because of c++ doesn't allow template specializations inside a class ...
    > > More exactly specialized template should be associated with a namespace
    > > scope.

    >
    > Are you sure about that?
    >
    > class Test{
    > public:
    > template<typename T>void foo(T){}
    > template<>void foo(double){}
    > };
    >


    Yes, he is correct. The relevant section in standard is 14.7.3/2: "An
    explicit specialization shall be declared in the namespace of which the
    template is a member, or, for member templates, in the namespace of which
    the enclosing class or enclosing class template is a member."

    -Sharad




    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Sharad Kala, Aug 31, 2004
    #14
    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.
Similar Threads
  1. Alf P. Steinbach
    Replies:
    6
    Views:
    534
    John Carson
    Sep 3, 2005
  2. flopbucket
    Replies:
    2
    Views:
    416
    Andrey Tarasevich
    Jun 23, 2006
  3. steve yee
    Replies:
    5
    Views:
    339
    Bo Persson
    Jul 1, 2008
  4. nguillot
    Replies:
    5
    Views:
    521
  5. Hicham Mouline
    Replies:
    1
    Views:
    584
    Victor Bazarov
    Apr 20, 2009
Loading...

Share This Page