Is not the address of a variable?

Вот такой незамысловатый код. Хочу использовать в качестве параметра шаблона адрес регистра, заданный численно.

#define PORT_A  (uint32_t*)0xAABBCCDD

template<uint8_t PIN, uint32_t* ptr> 
class _PIN {
   public:
}; 

template<>  
class _PIN< 12,  PORT_A> {};

void setup() {}

void loop() {}

Можно загнать в Ардуино ИДЕ и скомпилировать для любой платы, хоть для Уно. Выдает ошибку:

sketch_jul28a:7:36: error: '52445' is not a valid template argument for 'uint32_t* {aka long unsigned int*}' because it is not the address of a variable
 template<>  class _PIN< 12,  PORT_A> {};
                                    ^
exit status 1

То есть как это “не адрес переменной”?! а что это???

Если выбрать какую-нить плату позаковыристей, типа СТМ32 - добавляется еще одна ошибка

sketch_jul28a:1:17: error: reinterpret_cast from integer to pointer
 #define PORT_A  (uint32_t*)0xAABBCCDD
                 ^~~~~~~~~~~~

Я так понимаю, что суть именно в этом - новые версии С++ запрещают кастить инт в адрес.
И как это обойти? Например в СТМ32 все адреса регистров заданы именно такими дефайнами, как в первой строке моего примера.

Нашел вот такое решение, работает

#define PORT_A  (uint32_t*)0xAABBCCDD

struct __gen_struct_PORT_A { static __attribute__((always_inline)) inline volatile uint32_t * r() { return PORT_A; } };

template<uint8_t PIN, typename _GPIO> class _PIN {
public:
}; 

template<>  class _PIN< 12,  struct __gen_struct_PORT_A > {};


void setup() {}

void loop() {}

но сказать что я очень смутно понимаю, что тут происходит - ничего не сказать.
Похоже используется структура для генерации нужного значения на лету. Но синтаксис этот я могу пока только тупо копировать…

1 лайк

Ну, эта идея (так же как и две в том топике, что я привёл) на самом деле сводится к одному и тому же главному приёму - “следите за руками”:

  1. В параметрах шаблона должны быть константы
  2. К константам не применим reinterpret_cast, а значит нет способа преобразовать один указатель к другому

Собственно, беда в этом, а вовсе не в том, что нельзя числа к указателям преобразовывать. Можно, но тогда они не константы, а для шаблонов они должны быть константами.

Что ни придумаете для обмана шаблона то и хорошо. Вот мужик вычитание константных указателей использовал - прикольно :slight_smile:

2 лайка

спасибо!