#include <iostream>
using namespace std;
typedef struct {
unsigned v;
} GPIO_typedef;
#define PORTA ((GPIO_typedef*)0x04)
#define PORTB ((GPIO_typedef*)0x08)
template< GPIO_typedef* T >
inline
unsigned getPortFlag()
{
//static_assert(false, "not implemented for this target");return 0;
}
template< >
inline
unsigned getPortFlag< PORTA >()
{
return 1;
}
int main() {
// your code goes here
cout<<"Port A flag: "<<getPortFlag<PORTA>()<<"\n";
cout<<"Port B flag: "<<getPortFlag<PORTB>()<<"\n";
return 0;
}
В Keil'е получаю совсем невнятное сообщение, сейчас не приведу, а скинуть с работы забыл
В GCC немного попонятнее:
prog.cpp:22:10: error: template-id ‘getPortFlag<4u>’ for ‘unsigned int getPortFlag()’ does not match any template declaration
unsigned getPortFlag< PORTA >()
^~~~~~~~~~~~~~~~~~~~
prog.cpp:14:10: note: candidate is: template<GPIO_typedef* T> unsigned int getPortFlag()
unsigned getPortFlag()
^~~~~~~~~~~
prog.cpp: In function ‘int main()’:
prog.cpp:32:44: error: no matching function for call to ‘getPortFlag()’
cout<<"Port A flag: "<<getPortFlag<PORTA>()<<"\n";
^
prog.cpp:14:10: note: candidate: template<GPIO_typedef* T> unsigned int getPortFlag()
unsigned getPortFlag()
^~~~~~~~~~~
prog.cpp:14:10: note: template argument deduction/substitution failed:
prog.cpp:32:44: error: ‘4u’ is not a valid template argument for ‘GPIO_typedef*’ because it is not the address of a variable
cout<<"Port A flag: "<<getPortFlag<PORTA>()<<"\n";
^
Но всё равно что-то не догоняю, как правильно сделать.
И еще, похоже я не имею готовить static_assert — по задумке, если не нашлось нужной специализации, то он должен выстрелить, а он сразу стреляет. Хотя, это может из-за того, что со специализацией косяк
Здравствуйте, Marty, Вы писали:
M> я не имею готовить static_assert — по задумке, если не нашлось нужной специализации, то он должен выстрелить, а он сразу стреляет.
Конечно. Если конструкция static_assert(false) написана вне комментариев, то код с ней никогда не скомпилируется — она же всегда ложна.
Конкретно тут компилятор видит, что условие в static_assert не зависит от параметров шаблона, а значит он обязан его вычислить на первой стадии (из двух, которые two-phase name lookup). Он его вычисляет и завершает компиляцию.
То, что ты хочешь, можно сделать перенеся проверку на вторую стадию, например написав static_assert(T != T, ...);
Re[2]: Специализация шаблона функции с параметром не-типом
Проблема в том, что: 1) выделенное определено не мной, а в сторонней библиотеке; 2) Бывает typedef не только GPIO_typedef, а и TIM_typedef, ADC_Typedef etc, и для всех них нужно получить кое-какую информацию в зависимости от типа и конкретного значения
M>Неумею я что-то в сабж.
Дело не в этом. Дело в том, что проблема нерешаема в принципе. Нетиповой (non-type) аргумент шаблона должен быть константным выражением. А твой reinterpret_cast из целочисленной константы (0x04) в указатель нарушает это правило, потому что константное выражение не может содержать reinterpret_cast. У тебя и без специализации ничего не работало.
Если эти тупые define тебе даны от бога (очень похоже на легаси С), то смирись — шаблоны тут неприменимы.
R>и уберите или переосмыслите ваши шаблоны а то их смысл не понятен
Вот "за переосмыслить" я и пришел сюда. Смысл — повторюсь — получить некоторую мною навешенную информацию в зависимости от типа тайпдефа и конкретного значения
M>>Неумею я что-то в сабж. V>Дело не в этом. Дело в том, что проблема нерешаема в принципе. Нетиповой (non-type) аргумент шаблона должен быть константным выражением. А твой reinterpret_cast из целочисленной константы (0x04) в указатель нарушает это правило, потому что константное выражение не может содержать reinterpret_cast. У тебя и без специализации ничего не работало.
V>Если эти тупые define тебе даны от бога (очень похоже на легаси С), то смирись — шаблоны тут неприменимы.
Это SPL от STM — те самые тупые define'ы
Ясно. Спасибо
ЗЫ А constexpr не спасет отца русской демократии?
Просто подумал, что придется в итоге сделать тупую перегрузку функции по типу typedef'а, а там внутри if'ами выбирать результат в зависимости от значения аргумента. В принципе, большой беды не будет, если оно и в рантайме будет работать, но пару байт сэкономить тоже не грех — на некоторых STMках флеша всего 4Кб. Если constexpr привесить, оно в компайл-тайм вычислится?
M>Просто подумал, что придется в итоге сделать тупую перегрузку функции по типу typedef'а, а там внутри if'ами выбирать результат в зависимости от значения аргумента. В принципе, большой беды не будет, если оно и в рантайме будет работать, но пару байт сэкономить тоже не грех — на некоторых STMках флеша всего 4Кб. Если constexpr привесить, оно в компайл-тайм вычислится?
Нет. Потому, что аргумент не будет константным выражением, см. выше. Но если аргумент функции известен на этапе компиляции, то с вероятностью 100% сработает оптимизация, и никаких вычислений в ран-тайме не будет. Можешь проверить asm и убедиться.
Да здравствует мыло душистое и веревка пушистая.
Re: Специализация шаблона функции с параметром не-типом
Спасибо за совет. Правда я в итоге сделал всё далеко не так . Получилось поприятнее, чем у тебя. Показать не могу, сорри — на работе заругают Коротенько опишу только идеи
Тактирование. Нужно получить указатель на функцию тактирования и флаг, который ей передать. Сделал на шаблончиках, некоторая диспечеризация со специализацией шаблонов и на нижнем уровне немного бойлер-плейта с препроцессором и условной компиляцией, потому как семейства STMок отличаются друг от друга, но при внимательном изучении оказалось, что не все так плохо и есть много общего.
За полдня или меньше забил все по F1, F3, F4 — то, что мне непосредственно сейчас нужно. Любая периферия тактируется теперь так:
GPIO. У F3/F4 структуры одинаковые, и ширше, чем у F1 — можно больше комбинаций наплодить, правда, непонятно, а надо ли, что из них будет работать, а что нет —
Поэтому режим пина PinMode свел к enum 1 в 1 как у F1 — для F3/F4 в меру разумения заполнил остальные поля сам.
Сделал структуру GpioPinAddr — там порт и номер пина, сделал класс GpioPin — который принимает GpioPinAddr и режим PinMode — in/out/etc. Если что не так — кидаются ассерты.
Нагенерил макросов PA0-PA15, PB0-... — https://ideone.com/rZY85U
Перегрузил операторы и делаю теперь так: