1

I have read all the posting regarding this subject. It is understandable that you can not use static variables in constexpr since they are not known until link time. However I do not understand why the compiler will not allow the creation of a static pointer to a truly static address.

We have been converting our code to C++11, due to the "many advantages for embedded programming". This particular issue is troubling. Here are the various attempts to get this to work.

#define PERIPH_BASE   0x40000000U
#define GPIOH_BASE    (AHB1PERIPH_BASE + 0x1C00U)
#define GPIOH         ((GPIO_TypeDef *) GPIOH_BASE)

#define KBATH_NFAULT_GPIO_Port GPIOH

// Attempt #1
const  GPIO_TypeDef* KBATH_NFAULT_GPIO_Port = (GPIO_TypeDef*)GPIOH_BASE;
constexpr DigitalInput BathNFaultK {const_cast<GPIO_TypeDef*> 
    (KBATH_NFAULT_GPIO_Port), BATH_NFAULT_Pin};

// Attempt #2
constexpr GPIO_TypeDef*  KBATH_NFAULT_GPIO_Port = (GPIO_TypeDef*)GPIOH_BASE;
constexpr DigitalInput BathNFaultK {KBATH_NFAULT_GPIO_Port, BATH_NFAULT_Pin};

// Attempt #3
#define STM_PERIPH(a) __builtin_constant_p (a) ? a : a
constexpr DigitalInput BathNFaultK {
    STM_PERIPH((GPIO_TypeDef*)GPIOH_BASE), BATH_NFAULT_Pin};

// Attempt #4
static constexpr inline GPIO_TypeDef* STM_GPIO_PORT(GPIO_TypeDef* p){
    return __builtin_constant_p((p))?(p):(p);
}
constexpr DigitalInput BathNFaultK {
    const_cast<GPIO_TypeDef*>(STM_GPIO_PORT(BATH_NFAULT_GPIO_Port)), 
    BATH_NFAULT_Pin
};

In regular "C", this is acceptable. Is there a solution? Is this fixed in C++17?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
  • *"In regular "C", this is acceptable"* I'm not sure what you mean by that. C language doesn't have a concept of `constexpr`. Plain `const` should work in C++, too. – Igor Tandetnik Oct 07 '18 at 18:44
  • why do you want constexpr? – OznOg Oct 07 '18 at 19:01
  • 1
    What are the error messages for each "attempt"? What did the original C code look like? (so we might have some idea what you are trying to "convert"). – Clifford Oct 07 '18 at 22:24
  • This is something that has been bugging me as well. And although I don't exactly know how "DigitalInput" is defined I guess that all of those expressions would need a reinterpret_cast in order to work which is forbidden in constexpr. The only workaround to really make this work would be to define all memory addresses you need in the linker script. Then you could directly assign from those symbols. – Vinci Oct 08 '18 at 04:57
  • Assuming `struct DigitalInput{ GPIO_TypeDef * port; uint32_t pin; };`, I get an error compiling your attempt 1. The solution to that, I think, is obvious: `const GPIO_TypeDef *` is not of const type, it's nonconst-pointer-to-const. Flip it around to const-pointer-to-(non)const, and it builds: `GPIO_TypeDef * const KBATH_NFAULT_GPIO_Port = (GPIO_TypeDef*)GPIOH_BASE;` I suspect this is your issue, and this question boils down to being a duplicate of https://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int-const-int-const-and-int-const – Sigve Kolbeinson Oct 08 '18 at 12:14
  • Due to the "many advantages for embedded programming"... says who? The C++ compiler vendor? Bjarne Stroustrup? Overall, writing 20 lines for something that can be done in 3 lines isn't an advantage, but a burden. – Lundin Oct 08 '18 at 12:55
  • #define STM_PERIPH(a) __builtin_constant_p (a) ? a : a GPIO_TypeDef *const KBATH_NFAULT_GPIO_Port = STM_PERIPH((GPIO_TypeDef*const)GPIOH_BASE); *** give me this error message: IntrepidSource/src/IntrepidMain.cpp:148:75: error: the value of 'KBATH_NFAULT_GPIO_Port' is not usable in a constant expression constexpr DigitalInput BathNFault {KBATH_NFAULT_GPIO_Port, BATH_NFAULT_Pin}; – Allen Curtis Oct 08 '18 at 21:06
  • Thanks for the feedback regarding the misplacement of const. However this still does not compile for me saying "error: 'reinterpret_cast(1073880064)' is not a constant expression" – Allen Curtis Oct 08 '18 at 21:12
  • There is no `reinterpret_cast` in your question. Try your attempt #1 as written, but move the const. I suggest you edit your question - 1) what is your __purpose__ (how do you want to use`DigitalInput BathNFaultK`; does it need to be `constexpr`, is `const` sufficient)? 2) Provide the definition of `DigitalInput` 3) Do a separate code block per attempt, and include the errors for that attempt underneath it - Attempt #1, Attempt #1 errors, Attempt #2 etc. Saying 'I tried this and got this error, then this and got this error' is clearer than 'I tried all these things and they don't work' – Sigve Kolbeinson Oct 09 '18 at 08:43
  • DigitalInput is a class. You can create a constexpr constructor, not a pure const. All attempts result in the same error, "error: 'reinterpret_cast(1073880064)' is not a constant expression". The code does not contain a reinterpret_cast but that is the error message. – Allen Curtis Oct 12 '18 at 02:22

0 Answers0