为什么constexpr正在解决重复的定义



我有一个头文件,其中字符串被定义为静态全局。

namespace space {
#define NAME(P) static std::string const s_##P = #P
NAME(foo); NAME(bar); //... other values
#undef  NAME
}

在另一个标头中,定义了一个枚举,模板专用化提供了枚举和space中的字符串之间的映射。

enum class letter { alpha, beta };
template<letter> std::string const & mapping();
#define MAPPING(P1,P2) template<> std::string const & mapping<letter::P1>() { return space::s_##P2; }
MAPPING(alpha,foo)
MAPPING(beta,bar)
#undef  MAPPING

当标头包含在多个翻译单元中时,上面的代码不会链接,因为专业化定义不匹配——这是由于每个翻译单元的全局重新定义(我想(。

将映射函数封装在匿名命名空间中或添加static关键字可以解决链接问题,但编译器会抱怨这些函数是defined but not used [-Wunused-function]

template<letter> static std::string const & mapping();

但是,将专业化定义为constexpr,就不再存在任何链接或警告问题。

template<letter> std::string const & mapping();
#define MAPPING(P1,P2) template<> constexpr std::string const & mapping<letter::P1>() { return space::s_##P2; }

我理解为什么非static版本在链接时失败,以及为什么static版本工作并触发警告。但我不明白constexpr说明符为什么能解决这两个问题。

你能给出一个解释,甚至更好的是,在标准中给出一个理性的解释吗?

函数模板专业化是函数,因此与非模板专业化的函数一样,受一个定义规则的约束。

当函数未声明为staticconstexpr时,您看到的链接器错误是由于同一函数模板专门化的多个定义造成的,每个定义都有外部链接。

添加static时,已将链接设置为内部链接。这使得每个翻译单元都可以安全地包含自己的定义副本。然而,在任何没有调用这些函数的TU中,编译器都知道(由于内部链接(它们也不能从任何其他TU调用,因此无法使用它们。

使用constexpr,函数根据标准隐式内联,但它们的链接不受影响。由于它们是内联的,您可以有多个定义,但由于它们有外部链接,当一个TU不使用它们时,编译器不会抱怨。

用constexpr说明符声明的

函数是内联函数。

来自C++20标准(9.2.5 constexpr和consteval说明符(

1 constexpr说明符应仅应用于变量或变量模板或函数或函数模板。consteval说明符应仅应用于函数或函数模板的声明A函数或使用constexpr或consteval说明符声明的静态数据成员是隐式的内联函数或变量(

相关内容

  • 没有找到相关文章

最新更新