1

I want to use constexpr instead of #defines wherever possible, for type safety and namespace features.

Unfortunately, I get this error: 'reinterpret_cast<SPI_TypeDef*>(1073756160)' is not a constant expression when trying.

#include <stm32f0xx.h> // #defines SPI2 as pointer to a struct of volatile unsigned ints

constexpr auto myPort = SPI2;

I'm not looking for an explanation of why reinterperet_cast cannot be used in a constexpr.

What is the modern C++ way to have a constexpr pointer to some memory mapped hardware?

One reason for this is to use these constexpr values in templated code.

Cameron Tacklind
  • 5,764
  • 1
  • 36
  • 45

3 Answers3

2

constexpr code wasn't invented so that you could avoid using #defines; it's there so that you can do certain things with expressions that you couldn't otherwise. You can pass constexpr pointers or integers as template parameters, for example, since they are constant expressions.

Basically, the primary purpose of any constexpr variable or function is to be able to be used within compile-time programming. So to declare a variable to be constexpr is to say "this is a compile-time constant and it's reasonable to use it at compile-time."

A pointer whose value is an arbitrary address cannot be used at compile-time. So marking such a pointer as a compile-time value is a contradiction. So you're not allowed to do it. constexpr pointers are required to be real pointers, which are either null pointers or point to actual objects. Not to arbitrary addresses.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • This is exactly why I'd like to use `constexpr`. I'd love to be able to write templated code that takes a pointer as the template argument. Where the pointer points is *known* at compile time. That's the whole point of memory mapped hardware. Any offsets from that base address are also known at compile time. Of course the value pointed to by those pointers cannot be known at compile time. That's why the pointers are `constexpr` to `volatile uint32_t`. But comparing those pointers, for instance, could absolutely happen at compile time. – Cameron Tacklind Apr 04 '21 at 20:47
  • @CameronTacklind: But it's not a pointer *to* anything; it's just a number. In constexpr coding, pointers aren't addresses; they point at objects. The C++ object model is *real* in constexpr code, so you can't just make up a number and pretend that it's a meaningful pointer. They can only point at an object or null. "*That's the whole point of memory mapped hardware.*" Your compiler can't do "memory mapped hardware". – Nicol Bolas Apr 04 '21 at 21:44
  • 1
    @CameronTacklind: If you'd "love to be able to write templated code that takes a pointer as the template argument." - you better update your question accordingly to get better answers. – Chilippso Apr 05 '21 at 06:05
0

It's not possible. Even std::bit_cast, which can in certain cases emulate reinterpret_cast at compile-time, loses its constexpr-ness when one of the involved types is a pointer.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
0

Like other answers already state, it is not possible for arbitrary pointers.

If it is "for type safety and namespace features [...] to some memory mapped hardware" you are asking for, why you don't just use

// assumed preconditions, since not provided in question
typedef struct {
  volatile unsigned int a;
  volatile unsigned int b;
} SPI_TypeDef;

SPI_TypeDef* SPI2 = (SPI_TypeDef*)0x12345678;

// actual answer
SPI_TypeDef* const myPort = SPI2;

This way your pointer myPort to some data of type struct SPI_TypeDef is const, but not the pointed-to struct.

const keyword is generally "left-assigning".

Chilippso
  • 451
  • 2
  • 9
  • `error: cannot convert 'SPI_TypeDef*' to 'volatile unsigned int* const' in initialization` – Cameron Tacklind Apr 04 '21 at 20:43
  • You may provide the code excerpt where `SPI2` is defined. I assume it is a simple integral `#define` for a memory location (i.e. pointer). If it is already typed as `SPI_TypeDef*` you may better use `SPI_TypeDef* const = SPI2`. – Chilippso Apr 05 '21 at 05:16