使用constexpr函数在g ++中的不同行为 - 7.0 /访问硬件

wim*_*aan 5 c++ reinterpret-cast constexpr

我使用以下代码访问某些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) {}
}
Run Code Online (Sandbox Code Playgroud)

在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>();
Run Code Online (Sandbox Code Playgroud)

我得出的结论是,版本6.2.1不是混淆,7.0是!reinterpret_cast导致非constexpr表达式.

那么,有没有解决方案将寄存器地址声明为constexpr?

wim*_*aan 0

根据 phil1970 的说法,一个可能的解决方案是使用 getBaseAddr() 作为内联函数或别名:

struct Test {
    static void foo() {
        p()->r1 = 42;    
    }
    static constexpr auto p = getBaseAddr<MCU::Timer, 0>;
};
Run Code Online (Sandbox Code Playgroud)