Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to give an enum an alias name

1 view
Skip to first unread message

Kurt Stege

unread,
Sep 19, 2007, 11:25:08 AM9/19/07
to
Dear all.

I would need some idea regarding using declarations or
similar means.

I have written a library like following example:

// library code
struct A
{
enum E { e };
static enum A::E func(A::E) { return A::e; }
};

// client code

void foo()
{
A::E bar = A::e;
bar = A::func(bar);
}


For some reasons of restructuring, I would like to move
the enum to another class (or namespace) B, without breaking
existing client code.

That is, some library functions would expect parameters of
type B::E, while the client still calls the function with
A::e.

I have no problems with keeping class A in my library
to allow client code to use still names like A::E and
A::e, however, I don't see a way to provide these symbols
using the same type as B::E.

// restructured library code
struct B
{
enum E { e };
};

struct A
{
// for compatibility to old client code put B::E into struct A

#if 0 // a) introduces a new incompatible type
enum E { e };
#endif

#if 0 // b) doesn't work with current clients compiler, MSVC 6
using B::E;
using B::e;
#endif

#if 0 // c) imports B::E, but not B::e
typedef B::E E;
#endif

#if 1 // d) imports B::E, B::e is different and incompatible to A::e
typedef B::E E;
enum { e = B::e };
#endif

static enum B::E func(B::E) { return B::e; }
};

// client code

void foo()
{
A::E bar = A::e;
bar = A::func(bar);
}


I would have expected version b) to work. But at least my compiler
claims that the used symbols have to be members of a base class of A
(error C2602). And the compiler seems to be right, as clause 4 in
section 7.3.3 "The using declaration" in the C++ standard ISO/IEC
14882:2003 states: "A using-declaration used as a member-declaration
shall refer to a member of a base class of the class being defined,
shall refer to a member of an anonymous union that is a member of a
base class of the class being defined, or shall refer to an
enumerator for an enumeration type that is a member of a base class
of the class being defined."

The nearest thing I have found is version d), but of course the
implicit type conversion from A::<unnamed enum> to B::E is not
possible. That is, the client code uses a constant A::e that has
to be either of type B::E or has to be of a type that can be
converted (implicit) to B::E.

Alas, I have no more ideas how to provide a conversion
function for enums. They seem only to be available for classes...
Do you?

Best regards,
Kurt.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

john...@torjo.com

unread,
Sep 19, 2007, 4:11:11 PM9/19/07
to
On 19 Sep, 18:25, Kurt Stege <kurt.st...@siemens.com> wrote:
> Dear all.
>
> I would need some idea regarding using declarations or
> similar means.
>
> I have written a library like following example:
>
> // library code
> struct A
> {
> enum E { e };
> static enum A::E func(A::E) { return A::e; }
>
> };

One extra layer of indirection ;)

struct MyCoolEnum {
typedef enum type { a, b };
};

struct A {
typedef MyCoolEnum E;
};

struct B {
typedef MyCoolEnum E;
};

int main()
{
A::E::type t = A::E::a;
B::E::type t2 = B::E::b;
}

It's a bit more to type, but what can I say ;)

Note that the following:

struct A {
using MyCoolEnum;
};

makes VC2003 choke. So, I guess the first implementation is better ;)

Best,
John

--
http://John.Torjo.com -- C++ expert
... call me only if you want things done right

Neal E. Coombes

unread,
Sep 19, 2007, 7:29:39 PM9/19/07
to
> struct A
> {
> // for compatibility to old client code put B::E into struct A
> #if 1 // d) imports B::E, B::e is different and incompatible to A::e
> typedef B::E E;
> enum { e = B::e };
> #endif

// what about

typedef B::E E;
static const E e = B::e;

>
> static enum B::E func(B::E) { return B::e; }
>
> };

Dave Harris

unread,
Sep 19, 2007, 7:30:48 PM9/19/07
to
kurt....@siemens.com (Kurt Stege) wrote (abridged):

