我想在我的代码中消除对 #define 宏的依赖,但是我无法通过 constexpr
实现相同的功能。
为了实际应用,考虑以下示例:
#define PRODUCT_NAME "CloysterHPC"
constexpr const char* productName = PRODUCT_NAME;
class Newt : public View {
private:
struct TUIText {
#if __cpp_lib_constexpr_string >= 201907L
static constexpr const char* title =
fmt::format("{} Installer", productName).data();
#else
static constexpr const char* title = PRODUCT_NAME " Installer";
#endif
};
};
我通过艰难的方式学到了fmt::format()
函数不是一个constexpr
函数,它只是一个运行时函数。我原本期望能够在代码中使用它来更加表达性强,但事实证明我不能这样做。所以我尝试使用std::string
,但是在将代码改为类似下面这样之后,我得到了完全相同的结果:
#define PRODUCT_NAME "CloysterHPC"
constexpr const char* productName = PRODUCT_NAME;
class Newt : public View {
private:
struct TUIText {
#if __cpp_lib_constexpr_string >= 201907L
static constexpr const char* title = std::string{
std::string{productName} + std::string{" Installer"}}.data();
#else
static constexpr const char* title = PRODUCT_NAME " Installer";
#endif
};
};
那么我的误解是什么:
- 我以为可以在
constexpr
上下文中使用fmt
,但这是不正确的。 std::string
在有适当支持的情况下应该是constexpr
的,以便在编译时评估字符串操作,但它似乎并非如此。- 我误解了标准库中
__cpp_lib_constexpr_string
宏的效用。 - C++20 将在
constexpr
上下文中提供更多文本操作的灵活性。
我已经做了功课,发现了 Stack Overflow 上关于类似问题或如何在 constexpr
上下文中使用 std::string
的其他问题:
但是它们都没有清晰地回答我的问题:我如何在编译时连接两个给定的字符串,以正确地摆脱代码中的`#define`宏?
这似乎很简单,因为两个字符串都在编译时已知,并且它们也是`constexpr`。最终目标是获得第三个`constexpr const char*`,其内容为:CloysterHPC Installer
,而不在代码中使用任何`#define`宏。
libstdc++
。gcc-toolset-12-12.0-5.el8.x86_64
gcc-toolset-12-libstdc++-devel-12.1.1-3.4.el8_7.x86_64
注意:有时我在问题中提到字符串时,知道它们不是std::string
,而实际上是const char*
。这只是一种语言约定,而不是类型定义。
std::string
时,其开销很可能是微不足道的。除非你在一个仅有几千字节内存的系统上,否则你很可能会过度优化一个无关紧要的问题。 - tadmanconst
是理想的,但下一个最好的选择是一个可以调用并返回所需内容的函数。除非你每秒打印一百万次产品名称,否则这不会成为问题。 - tadman