c++ - 标题中的模板规范问题
问题描述
我必须将一些代码从 Microsoft Visual Studio 编译器移植到 clang。这让我有些紧张。因为我必须确保代码仍然可以用 MVSC 编译/链接。以下代码是不法行为语料库。重要的是,我无法将代码拆分为 src 和头文件。
编译器:6.0.0-1ubuntu2 和 Visual Studio 2015
C++:版本 14
操作系统:Ubuntu 18.04 和 Windows 10/7
代码在头文件中。我将它包含在几个 src 文件中。
代码:
#ifndef GLOBAL_SETTINGS_
#define GLOBAL_SETTINGS_
#include <cstdint>
namespace global {
enum resolution {
Hz,
kHz,
MHz
};
template<resolution T>
struct sys_clk
{
static const double frequency;
};
#define SYS_CLK_FREQ (115.0e6)
template<> const double sys_clk<Hz>::frequency = SYS_CLK_FREQ;
template<> const double sys_clk<kHz>::frequency = SYS_CLK_FREQ/1.0e3;
template<> const double sys_clk<MHz>::frequency = SYS_CLK_FREQ/1.0e6;
#undef SYS_CLK_FREQ
} // namespace global
#endif /* GLOBAL_SETTINGS_ */
这编译得很好,但链接器发现自己处于无法解决的情况。
链接器错误:
multiple definition of `global::sys_clk_scon<(global::resolution)0>::frequency'
multiple definition of `global::sys_clk_scon<(global::resolution)1>::frequency'
multiple definition of `global::sys_clk_scon<(global::resolution)2>::frequency'
问题:
这个链接器错误如何解决,所以它在 MVSC 和 clang 中编译?
解决方案
不要只专门化静态变量,而是专门化整个类。这将允许您制作变量constexpr
,从而消除在任何 TU 中定义它们的需要。
template<resolution T>
struct sys_clk;
#define SYS_CLK_FREQ (115.0e6)
template<> struct sys_clk<Hz> {
static constexpr double frequency = SYS_CLK_FREQ;
};
template<> struct sys_clk<kHz> {
static constexpr double frequency = SYS_CLK_FREQ/1.0e3;
};
template<> struct sys_clk<MHz> {
static constexpr double frequency = SYS_CLK_FREQ/1.0e6;
};
#undef SYS_CLK_FREQ
需要注意的是,您必须确保它们没有被 odr 使用(获取它们的地址或绑定到它们的引用)。因为那样你的多个定义错误将变成一个未解决的定义错误。
推荐阅读
- build.gradle - 使用带有 minSdkVersion 21 的 desugar 时强制启用 multidex
- catboost - Catboost:更小的安装可能吗?
- .net - 如何在 Linux 容器中重新启动 Azure 函数?
- reactjs - redux 只返回初始状态?
- .net - 在 .Net 5.0 隔离过程函数中使用 SignalR
- javascript - 编辑 Formik 表单时如何禁用输入文件
- php - 如何在资源类中加载嵌套关系的数据
- visual-studio - 如何修复 Visual Studio 中的附加按钮和运行按钮?
- systemd - Puma systemd 重启超时并且似乎失败,即使它实际上已经成功
- json - 如何将对象参数作为哈希表传递给 json arm 模板?