> For some reasons of restructuring, I would like to move
> the enum to another class (or namespace) B, without breaking
> existing client code.
> [...]

> #if 0 // c) imports B::E, but not B::e
> typedef B::E E;
> #endif

It's close, though, and heading in the right direction. This should work:

struct B { enum E { e }; };

struct A {

typedef B::E E;
static const E e = B::e;

};

// Test code
A::E sourceA() { return A::e; }
B::E sourceB() { return B::e; }

void sinkA( A::E arg ) {
switch (arg) {
case A::e: break;
}
}

void sinkB( B::E arg ) {
switch (arg) {
case B::e: break;
}
}

void test() {
sinkA( sourceA() );
sinkB( sourceB() );
sinkA( sourceB() );
sinkB( sourceA() );
}

The above compiles with http://www.comeaucomputing.com/tryitout/ . You
will now be able to take the address of A::e when you couldn't before,
but hopefully that won't hurt anyone.

In my experience life is easier if you put enums in namespaces rather
than structs.

-- Dave Harris, Nottingham, UK.

Kurt Stege

unread,
Sep 20, 2007, 12:21:48 PM9/20/07
to
john...@torjo.com wrote:
> On 19 Sep, 18:25, Kurt Stege <kurt.st...@siemens.com> wrote:

>>I have written a library like following example:

> One extra layer of indirection ;)

Too late...

> It's a bit more to type, but what can I say ;)

... for it would break already existing client code.

Thanks,
Kurt.

(Note: Sometimes I hate Thunderbird. Using copy and paste
seems to destroy the indentation marks for cited text,
as I see now. Sorry for this inconvenience in this and my
previous posting.)

{ You may try Edit > Paste As Quotation (Ctrl+Shift+V). -mod/sk }

--

Kurt Stege

unread,
Sep 20, 2007, 6:21:34 PM9/20/07
to
Dave Harris wrote:
> kurt....@siemens.com (Kurt Stege) wrote (abridged):
>
>>For some reasons of restructuring, I would like to move
>>the enum to another class (or namespace) B, without breaking
>>existing client code.

> struct B { enum E { e }; };


>
> struct A {
> typedef B::E E;
> static const E e = B::e;
> };

Yes, this should work. This bit I was missing.

Alas, the most heavily used compiler in our company,
MSVC6 (sic), even chokes on these lines:

struct C
{
static const int i=0;
};

I can't believe, but it supposes I would like to make
a virtual function abstract, and tells me that i is
not a function. When I change the 0 to 1, I get a
second error message for that line that tells me to
use "= 0" instead...

So I actually have to use only a declaration in the
class definition for the enumeration constants and
define (and initialize) that constants in an implementation
file. That will work, but I guess, under these circumstances
I forget this step of re-factoring.

> You
> will now be able to take the address of A::e when you couldn't before,
> but hopefully that won't hurt anyone.

This should not be a problem.

> In my experience life is easier if you put enums in namespaces rather
> than structs.

You are suggesting to put each enum in an own namespace, I guess.
That might be a good idea in general. But in this case, it does
not help in copying an enum type with all its values.
(Yes, it would help for my very first problem, as I see now.)

My real problem is, that my old library with enum A looks like:

namespace mylib
{
class myclass
{
public:
enum A { ... };
// and all the stuff for what myclass has been invented.
}
}

And for new features I decided to use enum A as well in other
places and now would like to move it this way:

namespace mylib
{
enum A { ... };
class myclass
{
// all the stuff for what myclass has been invented.
}
}

Changing the library in this way would be no problem, except
for old client code that already acesses mylib::myclass::A
and its values.

However, you had been right: Putting all enums into namespaces
and *not* into classes would have helped a little bit. There
is one specific reason why I would like to move that enum,
beyond beauty of code. Other classes that use enum A now
have to include myclass.h with all that stuff that has
nothing to do with the single enum they actually need.
Maybe I even run into trouble for recursive inclusion of
header files due to this construction.

Best regards,
Kurt.

0 new messages