首页 > 解决方案 > constexpr 适用于 Ubuntu,但不适用于 MacOS

问题描述

我有这段代码在 Ubuntu 上编译得很好,但是当我尝试在 MacOS 上编译它时,我得到了这个错误:

Constexpr variable 'HeuristicNames' must be initialized by a constant expression
#define LSHPair std::pair<const char *, LISTSCHED_HEURISTIC>
static constexpr LSHPair HeuristicNames[] = {
    LSHPair("CP", LSH_CP),    LSHPair("LUC", LSH_LUC),
    LSHPair("UC", LSH_UC),    LSHPair("NID", LSH_NID),
    LSHPair("CPR", LSH_CPR),  LSHPair("ISO", LSH_ISO),
    LSHPair("SC", LSH_SC),    LSHPair("LS", LSH_LS),
    LSHPair("LLVM", LSH_LLVM)};

LISTSCHED_HEURISTIC是一个enum

我认为这个错误意味着赋值右侧的某些部分不是 a constexpr,因此结果变量不能是 a constexpr。但是,我对周围的规则没有足够的把握constexpr来理解为什么或如何解决它。

我也不明白为什么这在 MacOS 上与在 Ubuntu 上不同。任何人都可以对此有所了解吗?

标签: c++macosc++11ubuntuc++14

解决方案


首先你不需要宏。你可以定义类型

using LSHPair =  std::pair<const char *, LISTSCHED_HEURISTIC>;

或者只是使用大括号初始化,更干净的是:

using LSHPair =  std::pair<const char *, LISTSCHED_HEURISTIC>;

static constexpr LSHPair HeuristicNames[] = {
    {"CP", LSH_CP},
    {"LUC", LSH_LUC},
    {"UC", LSH_UC},   
    {"NID", LSH_NID},
    {"CPR", LSH_CPR},
    {"ISO", LSH_ISO},
    {"SC", LSH_SC}, 
    {"LS", LSH_LS},
    {"LLVM", LSH_LLVM}
};

正如@CuriouslyRecurringThoughts 指出的构造函数std::pairis a constexprsincec++14

我已经在我的 Mac OS 上对此进行了测试,显然那里的 clang 与 Linux 上的工作方式有些不同(如compiler explorer 所示):

Marek R$ g++ main.cpp -std=c++11
main.cpp:17:26: error: constexpr variable 'HeuristicNames' must be initialized by a constant expression
static constexpr LSHPair HeuristicNames[] = {
                         ^                  ~
main.cpp:18:5: note: non-constexpr constructor 'pair<char const (&)[3], LISTSCHED_HEURISTIC, false>' cannot be used in a constant expression
    {"CP", LSH_CP},
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/utility:446:5: note: declared here
    pair(_U1&& __u1, _U2&& __u2)
    ^
1 error generated.
Marek R$ g++ main.cpp -std=c++14
Marek R$ 

所以 MacOS clang 是对的。

问题必须出在头文件上,并根据 C++ 标准对它们进行版本控制。很可能标准库的相同头文件用于clang,而gcc在Linux上使用。在 Macstd::pair上,构造函数以宏为前缀,该宏_LIBCPP_CONSTEXPR_AFTER_CXX11的定义更改了启用 C++ 标准的行为。在 Linux 上,您必须自己检查它是如何完成的。


推荐阅读