为什么constexpr解决重复定义?

问题描述 投票:0回答:2

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

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说明符可以解决这两个问题。

您能给我一个解释,甚至更好,一个合理的标准吗?

c++ constexpr
2个回答
0
投票

用constexpr说明符声明的函数是内联函数。


0
投票

功能模板专长是功能,因此,与非模板专长的功能一样,要遵循一定义规则。

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

添加static后,将链接建立为内部。这样,每个翻译单元都可以安全地包含其自己的定义副本。但是,在未调用这些函数的任何TU中,编译器都知道(由于内部链接)也无法从任何其他TU调用它们,从而使其无法使用。

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

© www.soinside.com 2019 - 2024. All rights reserved.