views:

429

answers:

7
typedef enum BeNeLux
{
   BELGIUM,
   NETHERLANDS,
   LUXEMBURG
} _ASSOCIATIONS_ BeNeLux;

When I try to compile this with C++ Compiler, I am getting errors, but it seems to work fine with a C compiler. So here's the question. Is it possible to pack an enum in C++, or can someone see why I would get the error?

The error is:

"semicolon missing after declaration of BeNeLux".

I know, after checking and rechecking, that there definitely is a semicolon there, and in any places required in the rest of the code.

Addendum:

_PACKAGE_ was just an example. I am renaming it.

_ASSOCIATIONS_ is not a type of BeNeLux:

#define _ASSOCIATIONS_ __attribute__((packed))

The code is iffed, but only to make sure it is GNU C/C++.

#if defined (__GNUC__) 
#define _ASSOCIATIONS_ __attribute__((packed))
#else
#define _ASSOCIATIONS_

Would this cause problems? I thought (GNUC) worked for both C and C++

Addendum 2:

I even tried

#ifdef __cplusplus
extern "C" {
#endif

    typedef enum BeNeLux
    {
       BELGIUM,
       NETHERLANDS,
       LUXEMBURG
    } _ASSOCIATIONS_ BeNeLux;

#ifdef __cplusplus
}
#endif

No joy. Anyone?

Note: -fshort-enums is not a possibility; looking for a programmatic solution.

A: 

I suppose you're using GCC and G++. The code compiles fine with either, for me. It would be rather suprising to see such a feature disappear when enabling C++ on any one particular compiler.

Make sure that your #define is not #if'ed out for C++ code, e.g. #ifndef __cplusplus.

Try g++ -E to see the preprocessor output and verify that the #define appears.

Also, even for preprocessor macros, names beginning with an underscore and capital letter or two underscores are reserved for the compiler and library. If you must have a macro, PACKED might be the best name for it.

Potatoswatter
Added that code directly without the #ifs and it still did not work.
Sagar
@Sagar: try both `gcc -v` and `g++ -v` to make sure you're getting the same version of both.
Potatoswatter
According to the manual http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_5.html#SEC105 this should work even in GCC 2.95.
Potatoswatter
A: 

In C++, you don't need the typedef. Just start with enum BeNeLux. It's also possible (I can never remember) that declaring a type and a variable with the same identifier may not be legal in one of the languages.

Adrian McCarthy
the addendum makes clear that's not what he wants. Declaring type and identifier simultaneously is impossible in both languages.
Potatoswatter
I mean, declaring `typedef` and identifier simultaneously is impossible in both.
Potatoswatter
@Potatoswatter: Huh?
Adrian McCarthy
A: 
enum BeNeLux
{
   BELGIUM,
   NETHERLANDS,
   LUXEMBURG
};

This is what is expected of C++ code.

DeadMG
the addendum makes clear that's not what he wants.
Potatoswatter
No, it doesn't. If he just used this, then he would be finished.
DeadMG
@DeadMG: No. The question is for "typedef enum" and attribute packing. I know enum BeNeLux would work, but that is not what I need.
Sagar
+1  A: 
#if defined (__GNUC__)
#  if defined (__cplusplus)
#     define _ASSOCIATIONS_(X) __attribute__((packed))
#  else
#     define _ASSOCIATIONS_(X) __attribute__((packed)) X
#  endif
#else
#  if defined (__cplusplus)
#     define _ASSOCIATIONS_(X)
#  else
#     define _ASSOCIATIONS_(X) X
#  endif
#endif

typdef enum BeNeLux {
  BELGIUM,
  NETHERLANDS,
  LUXEMBURG
} _ASSOCIATIONS_ (BeNeLux);

This seems to compile in my g++ (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu4)

Meera
Hi Meera, it works for us with g++ versions above 4 too. The problem is we have to use version 3.3.5 or lower (above comments).
Sagar
I made another try... http://stackoverflow.com/questions/2791739/c-packing-a-typedef-enum/2916024#2916024
Meera
+1  A: 

I don't think that there is something that does exactly what you want here. I assume you are trying to create a type which is the smallest type for the enum's range.

If you need this type of control, I would recommend something like this:

typedef unsigned char BeNeLux;
static const BeNeLux BELGIUM = 0;
static const BeNeLux NETHERLANDS = 1;
static const BeNeLux LUXEMBURG = 2;

not quite as pretty and possibly a little less type safe. But has the effect that you want. sizeof(BeNeLux) == 1 and you have a named constant for all values in the range. A good compiler won't even allocate a variable for static const integer values so long as you never attempt to use the address of it.

Evan Teran
Thank you sir! That worked awesomely :D
Sagar
A: 

There are no real breakthroughs here. I just reordered things in the hopes that your compiler would like it better. I did not have your version of gcc or g++ so I could not test with those. I did run it through version 3.4.5 gcc and g++ (mingw special) which both warned 'packed' attribute ignored when ordered like your code, but did not complain about mine.

#ifdef __GNUC__
#define attribute(x) __attribute__((x));
#else
#define attribute(x)
#endif


#ifdef __cplusplus
extern "C" {
#endif

enum BeNeLux
{
    BELGIUM,
    NETHERLANDS,
    LUXEMBURG
} attribute(packed);
// I declared attribute to look like a f() so that it would not look like I was
// declaring a variable here.

#ifndef __cplusplus
typedef enum BeNeLux BeNeLux; // the typedef is separated into a separate stmt
#else
}
#endif
nategoose
A: 
#if defined (__GNUC__)

#  if defined (__cplusplus)
#     define ENUM enum
#  else
#     define ENUM typedef enum
#  endif

#  if defined (__cplusplus)
#     define _ASSOCIATIONS_(X) __attribute__((packed))
#  else
#     define _ASSOCIATIONS_(X) __attribute__((packed)) X
#  endif
#else
#  if defined (__cplusplus)
#     define _ASSOCIATIONS_(X)
#  else
#     define _ASSOCIATIONS_(X) X
#  endif
#endif

ENUM BeNeLux {
  BELGIUM,
  NETHERLANDS,
  LUXEMBURG
} _ASSOCIATIONS_ (BeNeLux);

Another snippet. see the new #define ENUM

Meera