So i understand that before a certain C++ verison where scoped enums existed, people simulated the behavior by nested an enum inside a struct, but I also thought about why they didnt just put it inside of a namespace. I found that it is because putting it inside of a struct has type saftey where as a namespace doesnt but I am confused on how this works? I know that if you nest types inside of classes, the class just becomes essentially a namespace for the nested type but how does it provide type safety?
#enum inside struct vs inside name space
68 messages · Page 1 of 1 (latest)
When your question is answered use !solved or the button below to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.
if it belongs only to this struct, define it in struct, else in namespace
??
in the case of nesting an unscoped in enum in a struct to simulate a scoped enum. Id be looking to use it outside the struct
If you go back to the original proposal, you can see some more details as to how people used it:
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1513.pdf
Specifically, people often made the class type have a member variable that stored the enum itself
And also add things like operator< or whatever they needed to it
This is outlined again in the later version of the proposal: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf
im confused looking at the proposal
it has
typedef enum Alert { CndGreen, CndYellow, CndRed };
what is the purpose of this? it declares a type def that has no name
wouldnt it be the same as enum Alert { CndGreen, CndYellow, CndRed };
In C, it was different
something like typedef enum Alert { CndGreen, CndYellow, CndRed } Alert;
makes sense to me
If you didn't use the typedef in C, then you'd have to say enum Alert every time you wanted to name it
same with struct
yes
but in c it would need to be like this no?
typedef enum Alert { CndGreen, CndYellow, CndRed } Alert;
it allows you to use Alert and also enum Alert
unless I am mis understanding the purpose of:
typedef enum Alert { CndGreen, CndYellow, CndRed }
i think it would only allow you to do enum Alert since the typedef doesnt have a name?
It's possible that the proposal may have a typo, I'd think it should be typedef enum { .... } Alert;
Other parts of the proposal just do enum Color_ { ...};
the bigger difference in behaviour between scoped and unscoped enums, isn't about being nested inside some "namespace" or "struct/class name"
it's about what conversions to/from integer work "out of the box"
gotcha okay, thought I was seeing things for a second LOL
;compile
enum class fruit { apple, orange };
int main()
{
int i = fruit::apple;
}
Compiler Output
<source>: In function 'int main()':
<source>:5:18: error: cannot convert 'fruit' to 'int' in initialization
5 | int i = fruit::apple;
| ~~~~~~~^~~~~
| |
| fruit
Build failed
slybach | c++ | x86-64 gcc 15.2 | godbolt.org
unscoped enums implicit conversion to int, but scoped enums dont allow impliti conversions to int id have to manually do it
right
I'm doing it the wrong way around
lol
i think i understand that
but I am more so confused on why (pre scoped enums) wrapping it in a struct creates type safety and wraping it in a namespace doesnt
that, disregard old pieces of code that I definitely did not write
anyway, that's not something you can achieve by just plopping a plain enum inside a namespace
;compile
namespace fruit
{
enum whatever { apple, orange };
}
int main()
{
int i = fruit::apple;
}
Compilation successful
slybach | 24ms | c++ | x86-64 gcc 15.2 | godbolt.org
does this clear anything about your confusion
oh wait, i not understand question at all
if you create a dedicated struct, then by default instances of the struct cannot be converted to int, you'd have to go out of your way to explicitly define the implicit conversion
if that's not clear, then do you expect the code below to work
struct fruit
{
int data = 0;
};
int main()
{
int i = fruit{};
}
because if you do, then we need to start from there
Okay so at first I understood it. Now I am trying it and I am confused. I understand that if you plop an enum into a namespace it still implicitly converts to int, if you use a scoped enum it doesn’t implicitly convert to int, but if you plop an enum inside of a struct, it still implicitly converts to int. You were saying that putting it inside a struct would create type safety but this code compiles fine:
struct test{
private:
test ();
public:
enum color {RED, BLUE};
};
int main() {
test:: color x = test::BLUE; //works
int y = test::BLUE; //works
return 0;
}
Doing above is essentially the same thing as this no?:
namespace Test{
enum color{RED,BLUE};
}
int main() {
test:: color x = test::BLUE; //works
int y = test::BLUE; //works
return 0;
}
sure, but that's also literally not what I wrote
and not what I said to "do" when using a struct
;compile
struct fruit
{
int data = 0;
};
int main()
{
int i = fruit{};
}
Compiler Output
<source>: In function 'int main()':
<source>:8:11: error: cannot convert 'fruit' to 'int' in initialization
8 | int i = fruit{};
| ^~~~~~~
| |
| fruit
Build failed
slybach | c++ | x86-64 gcc 15.2 | godbolt.org
and if you're thinking "but that's not the interface/syntax of an enum", that's because I can't be bothered to complete the thing
and you're also just not gonna get "all around nice syntax" trying to reimplement a scoped enum without scoped enum
I know and I apologize for the confusion. I understand scoped enums, but my confusion was pooping an enum in a struct vs ploping an enum in a name space and I thought you answered that but when I was looking at your code you were using an enum plopped inside a namespace and just a regular struct which I know they don’t convert
The proposals I linked earlier show what is possible when using the "enum in a struct" thing
People doing operator overloads and preventing implicit casting is only possible if you can only use the enum through the struct/class
And that's essentially the entire motivation for why enum class was introduced in the first place
I don't anyone claimed that pooping an enum in a struct would enable "safety" with respect to enum conversion
this indirectly goes back to my point about what scoped enum actually do/change
I personally don't care much about having to do fruit::apple rather than directly apple, enforcing a "longer name" for enum to prevent name collision and whatnot already has solutions in the language that wouldn't require introducing "scoped enum" on top of "unscoped enum"
as far as I'm concerned the bigger point is and has always been about conversions
and my example about putting an unscoped enum in a namespace is specifically to show that this does nothing for conversions
when people say "wrapping an enum in a struct", and when talking specifically for purposes of safer conversions, it's not about just putting the enum definition in a struct, it's about going all the way to make it safer
;compile
class color
{
int data;
public:
color() = default;
explicit color(int value) : data(value) {}
explicit operator int() const { return data; }
static color RED() { return color{0}; }
static color BLUE() { return color{1}; }
};
int main()
{
color c = color::RED();
int i = color::RED();
}
Compiler Output
<source>: In function 'int main()':
<source>:18:23: error: cannot convert 'color' to 'int' in initialization
18 | int i = color::RED();
| ~~~~~~~~~~^~
| |
| color
<source>:9:14: note: explicit conversion function was not considered
9 | explicit operator int() const { return data; }
| ^~~~~~~~
Build failed
slybach | c++ | x86-64 gcc 15.2 | godbolt.org
this is closer to the kind of thing you need to do if you want behaviour similar to a scoped enum, without a scoped enum
@cobalt warren Has your question been resolved? If so, type !solved :)