Topic: The using declaration and enumerators
Author: David R Tribble <david@tribble.com>
Date: Fri, 26 Jan 2001 19:39:18 GMT Raw View
scott_schurr@my-deja.com wrote:
> Given Michiel Salters' suggestion, I was able to achieve my
> desired end with the following code:
>
> class A {
> public:
> enum E {
> alpha,
> beta
> };
> };
>
> class B {
> public:
> typedef A::E E;
> static const E alpha = A::alpha;
> static const E beta = A::beta;
>
> E getAlpha () const { return alpha; }
> };
>
> Works great. I like it a lot.
Another approach you could try is:
class B
{
public:
enum E
{
alpha = A::alpha,
beta = A::beta
};
E getAlpha() const { return alpha; }
...
};
It's a pain, but no more so that the solution above. It also the
drawback of making B::A a different type than A::A.
--
David R. Tribble, mailto:david@tribble.com, http://david.tribble.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Sebastian Moleski \(SurakWare\)" <smoleski@surakware.com>
Date: Thu, 18 Jan 2001 21:36:31 GMT Raw View
"Scott Schurr" <scotts@ims.com> schrieb im Newsbeitrag
news:945g58$8vi$1@ims.com...
> I've got an enumeration declared in one class, and I want to reuse
> the same enumeration, and its enumerators, in another class. The
> classes are unrelated inheritance-wise.
>
> I've found a couple of hints, but I'm not sure where the standard
> falls on this. My first hint is in The C++ Programming Language,
> Third Edition at the end of section 8.8.2, Using Declarations,
> pg 171. The paragraph refers to parser tokens MUL and DIV declared
> in class "Lexer". The paragraph reads:
>
> I could have introduced the token names into the Parser's
> namespace. However, I left them explicitly qualified as a
> reminder of Parser's dependency on Lexer.
>
> So, at least in the Third Edition, Mr. Stroustrup hints that I
> can do what I want to do. But he doesn't tell me how. So I
> tried to do this a couple of ways, but I haven't yet found
> the correct leverage point with my compiler. Here is a toy
> example of what I want to do.
>
> class A {
> public:
> enum E {
> alpha,
> beta
> };
> };
>
> class B {
> public:
> typedef A::E E; // This works
> // using A::E; // This generates the error:
> // "type `A' is not a base type for type `B'"
>
> // using A::alpha; // This generates the error:
> // "type `A' is not a base type for type `B'"
>
> // using A::E::alpha; // This generates the error:
> // "Internal compiler error 89."
This should work.
sm
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Andrei Iltchenko" <Andrei.Iltchenko@openmarket.com>
Date: Thu, 18 Jan 2001 21:37:00 GMT Raw View
> I've got an enumeration declared in one class, and I want to reuse
> the same enumeration, and its enumerators, in another class. The
> classes are unrelated inheritance-wise.
>
> I've found a couple of hints, but I'm not sure where the standard
> falls on this. My first hint is in The C++ Programming Language,
> Third Edition at the end of section 8.8.2, Using Declarations,
> pg 171. The paragraph refers to parser tokens MUL and DIV declared
> in class "Lexer". The paragraph reads:
>
> I could have introduced the token names into the Parser's
> namespace. However, I left them explicitly qualified as a
> reminder of Parser's dependency on Lexer.
>
> So, at least in the Third Edition, Mr. Stroustrup hints that I
> can do what I want to do.
No he doesn't. He doesn't in the least say that it's possible
to introduce an enumerator defined in one class to the scope
of another class that is not related to the first through
inheritance. He talks about namespaces there...
> So I tried to do this a couple of ways, but I haven't yet found
> the correct leverage point with my compiler. Here is a toy
> example of what I want to do.
>
> class A {
> public:
> enum E {
> alpha,
> beta
> };
> };
>
> class B {
> public:
> typedef A::E E; // This works
> // using A::E; // This generates the error:
> // "type `A' is not a base type for type `B'"
>
> // using A::alpha; // This generates the error:
> // "type `A' is not a base type for type `B'"
>
> // using A::E::alpha; // This generates the error:
> // "Internal compiler error 89."
>
> // E getAlpha () const { return alpha; } // What I want to do.
> E getAlpha () const { return A::alpha; } // What I have to do.
> };
>
> What I want to know is whether the standard allows me to bring
> alpha and beta into B's scope. If it does, what syntax should I use?
The only way you can introduce names from one scope to another
so that they become synonyms for the names declared in the first scope
is by using either a using-declaration or a using-directive.
As the Standard doesn't allow for the use of using-directives in class
scope, the only solution left is to use a using declaration. However,
the standard says that if a using-declaration is used in class scope, it
shall refer to a member of a base class of the class being defined, or
to an enumerator for an enumeration type defined in the base class of
the class being defined... See 7.3.3/4. This means:
1. You couldn't reuse the enumeration type A::E in B, even if A
was a base class of B.
2. You can't reuse any of the enumerators of the enumeration type
A::E in B, as A doesn't constitute a base class of B.
3. The only way for you to reuse the enumerators of A::E in B is
to make A a base class of B.
Regards,
Andrei Iltchenko
Brainbench MVP for C++
http://www.brainbench.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Thu, 18 Jan 2001 21:37:30 GMT Raw View
In article <945g58$8vi$1@ims.com>, Scott Schurr <scotts@ims.com> writes
>I've got an enumeration declared in one class, and I want to reuse
>the same enumeration, and its enumerators, in another class. The
>classes are unrelated inheritance-wise.
using declarations will not help you with this problem because those are
designed to do one of two things:
inject the declarations of a name from a namespace into a scope
inject a declaration of name from a base class into a derived class
scope.
You problem concerns neither of these.
>
>I've found a couple of hints, but I'm not sure where the standard
>falls on this. My first hint is in The C++ Programming Language,
>Third Edition at the end of section 8.8.2, Using Declarations,
>pg 171. The paragraph refers to parser tokens MUL and DIV declared
>in class "Lexer". The paragraph reads:
>
> I could have introduced the token names into the Parser's
> namespace. However, I left them explicitly qualified as a
> reminder of Parser's dependency on Lexer.
>
>So, at least in the Third Edition, Mr. Stroustrup hints that I
>can do what I want to do. But he doesn't tell me how.
Probably because you are seeing what you hope to see rather than what he
was actually writing about:)
> So I
>tried to do this a couple of ways, but I haven't yet found
>the correct leverage point with my compiler. Here is a toy
>example of what I want to do.
>
>class A {
>public:
> enum E {
> alpha,
> beta
> };
>};
>
>class B {
>public:
> typedef A::E E; // This works
and is the only legitimate way to achieve your objective, why does it
worry you? Well, it does not inject the enumeration constants which will
still have to be written as A::alpha etc.
> // using A::E; // This generates the error:
> // "type `A' is not a base type for type `B'"
See above, the compiler is right
>
> // using A::alpha; // This generates the error:
> // "type `A' is not a base type for type `B'"
Again, the compiler is right
>
> // using A::E::alpha; // This generates the error:
> // "Internal compiler error 89."
I am now wondering if using ::A::E::alpha might work, but why care? If
you want the enum shared encapsulate your classes in a namespace and
move the enum definition from the class scope to the namespace scope.
>
> // E getAlpha () const { return alpha; } // What I want to do.
Why? Why does the correct method disturb you?
> E getAlpha () const { return A::alpha; } // What I have to do.
>};
>
>What I want to know is whether the standard allows me to bring
>alpha and beta into B's scope. If it does, what syntax should I use?
No, I do not think it does, and, frankly, I do not know why you want to
couple to unrelated classes this way.
>The only clue I've found in the standard is in section 7.3.3
>paragraph 2:
>
> The member name specified in a using-declaration is declared in the
> declarative region in which the using-declaration appears. [Note:
> only the specified name is so declared; specifying an enumeration
> name in a using-declaration does not declare its enumerators in the
> using-declaration's declarative region.]
>
>My read of this paragraph says that B's "using A::E" should be okay,
No because A is NOT a namespace, it is a class.
>but would not introduce "alpha" or "beta" into B. What the paragraph
>does not say is whether or not it should be possible to introduce
>"alpha" or "beta" into B.
>
>Any hints? Ideas? Thanks!
Doctor, doctor, it hurts when I do this.
Then do not do that.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: scott_schurr@my-deja.com
Date: Fri, 19 Jan 2001 02:22:08 GMT Raw View
Thank you for all of the replies. I'd especially like to thank
Michiel Salters for his excellent proposal for a solution. It
works well for me, and I like it a lot. The inheritance-based
suggestions were also very useful, but in the case I'm working on,
changing the inheritance structure is less desirable. At least
from my perspective.
In article <945g58$8vi$1@ims.com>,
scotts@ims.com (Scott Schurr) wrote:
> So, at least in the Third Edition, Mr. Stroustrup hints that I
> can do what I want to do.
And a number of you corrected me. I now see the error of my
ways and apologize for the confusion. I hadn't looked far
enough forward in the chapter to realize that Lexer was a
namespace. I clumsily assumed that Lexer was a class. Sorry.
Given Michiel Salters' suggestion, I was able to achieve my
desired end with the following code:
class A {
public:
enum E {
alpha,
beta
};
};
class B {
public:
typedef A::E E;
static const E alpha = A::alpha;
static const E beta = A::beta;
E getAlpha () const { return alpha; }
};
Works great. I like it a lot.
Thanks again for all the help. And I'll be reading the whole
section on namespaces tonight...
--------------------------------------
Scott Schurr
Integrated Measurement Systems, Inc.
Voice: (503) 626-7117
Fax: (503) 644-6969
Email: scotts@ims.com
--------------------------------------
Sent via Deja.com
http://www.deja.com/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: scotts@ims.com (Scott Schurr)
Date: Thu, 18 Jan 2001 01:28:46 GMT Raw View
I've got an enumeration declared in one class, and I want to reuse
the same enumeration, and its enumerators, in another class. The
classes are unrelated inheritance-wise.
I've found a couple of hints, but I'm not sure where the standard
falls on this. My first hint is in The C++ Programming Language,
Third Edition at the end of section 8.8.2, Using Declarations,
pg 171. The paragraph refers to parser tokens MUL and DIV declared
in class "Lexer". The paragraph reads:
I could have introduced the token names into the Parser's
namespace. However, I left them explicitly qualified as a
reminder of Parser's dependency on Lexer.
So, at least in the Third Edition, Mr. Stroustrup hints that I
can do what I want to do. But he doesn't tell me how. So I
tried to do this a couple of ways, but I haven't yet found
the correct leverage point with my compiler. Here is a toy
example of what I want to do.
class A {
public:
enum E {
alpha,
beta
};
};
class B {
public:
typedef A::E E; // This works
// using A::E; // This generates the error:
// "type `A' is not a base type for type `B'"
// using A::alpha; // This generates the error:
// "type `A' is not a base type for type `B'"
// using A::E::alpha; // This generates the error:
// "Internal compiler error 89."
// E getAlpha () const { return alpha; } // What I want to do.
E getAlpha () const { return A::alpha; } // What I have to do.
};
What I want to know is whether the standard allows me to bring
alpha and beta into B's scope. If it does, what syntax should I use?
The only clue I've found in the standard is in section 7.3.3
paragraph 2:
The member name specified in a using-declaration is declared in the
declarative region in which the using-declaration appears. [Note:
only the specified name is so declared; specifying an enumeration
name in a using-declaration does not declare its enumerators in the
using-declaration's declarative region.]
My read of this paragraph says that B's "using A::E" should be okay,
but would not introduce "alpha" or "beta" into B. What the paragraph
does not say is whether or not it should be possible to introduce
"alpha" or "beta" into B.
Any hints? Ideas? Thanks!
--------------------------------------
Scott Schurr
Integrated Measurement Systems, Inc.
Voice: (503) 626-7117
Fax: (503) 644-6969
Email: scotts@ims.com
--------------------------------------
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Michiel Salters <salters@lucent.com>
Date: Thu, 18 Jan 2001 17:18:33 GMT Raw View
Scott Schurr wrote:
[ SNIP ]
> Here is a toy
> example of what I want to do.
> class A {
> public:
> enum E { alpha, beta };
> };
> class B {
> public:
> typedef A::E E; // This works
> // using A::E; // This generates the error:
> // "type `A' is not a base type for type `B'"
> // using A::alpha; // This generates the error:
> // "type `A' is not a base type for type `B'"
> // using A::E::alpha; // This generates the error:
> // "Internal compiler error 89."
> // E getAlpha () const { return alpha; } // What I want to do.
> E getAlpha () const { return A::alpha; } // What I have to do.
> };
> What I want to know is whether the standard allows me to bring
> alpha and beta into B's scope. If it does, what syntax should I use?
There really is no way to bring A::alpha into B's scope. After all, it's
A::alpha. The typedef for the same reason didn't bring A::E into the
scope of B, it introduced a new name B::E which is in the scope of B.
However, both A::E and B::E are the same type. That is possible
because names are in scopes, and the types they name are not.
Luckily, there is a way to fake this. It is legal to define named constants
of enum type, and such constants may be named/defined in B's scope.
This allows you to include in class B the following definitions:
const E alpha = A::alpha; const E beta = A::beta;
which allows you to use B::alpha as you desire (i.e. as unqualified alpha
within members of B).
HTH,
Michiel Salters
--
Michiel Salters
Michiel.Salters@cmg.nl
salters@lucent.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: pierrebai@my-deja.com
Date: Thu, 18 Jan 2001 17:21:52 GMT Raw View
In article <945g58$8vi$1@ims.com>,
scotts@ims.com (Scott Schurr) wrote:
> I've got an enumeration declared in one class, and I want to reuse
> the same enumeration, and its enumerators, in another class. The
> classes are unrelated inheritance-wise.
The trick is to declare a base class that only contain the enumeration
and have both classes derive from it. The only potential side-effect is
that compilers have the opportunity to make empty base class occupy zero
byte in derived classes, but they are not forced to. Thus your classes
could grow by a small amount. The other technique you were looking for
is related to *namespace* not classes.
Sent via Deja.com
http://www.deja.com/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]