reinterpret_cast is not a constant expression - needed help to find solution

Zygmunt Ptak zygmuntptak@gmail.com
Mon Oct 2 21:57:00 GMT 2017


Hi Jens,

This helps just a little.
I figure out that I can use something like:

template<typename RegType, intptr_t ptr>
class Register {
RegType & reg() { return *reinterpret_cast<RegType*>(ptr); }
};

and then, here is important:
I have to use this:

const intptr_t reg_value_b = reinterpret_cast<intptr_t>(&PORTB);
typedef Register<volatile uint8_t, reg_value_b> RegisterPortB;

instead of this:

typedef Register<volatile uint8_t, reinterpret_cast<intptr_t>(&PORTB)>
RegisterPortB;

// second case will tell you that reinterpret_cast is not constexpr.

Overall in my case non-constexpr for reinterpret_cast sucks. I'm
taking few more bytes in final binary (just for very simple code).
If I will use in every part of my code there can be a case when I will
not have enough memory.

Would be great to disable that somehow in gcc. For now I'm not able
change my code.

Best Regards
Zygmunt

2017-09-05 11:52 GMT+02:00 Kilian, Jens <jens.kilian@advantest.com>:
> Hi Zygmunt,
> You could try changing the second template parameter to an actual pointer (the register address before casting) and apply the reinterpret cast to it in the reg() function.
>
> Hope this helps,
>
>         Jens.
>
>> -----Original Message-----
>> From: Zygmunt Ptak [mailto:zygmuntptak@gmail.com]
>> Sent: Sunday, 03 September, 2017 22:20
>> To: gcc-help@gcc.gnu.org
>> Subject: reinterpret_cast is not a constant expression - needed help to
>> find solution
>>
>> Hi,
>>
>> I have a code for AVR written in c++.
>> To get the same size result as C code I'm using template classes.
>> For example:
>>
>> #define AVR_REG_TO_U16(REG) (reinterpret_cast<u16>(& REG))
>>
>> template<typename RegType, u16 reg_r>
>> struct Register
>> {
>>     typedef Register<RegType, reg_r> Type;
>>     constexpr Register<RegType, reg_r>() {}
>>     static RegType & reg() { return *reinterpret_cast<RegType*>(reg_r); }
>>     void operator = (RegType value) { reg() = value; }
>>     void setBit(RegType value)   { reg() = static_cast<RegType>(reg()
>> | 1 << value); }
>>     void dropBit(RegType value)  { reg() = static_cast<RegType>(reg()
>> & ~(1 << value)); }
>>     void clear()                 { reg() = 0; }
>>     void setBits(RegType mask)   { reg() = static_cast<RegType>(reg()
>> |  mask); }
>>     void clearBits(RegType mask) { reg() = static_cast<RegType>(reg()
>> & ~mask); }
>>     operator RegType() { return reg(); }
>> } __attribute__((packed));
>>
>> // and finally:
>>
>> Register<volatile uint8_t, AVR_REG_TO_U16(PIND)> pin_d;
>> pin_d.setBit(1);
>>
>> Everything works pretty cool on old compiler.
>> But on newer (in my case gcc-7.1.0) there is an error:
>>
>> error: 'reinterpret_cast<volatile uint8_t* {aka volatile unsigned
>> char*}>(41)' is not a constant expression
>>
>> I tried found some solution, but nothing.
>> All the time the same problem.
>> Is it possible to turn off that option?
>>
>> I understand that this type of the code doesn't make a sens on PC, but
>> on AVR it really does.
>>
>> Of course that simple example looks like not having any benefit.
>> But it has, compiler nicely optimize code and as I said I'm able to
>> get the same size of the code like in pure C.
>> Size is really matter here with 2kB of the SRAM on atmega328p.
>> I don't want to use pure C. I want to use C++ which is better for my
>> project.
>>
>> Best regards
>> Zygmunt Ptak



More information about the Gcc-help mailing list