Я пишу класс для настройки последовательного порта на микроконтроллере AVR.У меня есть шаблонная функция, которая принимает в качестве параметров значение тактовой частоты процессора и желаемую скорость передачи данных, выполняет быстрый расчет, проверяет, находится ли фактическое значение в пределах 1,5% от требуемого значения с помощью статических подтверждений, а затем возвращает фактическое значение для установки внутри.8-битный регистр.Мне нужно использовать std :: round, и его возвращаемое значение должно быть constexpr, чтобы все оценивалось во время компиляции.Это проблемный бит:
#include <cmath>
template<int c, int b>
constexpr int UBRRValue() {
// return the value for UBRR register to get close to the desired baud rate
// avoid integer division
return std::round( static_cast<float>(c) / ( 16 * b ) - 1 );
}
int main() {
constexpr auto val = UBRRValue<2000,25>();
return val;
}
Это прекрасно работает для x86 в проводнике компилятора, он возвращает 4. На AVR нет cmath, float round (float) определен в math.h и реализован в сборке, так что, вероятно, не constexpr.После быстрого поиска я нашел это: https://stackoverflow.com/a/24348037/11221049 Я сделал несколько настроек, чтобы затем gcc указал, что эта функция не является constexpr.Я сделал это constexpr, но тогда его результат никогда не будет constexpr, потому что он требует доступа к члену объединения, который не был инициализирован.Союз трюки не являются constexpr.Итак ... возможно ли сделать функцию constexpr round (зная, что что-то из math.h написано непосредственно в ассемблере)?Как это делается в gnu libc ++?