Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   c++0x: Is it possible to make the compiler choose scope if unambiguous? (http://www.velocityreviews.com/forums/t744446-c-0x-is-it-possible-to-make-the-compiler-choose-scope-if-unambiguous.html)

Johannes Bauer 03-02-2011 09:10 PM

c++0x: Is it possible to make the compiler choose scope if unambiguous?
 
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

--
>> Wo hattest Du das Beben nochmal GENAU vorhergesagt?

> 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 <hidbv3$om2$1@speranza.aioe.org>

Michael Doubez 03-02-2011 10:22 PM

Re: c++0x: Is it possible to make the compiler choose scope if unambiguous?
 
On 2 mar, 22:10, Johannes Bauer <dfnsonfsdu...@gmx.de> wrote:
> 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.

--
Michael

Johannes Bauer 03-02-2011 10:27 PM

Re: c++0x: Is it possible to make the compiler choose scope if unambiguous?
 
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.

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

>
> 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

--
>> Wo hattest Du das Beben nochmal GENAU vorhergesagt?

> 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 <hidbv3$om2$1@speranza.aioe.org>

Michael Doubez 03-02-2011 10:47 PM

Re: c++0x: Is it possible to make the compiler choose scope if unambiguous?
 
On 2 mar, 23:27, Johannes Bauer <dfnsonfsdu...@gmx.de> wrote:
> 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).


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.

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

>
> > 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".


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.

--
Michael

Öö Tiib 03-02-2011 10:48 PM

Re: c++0x: Is it possible to make the compiler choose scope if unambiguous?
 
On Mar 3, 12:27*am, Johannes Bauer <dfnsonfsdu...@gmx.de> wrote:
> Am 02.03.2011 23:22, schrieb Michael Doubez:
>
>
> >> myPeriphMemory.TESTDIR = (myPeriphMemory.TESTIS & ~(0x30000)) |
> >> (typeof(enum class Enum))aValue;

>
> > 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".


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.


All times are GMT. The time now is 12:11 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.