Hi, after playing hard with this task I was wrong. I reimplemented my structure in few different versions and final ASM code is the same in all cases. Everything is OK and works great. Best Regards Zygmunt 2017-10-02 23:57 GMT+02:00 Zygmunt Ptak <zygmuntptak@xxxxxxxxx>: > 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