Topic: explicit enum' suggestion


Author: andyturner74@yahoo.com
Date: Mon, 16 May 2005 11:23:26 CST
Raw View
What are the advantages / disadvantages to nesting an enum inside a
struct vs. inside a namespace?  Also, regarding the problem of implicit
conversion of enums to ints -- without that we could not use enums
inside switch statements.
Isn't that one of the main usages for enums?

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: cppljevans@cox-internet.com (Larry Evans)
Date: Wed, 18 May 2005 05:39:04 GMT
Raw View
On 05/16/2005 12:23 PM, andyturner74@yahoo.com wrote:
> What are the advantages / disadvantages to nesting an enum inside a
> struct vs. inside a namespace?  Also, regarding the problem of implicit
> conversion of enums to ints -- without that we could not use enums
> inside switch statements.
> Isn't that one of the main usages for enums?
I've found it useful for creating 'named' tuples, i.e. a tuple, t,
whose fields can be accessed with some meaningful name, e.g.
t.get<name>() or t.get<title>() where name and title are
enumerators in some enumeration.

See:

http://boost-sandbox.sourceforge.net/vault/index.php?PHPSESSID=ba2128cee57566d33b8a887632d0affd&direction=0&order=&directory=cppljevans&PHPSESSID=ba2128cee57566d33b8a887632d0affd

in file:

   tuple_nested_enum_test.cpp

and in particular, the

   void test_indexed(void)

function which shows:

   tuple_0.get<index>();

where index is an enumerator in:

       enum
     field_names
     { f_0
     , f_1
     , f_2
     };

HTH.

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Tony" <gottlobfrege@gmail.com>
Date: Sun, 24 Apr 2005 20:23:50 CST
Raw View
REH wrote:
> "Tony" <gottlobfrege@gmail.com> wrote in message
> news:1113940833.589171.51870@z14g2000cwz.googlegroups.com...
> > P.S. currently I often do things like
> >
> > struct Foo
> > {
> >    enum Enum
> >    {
> >       Bar, Etc, More
> >    };
> > };
> >
> Why do you define it inside a struct, and not a namespace:
>
> namespace Foo {
>     enum Enum {Bar, Etc, More};
> }
>
> using Foo::Enum;
>
> Enum tmp = Foo::Bar;
>
>
>
I tend not to use a namespace here because often my enums are inside a
class.  (So, yes, that means 2 levels of scope specifiers. ie
Class::Foo::Bar.)

A real world example would be:

class ImageDisplay
{
 //...
 struct/enum ViewMode
 {
   sizetofit,
   etc
 };

 SetViewMode(ViewMode viewMode);
 //...
};

//...
   foo.SetViewMode(ImageDisplay::ViewMode::sizetofit);

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Tony" <gottlobfrege@gmail.com>
Date: Mon, 25 Apr 2005 10:17:28 CST
Raw View
Nathan Yospe wrote:
> Tony wrote:
> > I don't like that enums don't scope their identifiers:
>
> I actually advise, and have considered mandating, a similar struct
> for my team, for completely unrelated reasons. Because enums don't
> allow for forward declaration, I recommend the following for enums
> that may be passed as function parameters beyond a single header:
>
> --- begin ---
>
> // EnumDeclarationHeader.hxx
>
> struct EnumName {
>     enum inner_name_ {
>         Specifier1,
>         Specifier2,
>         ...
>         SpecifierN
>     };
>     EnumName(EnumName::inner_name_ v): value(v) {}
>     EnumName& operator=(EnumName::inner_name_ v) { value = v; return
> *this; }
>     inner_name_ value;
> };
>
> bool operator==(EnumName const& left, EnumName::inner_name_ right);
> bool operator==(EnumName::inner_name_ right, EnumName const& left);
> bool operator==(EnumName const& left, EnumName const& right);
>
>
> I don't provide a conversion operator in order to discourage usage
> of the raw enumeration type
[...]
>Now, I have my
> doubts about the inner_name_ itself, but I could think of no other
> means of containing an instance...
>
> --
>
> Nathan F. Yospe
> coding standards conformance, core architecture, portability, i18n
> SAP Labs LLC, Los Angeles
>

Yeah, actually, I don't normally do the conversion operator either, I
was just making up the example as I went along without thinking about
it.

In fact, I don't think that I would bother with any of the operators -
I would just let the constructor convert the constants into EnumNames,
It seems less efficient (creating temporaries, etc), but it would all
get optimized away by the compiler.  And it would keep the technique as
light-weight as possible (code/typing wise).

And I agree with the problems of 'inner_name_'.  You really want to
keep it out of bounds, but can't.

Also, you can't make the pattern into a template. I could be a MACRO,
but I hate macros.

And I am definitely going to use the notion of forward-declaring as
another reason to use this idea.  (I don't get to decide the coding
standards, but I do have a say in it...)

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: brangdon@cix.co.uk (Dave Harris)
Date: Tue, 26 Apr 2005 05:22:02 GMT
Raw View
gottlobfrege@gmail.com (Tony) wrote (abridged):
> I tend not to use a namespace here because often my enums are inside a
> class.  (So, yes, that means 2 levels of scope specifiers. ie
> Class::Foo::Bar.)

One advantage of the struct-with-member-variable is that it allows you to
forward declare it. However, you lose that if it is nested inside another
class.

