Что мешает вычислению этой функции constexpr во время компиляции?
Я работаю над классом для представления набора аппаратных выводов микроконтроллера (STM32). Выбранные контакты могут быть прерывистыми на порте, но предполагается, что они заказаны. Например, если этот объект создан для представления контактов PA2, PA3 и PA6, я хочу иметь возможность сделать такое назначение, которое устанавливает PA2 и PA6 и сбрасывает PA3.
В настоящее время я еще не реализовал ctor для прерывистых контактов. Текущий позволяет отображать только непрерывные выводы, такие как PA2, P3 и PA4. Однако логика отображения сжатых битов (например,
Я думал, что такое задание, как
Вот несколько упрощенная и недоработанная версия кода, который я тестирую. Код выбора порта (GPIOA, GPIOB и др.) Опущен.
#include <cstdint>
volatile uint32_t BSRR {0}; // Assume it's a HW register for atomic pin access.
class PortSegment {
public:
constexpr PortSegment(uint8_t start, uint8_t end)
: selection{calculateSelection(start, end)} {}
uint16_t operator=(uint16_t setVal) const;
// operator uint16_t() const; // to be implemented later
private:
static constexpr uint16_t calculateSelection(uint8_t start, uint8_t end);
static constexpr uint16_t mapBits(uint16_t val, uint16_t selection);
uint16_t selection; // Table of used bits in the port
};
// Used in ctor
constexpr uint16_t PortSegment::calculateSelection(uint8_t start, uint8_t end)
{
uint16_t result {0};
for (unsigned i = start; i <= end; ++i) result |= (1u << i);
return result;
}
// static function
constexpr uint16_t PortSegment::mapBits(uint16_t val, uint16_t selection)
{
uint16_t result {0};
for (unsigned i = 0; i < 16; ++i) {
if (selection & 1u) {
if (val & (1u << i)) {
result |= (1u << i);
}
}
else {
val <<= 1;
}
selection >>= 1;
}
return result;
}
inline uint16_t PortSegment::operator=(uint16_t setVal) const
{
uint32_t mapped {mapBits(setVal, selection)};
BSRR = ((~mapped << 16) | mapped)
& ((static_cast<uint32_t>(selection) << 16) | selection);
return setVal;
}
int main()
{
constexpr PortSegment segment {2,5}; // Use port pins 2,3,4,5
segment = 0b1010u;
}
В
Еще одна странная вещь, которую я обнаружил, если я изменю
Вот код в Godbolt.
1 ответ
Вы установили оптимизацию на уровень 1 в Godbolt! Пытаться
-O3
вместо
-O1
.