• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: referring to enum values in a template
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: referring to enum values in a template


  • Subject: Re: referring to enum values in a template
  • From: James Widman <email@hidden>
  • Date: Sun, 29 Jan 2006 01:19:47 -0500

Hi Nathan,

On Jan 27, 2006, at 9:11 PM, Nathan Roberts wrote:

Hello all,

I'm converting a CodeWarrior project to XCode, and I'm down to two lines that won't compile. The lines are template code, and they fail during instantiation. In fact, the two lines look pretty much equivalent, so I'll just include code for one.

Basically, I've got an enum that's defined in a template class.

Minor nit: we say "class template" when referring to the template (as opposed to instantiations of it). "Template class" is known these days as a somewhat deprecated shorthand for "template specialization". It sure does roll off the tongue more easily though. (:


I'm trying to refer to one of the values of the enum. In CW this compiled just fine when I had just the name of the enum value (eNotice); gcc wants me to be more specific (I used TVectorMessage<T>::ECode::eNotice). This latter seems to pass the syntax check, and to give an error during instantiation (T = STask), saying that 'eNotice' is not a member of 'TVectorMessage<STask>::ECode'.

I don't know if code will be necessary or helpful -- this may just be a syntax thing

It is. Actually, there are two issues here, and both of them seem to catch a lot of people off guard.


I've boiled your example down a little so that we can (a) try to compile it and (b) discuss it within a reasonable period of time. (:

template <class T> struct  A
    {
    enum E { e0, e1, e2, e3 };
    A( E, E ){}
    };

template <class T> struct  B : public A<T>
    {
    B() : A<T>(
               // what you had in your example:
               A<T>::E::e3,
               // what you probably had before GCC complained:
                e3 )
        {}
    };

B<int> bi; // elicit instantiation

Messages from GCC 4.0.1 are:

t.cpp: In constructor 'B<T>::B()':
t.cpp:14: error: 'e3' was not declared in this scope
t.cpp: In constructor 'B<T>::B() [with T = int]':
t.cpp:18:   instantiated from here
t.cpp:14: error: 'e3' is not a member of 'A<int>::E'

[Note that there is no 'with' clause for the error about e3: that message was issued during the definition of the template -- not its instantiation.]

Issue 1: Base classes of dependent type (or, during instantiation, of formerly-dependent type) are not searched during unqualified name lookup. (14.6.2p3) Why do we need this rule? Suppose we allowed unqualified lookup to look-up in ex-dependent base classes at instantiation time; and suppose we had the code:

template <class T> struct  A
    {
    enum E { e0, e1, e2, e3 };
    A(E) {}
    };

const int e3 = 4;

template <class T> struct  B : public A<T>
    {
    B() : A<T>( e3 ) {} // which e3?
    };

B<int> bi;

Now, during the definition of the primary template B, we can't look in A<T> -- it might later be explicitly or partially specialized, and so we can't assume that all future instantiations of A will contain 'enum E'. So we find the 'e3' in the global namespace.

Later, we instantiate. At that time, it's possible to look in the base class because it's no longer dependent: we know for certain what its members are. Now, we actually won't go looking for e3 in this case, because we already did the lookup at template definition time (14.6.3). But if we *were* to do lookup anyway, we would find a completely different symbol: ::A<int>::e3. The "would-be" name lookup has to be consistient. Why? It has something to do with 'export', and that's all I'm going to say about that. (:

Issue 2: Enums do not introduce a new scope; instead, enumeration constants ([e0-e3] above) are injected into the scope where the enumeration type name resides. So instead, you should use:

B() : A<T>( A<T>::e3, A<T>::e3 )

Again, GCC won't look in A<T> at template def time; instead it will just record the fact that a dependent expression was seen. During instantiation time, it will finally be able to look in a concrete scope -- A<int> -- and it will find ::A<int>::e3.

HTH,

James
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Follow-Ups:
    • Re: referring to enum values in a template
      • From: Nathan Roberts <email@hidden>
References: 
 >referring to enum values in a template (From: Nathan Roberts <email@hidden>)

  • Prev by Date: Re: Debugging a CGI with XCode, is it possible?
  • Next by Date: dumpmachine output for intel's mac
  • Previous by thread: referring to enum values in a template
  • Next by thread: Re: referring to enum values in a template
  • Index(es):
    • Date
    • Thread