c++0x: Is it possible to make the compiler choose scope if unambiguous?

J

Johannes Bauer

Hi folks,

I'm writing a microcontroller abstraction library in C++0x, mainly to
try out how well suited it is for embedded purposes and play around with
some of the new exciting 0x-features.

I have a construction of nested classes, where the outermost defines a
memory map (e.g. a memory-mapped UART representation), then that memory
map has registers (e.g. a baudrate register), those nest bitfields (e.g.
a enum for some clock divider values).

This works actually very beautifully and allows me to do some neat
tricks. There is one small thing, however, where I am not sure how to
solve it more nicely using 0x's features. Consider this innermost class
representing some imaginary clock divider bitfield:

class Bf_CLKDIV {
public:
enum class Enum : uint32_t {
DIVBY2 = 0 << 16,
DIVBY4 = 1 << 16,
DIVBY8 = 2 << 16,
DIVBY16 = 3 << 16,
};
void operator=(enum class Enum aValue) {
myPeriphMemory.TESTDIR = (myPeriphMemory.TESTIS &
~(0x30000)) | (uint32_t)aValue;
}
} CLKDIV;

For the sake of simplicity, consider myPeriphMemory a global variable.
Now in code, I can assign values to that enum quite nicely:

portFoo.TESTDIR.CLKDIV = D_TEST_APB::Reg_TESTDIR::Bf_CLKDIV::Enum::DIVBY4;

However, since "D_TEST_APB::Reg_TESTDIR::Bf_CLKDIV::Enum::" is the only
type which matches operator= "DIVBY4" by itself would be unambiguous.
The compiler obviously rejects

portFoo.TESTDIR.CLKDIV = DIVBY4;

Is there some way, maybe by using the auto keyword to make the above
syntax look nicer? To make to compiler more willing to choose the scope
itself, if it is unambiguous?

And, by the way, since I declared my enum like this

enum class Enum : uint32_t

Is there a way to extract the underlying integer type during compile
time without having it to restate again as I do in:

myPeriphMemory.TESTDIR = (myPeriphMemory.TESTIS & ~(0x30000)) |
(uint32_t)aValue;

with the explicit cast? Something like (imaginary syntax here)

myPeriphMemory.TESTDIR = (myPeriphMemory.TESTIS & ~(0x30000)) |
(typeof(enum class Enum))aValue;

Best regards,
Johannes

--
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <[email protected]>
 
M

Michael Doubez

Hi folks,

I'm writing a microcontroller abstraction library in C++0x, mainly to
try out how well suited it is for embedded purposes and play around with
some of the new exciting 0x-features.

I have a construction of nested classes, where the outermost defines a
memory map (e.g. a memory-mapped UART representation), then that memory
map has registers (e.g. a baudrate register), those nest bitfields (e.g.
a enum for some clock divider values).

This works actually very beautifully and allows me to do some neat
tricks. There is one small thing, however, where I am not sure how to
solve it more nicely using 0x's features. Consider this innermost class
representing some imaginary clock divider bitfield:

class Bf_CLKDIV {
    public:
        enum class Enum : uint32_t {
            DIVBY2 = 0 << 16,
            DIVBY4 = 1 << 16,
            DIVBY8 = 2 << 16,
            DIVBY16 = 3 << 16,
        };

You are already in a class scope, IMO you don't need enum class; plain
enum should be sufficient:

enum Enum : uin32_t { ...
        void operator=(enum class Enum aValue) {
            myPeriphMemory.TESTDIR = (myPeriphMemory.TESTIS&
~(0x30000)) | (uint32_t)aValue;
        }

} CLKDIV;

For the sake of simplicity, consider myPeriphMemory a global variable.
Now in code, I can assign values to that enum quite nicely:

portFoo.TESTDIR.CLKDIV = D_TEST_APB::Reg_TESTDIR::Bf_CLKDIV::Enum::DIVBY4;

I don't see how you can make the economy of the class specifier.
However, since "D_TEST_APB::Reg_TESTDIR::Bf_CLKDIV::Enum::" is the only
type which matches operator= "DIVBY4" by itself would be unambiguous.
The compiler obviously rejects

portFoo.TESTDIR.CLKDIV = DIVBY4;

Is there some way, maybe by using the auto keyword to make the above
syntax look nicer? To make to compiler more willing to choose the scope
itself, if it is unambiguous?

And, by the way, since I declared my enum like this

enum class Enum : uint32_t

Is there a way to extract the underlying integer type during compile
time without having it to restate again as I do in:

myPeriphMemory.TESTDIR = (myPeriphMemory.TESTIS & ~(0x30000)) |
(uint32_t)aValue;

with the explicit cast? Something like (imaginary syntax here)

myPeriphMemory.TESTDIR = (myPeriphMemory.TESTIS & ~(0x30000)) |
(typeof(enum class Enum))aValue;

AFAIK if you remove the 'class', you no longer needed the cast.
 
J

Johannes Bauer

Am 02.03.2011 23:22, schrieb Michael Doubez:
You are already in a class scope, IMO you don't need enum class; plain
enum should be sufficient:

enum Enum : uin32_t { ...

Ah, okay, I didn't know that. I thought that if "class" was omitted the
enum is more weakly typed than the "class enum" (i.e. implicit
conversion to integer is possible). That a enum automatically is a
"class enum" if it appears inside a class is new to me.
AFAIK if you remove the 'class', you no longer needed the cast.

Well, but that is not what I want, I would like to disallow automatic
conversion (i.e. force the cast). This implicit enum-to-int conversion
has always annoyed me since it is quite error-prone. That's actually one
thing I really like about the "class enum".

Best regards,
Johannes

--
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <[email protected]>
 
M

Michael Doubez

Am 02.03.2011 23:22, schrieb Michael Doubez:



Ah, okay, I didn't know that. I thought that if "class" was omitted the
enum is more weakly typed than the "class enum" (i.e. implicit
conversion to integer is possible).

It is weakly typed but the name doesn't leak outside the class
namespace (just like today).
That a enum automatically is a
"class enum" if it appears inside a class is new to me.

Sorry, my phrasing must have been misleading. My point was that I
didn't understand why you would want strong typing, scoping is often
enough.

But If you do need strong typing, you could define it outside the
enclosing class since enum class already provides name scoping. And
use a typedef within the class.
Well, but that is not what I want, I would like to disallow automatic
conversion (i.e. force the cast). This implicit enum-to-int conversion
has always annoyed me since it is quite error-prone. That's actually one
thing I really like about the "class enum".

Ok. You may be able to retreive the layout compatible type from the
size and the signedness.

And define something like:

template<class T>
constexpr to_value(T e) -> enumClassToBase<T>::type
{
return enumClassToBase<T>::type(e)
}

myPeriphMemory.TESTDIR = (myPeriphMemory.TESTIS & ~(0x30000)) |
to_value(aValue);

Worth a try.
 
Ö

Öö Tiib

Am 02.03.2011 23:22, schrieb Michael Doubez:




Well, but that is not what I want, I would like to disallow automatic
conversion (i.e. force the cast). This implicit enum-to-int conversion
has always annoyed me since it is quite error-prone. That's actually one
thing I really like about the "class enum".

You have always disliked implicit conversion and also you want to get
rid of verbose explicit conversion?
Then the only way left is not to convert. Simply ... don't use your
Enum in arithmetics with ints and other annoying types.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top