types of classes in template classes

Discussion in 'C++' started by lobequadrat@googlemail.com, Apr 25, 2007.

  1. Guest

    Hello,

    I am trying to get the following code work (unfortunately not
    mine ... :( )

    template <class T> class Test {

    public:

    class ELEM;

    class CONST_ITERATOR {

    const Test<T>testAttribute::ELEM* elem;

    It can be compiled with g++ 2.95.3. But

    g++ -v
    Using built-in specs.
    Target: i686-apple-darwin8
    Configured with: /private/var/tmp/gcc/gcc-5367.obj~1/src/configure --
    disable-checking -enable-werror --prefix=/usr --mandir=/share/man --
    enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg]
    [^.-]*$/s/$/-4.0/ --with-gxx-include-dir=/include/c++/4.0.0 --with-
    slibdir=/usr/lib --build=powerpc-apple-darwin8 --with-arch=nocona --
    with-tune=generic --program-prefix= --host=i686-apple-darwin8 --
    target=i686-apple-darwin8
    Thread model: posix
    gcc version 4.0.1 (Apple Computer, Inc. build 5367) complains with the
    following error:


    src/SlowNameToTMap.hh:23: error: type 'SLOW_NAME_TO_T_MAP<T>' is not
    derived from type 'SLOW_NAME_TO_T_MAP<T>::CONST_ITERATOR'

    Any advice would be nice ... :)

    Greetings,

    lobequadrat
    , Apr 25, 2007
    #1
    1. Advertising

  2. wrote:
    ....
    >
    > src/SlowNameToTMap.hh:23: error: type 'SLOW_NAME_TO_T_MAP<T>' is not
    > derived from type 'SLOW_NAME_TO_T_MAP<T>::CONST_ITERATOR'
    >
    > Any advice would be nice ... :)


    A complete compilable (modulo the error) snippet would help in
    understanding exactly what your problem is.
    Gianni Mariani, Apr 25, 2007
    #2
    1. Advertising

  3. Guest

    On Apr 25, 10:34 am, Gianni Mariani <> wrote:
    > wrote:
    >
    > ...
    >
    >
    >
    > > src/SlowNameToTMap.hh:23: error: type 'SLOW_NAME_TO_T_MAP<T>' is not
    > > derived from type 'SLOW_NAME_TO_T_MAP<T>::CONST_ITERATOR'

    >
    > > Any advice would be nice ... :)

    >
    > A complete compilable (modulo the error) snippet would help in
    > understanding exactly what your problem is.


    My problem is that I can't use "const Test<T>testAttribute::ELEM*
    elem;"
    to define a const of this type. When I try to make the type visible by
    adding explicitly

    class CONST_ITERATOR:SLOW_NAME_TO_T_MAP<T>

    the compiler complains that "ISO C++ forbids declaration of 'ELEM'
    with no type".

    The complete source should be ...

    template <class T> class Test {

    public:

    class ELEM;

    class CONST_ITERATOR {

    const Test<T>testAttribute::ELEM* elem;

    };

    class ELEM {

    // whatever ...

    }

    };

    The code compiled without an error with g++ 2.95.3 ... but not with a
    current (see above) compiler ... ?
    , Apr 26, 2007
    #3
  4. wrote:
    > On Apr 25, 10:34 am, Gianni Mariani <> wrote:

    ....
    > The code compiled without an error with g++ 2.95.3 ... but not with a
    > current (see above) compiler ... ?
    >


    g++ 2.95.3 was buggy with templates. I wouldn't count on anything that
    it accepted being valid.


    Are either of these what you want ?

    template <class T> class Test {

    public:

    class ELEM;

    class CONST_ITERATOR {

    const typename Test<T>::ELEM * elem;
    // note the "typename" keyword
    };

    class ELEM {

    // whatever ...

    };

    };




    template <class T> class Testx {

    public:

    class ELEM;

    class CONST_ITERATOR {

    const ELEM * elem;

    };

    class ELEM {

    // whatever ...

    };

    };
    Gianni Mariani, Apr 26, 2007
    #4
  5. Guest

    On Apr 26, 11:42 am, Gianni Mariani <> wrote:
    > wrote:
    > > On Apr 25, 10:34 am, Gianni Mariani <> wrote:

    > ...
    > > The code compiled without an error with g++ 2.95.3 ... but not with a
    > > current (see above) compiler ... ?

    >
    > g++ 2.95.3 was buggy with templates. I wouldn't count on anything that
    > it accepted being valid.


    Ah ... ok - good to know ...

    > Are either of these what you want ?
    >
    > template <class T> class Test {
    >
    > public:
    >
    > class ELEM;
    >
    > class CONST_ITERATOR {
    >
    > const typename Test<T>::ELEM * elem;
    > // note the "typename" keyword
    > };
    >
    > class ELEM {
    >
    > // whatever ...
    >
    > };
    >
    > };
    >
    > template <class T> class Testx {
    >
    > public:
    >
    > class ELEM;
    >
    > class CONST_ITERATOR {
    >
    > const ELEM * elem;
    >
    > };
    >
    > class ELEM {
    >
    > // whatever ...
    >
    > };
    >
    > };


    Yepp - the first code snipped solved it ... as far as I understand c++
    interprets this statement
    "const typename Test<T>::ELEM * elem;" per default as a function and
    "typename" changes this, that it is interpreted as a declaration?

    Either way ... thanks for your help! :)

    lobequadrat
    , Apr 27, 2007
    #5
  6. James Kanze Guest

    wrote:
    > On Apr 26, 11:42 am, Gianni Mariani <> wrote:
    > > wrote:
    > > > On Apr 25, 10:34 am, Gianni Mariani <> wrote:

    > > ...
    > > > The code compiled without an error with g++ 2.95.3 ... but not with a
    > > > current (see above) compiler ... ?


    > > g++ 2.95.3 was buggy with templates. I wouldn't count on anything that
    > > it accepted being valid.


    > Ah ... ok - good to know ...


    Actually, g++ 2.95.3 was very good with templates. The only
    problem is that it is old; it implements templates as they were
    defined when it appeared, and not as they are defined today.

    > > Are either of these what you want ?


    > > template <class T> class Test {
    > > public:
    > > class ELEM;


    > > class CONST_ITERATOR {


    > > const typename Test<T>::ELEM * elem;
    > > // note the "typename" keyword
    > > };


    > > class ELEM {
    > > // whatever ...
    > > };
    > > };


    [...]

    > Yepp - the first code snipped solved it ... as far as I understand c++
    > interprets this statement
    > "const typename Test<T>::ELEM * elem;" per default as a function and
    > "typename" changes this, that it is interpreted as a declaration?


    The change is that orginally, all names in a template were bound
    at the point of instantiation. At that point, the compiler
    knows exactly what the name will be, and can treat it
    appropriately. The language was changed so that a compiler can
    parse and detect many errors in a template when the template is
    defined, before any instantiation. This causes two changes in
    code:

    -- Names in templates are divided into dependent and
    non-dependent names. Non-dependent names are completely
    bound at the site of the template definition, and are not
    looked up again at the site of instantiation. This
    typically affects functions which the template author
    expects to resolve to a function in a dependent base
    class---given something like:

    template< typename Toto >
    class C : public Toto
    {
    public:
    void f()
    {
    g() ; // should resolve to Toto::g()...
    }
    } ;

    Because there is nothing in the above code to let the
    compiler know that g() is dependent, the compiler tries to
    resolve it at the definition site, doesn't find a g(), and
    complains (or finds a g(), and that is the function which
    will be called, and not the one in the base class). Writing
    the call this->g() forces the compiler to consider the name
    dependent, and defers resolution until instantiation.

    -- It is, regretfully, impossible to correctly parse C++
    without knowing which names name types, and which don't.
    The same thing holds for templates. For non-dependent
    names, this is no problem; the compiler knows what they name
    at the definition site. For dependent names, however, it is
    a problem, since this information isn't available until
    later. The decision taken is that a dependent name will be
    assumed to be neither a type nor a template unless you tell
    the compiler otherwise. In your code, for example, the
    compiler originally assumed that ELEM in Test<T>::ELEM (a
    dependent name, since it obviously depends on Test<T>, which
    depends on T) is not a type nor a template. Except that in
    this case, the declaration is illegal if it isn't. By
    adding the keyword typename, you tell the compiler that it
    is a type name. Similar situations can occur (albeit much
    more rarely) with templates: if the orginal programmer of C,
    above, expected g to be a template function, and wrote:
    this->g<int>() ;
    the compiler would assume at the definition site that the <
    was the less than token, which would result in an error. In
    such cases, you have to write:
    this->template g<int>() ;
    so the compiler knows that g will name a template, and that
    the < starts the argument list.

    --
    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, Apr 27, 2007
    #6
    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. Chris Theis
    Replies:
    2
    Views:
    467
    Chris Theis
    Jul 24, 2003
  2. tom_usenet
    Replies:
    0
    Views:
    533
    tom_usenet
    Jul 24, 2003
  3. Replies:
    8
    Views:
    1,355
    Victor Bazarov
    Jan 7, 2006
  4. Adam Nielsen
    Replies:
    3
    Views:
    405
  5. Stephen Howe
    Replies:
    8
    Views:
    1,548
    Pavel
    Apr 10, 2011
Loading...

Share This Page