我使用以下代码访问某些 MCU 寄存器。
#include <stdint.h>
struct MCU {
struct Timer {
volatile uint8_t r1;
template<int N> struct Address;
};
};
template<>
struct MCU::Timer::Address<0> {
static constexpr uint8_t value = 0x25;
};
template<typename Component, int Number>
constexpr Component* getBaseAddr() {
return reinterpret_cast<Component*>(Component::template Address<Number>::value);
}
struct Test {
static void foo() {
p->r1 = 42;
}
static constexpr auto p = getBaseAddr<MCU::Timer, 0>();
};
int main() {
Test::foo();
while(true) {}
}
在 avr-g++ 6.2.1 中这工作正常。但是现在使用 avr-g++ 7.0 我得到了错误:
in constexpr expansion of 'getBaseAddr<MCU::Timer, 0>()'
bm10a.cc:23:58: error: value '37u' of type 'MCU::Timer*' is not a constant expression
static constexpr auto p = getBaseAddr<MCU::Timer, 0>();
我得出的结论是,版本 6.2.1 不符合,而 7.0 符合! reinterpret_cast 导致非 constexpr 表达式。
那么,有什么解决方案可以将寄存器地址声明为 constexpr 吗?
最佳答案
根据 phil1970,一个可能的解决方案是使用 getBaseAddr() 作为内联函数或它的别名:
struct Test {
static void foo() {
p()->r1 = 42;
}
static constexpr auto p = getBaseAddr<MCU::Timer, 0>;
};
关于c++ - g++-7.0/访问硬件中 constexpr 函数的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40684072/