static constexpr char mem[sizeof(GPIO_TypeDef)] {};
static constexpr std::uintptr_t memptr = &mem; // <- this is not working
Проблема с этим фрагментом кода состоит в том, что вам потребуется constexpr reinterpret_cast для второй строки, что не разрешено языком. Я знаю, что это очень распространенный шаблон для встраиваемых устройств, и я лично надеялся, что std :: bit_cast или std :: bless , чтобы рассмотреть это, но похоже, что мы Обойтись без.
Хотя есть способ заставить его скомпилироваться на хост-машине. Вы можете использовать параметр автоматического шаблона следующим образом:
template <auto BASE, std::uint8_t PIN>
class Gpio {};
Функции-члены класса Gpio, в любом случае, должны будут интенсивно использовать reinterpret_cast, поэтому, например, set может выглядеть так:
static void set(uint32_t bit) {
reinterpret_cast<GPIO_TypeDef*>(BASE)->BSRR = 1u << bit;
}
Поскольку параметр шаблона BASE теперь принимает указатели, вы даже можете передать указатель на экземпляр GPIO_TypeDef напрямую (в качестве приятного побочного эффекта это также решает проблему UB, поскольку параметр теперь фактически равен GPIO_TypeDef *):
GPIO_TypeDef mem{};
Gpio<&mem, 0u> gpio_a;
И на вашей цели вы можете продолжать использовать определения из заголовка STM32F7:
Gpio<GPIOA_BASE, 0u> gpio_a;
А также отвечать на вопрос из вашего последнего комментария
Но я совершенно не действительно понимаю, почему это не помогает при использовании constexpr.
Это может иметь две причины.
Создание экземпляра constexpr объекта GPIO_TypeDef также означает передачу указателя на объект const в класс шаблона. В случае, если у вас уже определены какие-либо функции-члены, которые reinterpret_cast в GPIO_TypeDef *, вы получите ошибку, что вы пытаетесь отбросить квалификатор const.
Также вы не можете создать экземпляры constexpr . не буквальные типы . GPIO_TypeDef не является литералом, так как все его члены непостоянны (скрыты за определением, называемым __IO).