constexpr 静态数据成员导致未定义的引用错误

3

我正在开发一个内核,我希望将我的静态数据成员 constexpr 化,这样我就可以在 enum class 中使用它的值。然而,如果我这样做,我会得到一个未定义的引用错误。只有当我将其非constexpr 并在类外初始化时,它才有效。

有效的代码:

// terminal.hpp
class Terminal
{
    static uint32_t col_map[16];
};

// terminal.cpp
uint32_t Terminal::col_map[16] = {
    0x000000, 0x0000AA, 0x00AA00, 0x00AAAA,
    0xAA0000, 0xAA00AA, 0xAA5500, 0xAAAAAA,
    0x555555, 0x5555FF, 0x55FF55, 0x55FFFF,
    0xFF5555, 0xFF55FF, 0xFFFF55, 0xFFFFFF
};

不起作用:

// terminal.hpp
class Terminal
{
    constexpr static uint32_t col_map[16] = {
        0x000000, 0x0000AA, 0x00AA00, 0x00AAAA,
        0xAA0000, 0xAA00AA, 0xAA5500, 0xAAAAAA,
        0x555555, 0x5555FF, 0x55FF55, 0x55FFFF,
        0xFF5555, 0xFF55FF, 0xFFFF55, 0xFFFFFF
    };

    enum class Color : uint32_t
    {
        Black = col_map[0],
        White = col_map[15]
    };  
};

请注意,我尝试在普通编译器上复现这个问题但没有成功,因此我认为它与内核或交叉编译器有关。
链接器错误:
terminal.o: In function `Terminal::drawcolormap()':
terminal.cpp:(.text+0x6f): undefined reference to `Terminal::col_map'

我总是运行make clean; make命令。


请问确切的错误信息是什么?在构建之前,您是否进行了清理操作? - cdhowie
可能是重复问题:Undefined reference to static constexpr char[] - Shafik Yaghmour
1个回答

7

如果一个静态数据成员被odr-used,则必须在类外定义——无例外

如果数据成员是constexpr,则它也必须在类定义内进行初始化。但是这不免除了在类外定义的要求。

正确的代码:

class Terminal
{
    constexpr static uint32_t col_map[16] = { /* ... */ };
    // ...
};
constexpr uint32_t Terminal::col_map[16]; // definition

这可能有点出人意料,但事实就是如此。


实际上这并不那么违反直觉,你可以获取包含在数组中的变量的地址,因此必须提供一个能够容纳静态数据的源文件。 - Jack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接