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

标签 c++ constexpr reinterpret-cast

我使用以下代码访问某些 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/

相关文章:

c++ - SDL 和 Visual Studio 2010 资源

c++ - 使用constexpr返回函数值C++的模板函数调用

c++ - 如何检测是否有func。是一个常量?并标记其他功能。 constexpr 取决于它?

c++ - `reinterpret_cast` a `T*` 到 `T(*)[N]` 是未定义的行为吗?

c++ - 转换整个 vector

c++ - 定义行为类似于标准 C++ 数据类型的新数据类型

c++ - 在没有任何库的情况下测试数字是否具有十进制值

c++ - 带有 + 的 Cin 输入导致下一个输入为字符串

c++ - constexpr 函数的规则

c++ - 转换为 char* 后写入 std::atomic