-- Dave Harris, Nottingham, UK.

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Tony" <gottlobfrege@gmail.com>
Date: Tue, 19 Apr 2005 15:10:52 CST
Raw View
I don't like that enums don't scope their identifiers:

enum Foo
{
   Foo_Bar,
   Foo_Etc,
   Foo_More
};

Foo foo = Foo_Bar;

I would prefer:

enum Foo
{
   Bar,
   Etc,
   More
};

Foo foo = Foo::Bar;


I can see 2 ways of allowing this:

1.  Just allow it.  Currently Foo::Bar, where Foo is an enum, is an
error.  Give it the obvious meaning instead.  However, that implies I
can still type just 'Bar', so to be safe I am going to define it as the
'more unique' Foo_Bar.

2. explicit enum:

explicit enum Foo
{
   Bar,
   Etc,
   More
};

Foo foo = Bar; // ERROR! explicit enum requires scope resolution
Foo foo = Foo::Bar;


Thoughts?

P.S. currently I often do things like

struct Foo
{
   enum Enum
   {
      Bar, Etc, More
   };
};

to get the scoping, or even:

struct Foo
{
   enum Enum
   {
      Bar, Etc, More
   };
   Foo(Enum e) : val(e)
   {
   }
   operator Foo() { return val; }

private:
   Enum val;
};

And then Foo acts like and enum, but still requires scope resolution.
But it is a bit of overkill, I think...

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: bogus@nowhere.net (REH)
Date: Fri, 22 Apr 2005 19:43:54 GMT
Raw View
"Tony" <gottlobfrege@gmail.com> wrote in message
news:1113940833.589171.51870@z14g2000cwz.googlegroups.com...
> P.S. currently I often do things like
>
> struct Foo
> {
>    enum Enum
>    {
>       Bar, Etc, More
>    };
> };
>
Why do you define it inside a struct, and not a namespace:

namespace Foo {
    enum Enum {Bar, Etc, More};
}

using Foo::Enum;

Enum tmp = Foo::Bar;




---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Nathan Yospe" <nathan.yospe@sap.com>
Date: Fri, 22 Apr 2005 14:44:35 CST
Raw View
Tony wrote:
> I don't like that enums don't scope their identifiers:

> enum Foo
> {
>    Foo_Bar,
>    Foo_Etc,
>    Foo_More
> };

> Foo foo = Foo_Bar;
>
> I would prefer:

> enum Foo
> {
>    Bar,
>    Etc,
>    More
> };

> Foo foo = Foo::Bar;

> I can see 2 ways of allowing this:

<cut>

> Thoughts?

While I don't have a particular problem with this for readability,
it does raise an ambiguity with regard to scope. As I read it, the
standard ('98; I don't have the '03 handy) specifies (7.2.10) that
braces following an enum-name do not introduce a new scope. I find
your syntax a little inconsistant with this. Perhaps "explicit" is
meant to introduce a scope specifier using the enum-name?

> P.S. currently I often do things like

> struct Foo
> {
>    enum Enum
>    {
>       Bar, Etc, More
>    };
> };

Why not the following?

namespace Foo {
    enum Enum {
        Bar, Etc, More
    };
}

> to get the scoping, or even:

> struct Foo
> {
>    enum Enum
>    {
>       Bar, Etc, More
>    };
>    Foo(Enum e) : val(e)
>    {
>    }
>    operator Foo() { return val; }
>
> private:
>    Enum val;
> };

> And then Foo acts like and enum, but still requires scope resolution.
> But it is a bit of overkill, I think...

I actually advise, and have considered mandating, a similar struct
for my team, for completely unrelated reasons. Because enums don't
allow for forward declaration, I recommend the following for enums
that may be passed as function parameters beyond a single header:

--- begin ---

// EnumDeclarationHeader.hxx

struct EnumName {
    enum inner_name_ {
        Specifier1,
        Specifier2,
        ...
        SpecifierN
    };
    EnumName(EnumName::inner_name_ v): value(v) {}
    EnumName& operator=(EnumName::inner_name_ v) { value = v; return
*this; }
    inner_name_ value;
};

bool operator==(EnumName const& left, EnumName::inner_name_ right);
bool operator==(EnumName::inner_name_ right, EnumName const& left);
bool operator==(EnumName const& left, EnumName const& right);

// SomeOtherHeader.hxx

struct EnumName;

void SomeFunction(EnumName const& enumReference);

// SomeOtherSource.cxx

#include "SomeOtherHeader.hxx"
#include "EnumDeclarationHeader.hxx"

void SomeFunction(EnumName const& enumReference)
{
    EnumName localEnumInstance = enumReference;
    localEnumInstance = EnumName::SpecifierX;
}

--- end ---

I don't provide a conversion operator in order to discourage usage
of the raw enumeration type, and because I consider that operator,
sans an explicit keyword, to be generally undesirable. Until there
is a well-supported explicit specifier for the conversion operator
in the same form as the explicit constructor, I discourage its use
except where strictly required.

I also chose to make the value public because this construct isn't
classlike... it does not logically manipulate its own data. I felt
that exposing the enumerated value was appropriate. Now, I have my
doubts about the inner_name_ itself, but I could think of no other
means of containing an instance...

--

Nathan F. Yospe
coding standards conformance, core architecture, portability, i18n
SAP Labs LLC, Los Angeles

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]