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@xxxxxxxxxxxxx>: > 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@xxxxxxxxx] >> Sent: Sunday, 03 September, 2017 22:20 >> To: gcc-help@xxxxxxxxxxx >> 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