【发布时间】:2018-09-25 16:43:42
【问题描述】:
我很惊讶这里还没有找到我的问题的答案。如果我忽略了,请随时指出我那里。
编辑:我收到通知说这可能与Why can templates only be implemented in the header file? 重复 虽然这包含很多关于编译器如何处理类模板类的有用信息,但我仍然没有找到关于如何处理类所需的静态常量成员的信息,这些成员实际上只需要一次用于所有可能的模板实例化。
我的用例是一个模板化的浮点数到字符串的转换类。一个成员函数应该是创建附加 si 前缀的数字的函数。因此需要一些带有前缀字符的查找数组——这个数组与实际选择的模板浮点类型无关。我做了类似的事情:
// Float2String.h
#include <string>
template <typename FloatType>
class Float2String
{
public:
//...
static std::string withSIPrefix (FloatType floatNumber, int numSignificantDigits)
{
// scale the number, convert it to a string and compute the idx to pick the right prefix...
return floatNumberScaledAndConvertedToString + siPrefixes[idx];
}
private:
static constexpr char[11][3] siPrefixes = {"f", "p", "n", "μ", "m", "", "k", "M", "G", "T", "P"};
};
// Float2String.cpp
#include "Float2String.h"
template <typename FloatType>
constexpr char Float2String<FloatType>::siPrefixes[11][3];
当尝试实际使用它时,例如要转换双数,我收到以下链接器错误:
Error:Undefined symbol 'Float2String<double>::siPrefixes' referenced from:
Error: Float2String<double>::withSIPrefix(double, int) in Main.o
我在 Mac OS 上使用 Clang 并启用 C++ 14 进行编译。
问题:我该如何做?也许用不同的方法可以做得更好?
【问题讨论】:
-
为什么需要在
.cpp文件中定义任何内容? godbolt.org/z/MLUmDm -
@Evg 虽然您的代码 sn-p 在 Godbolt 上编译得很好,但当尝试在仅包含一个源文件的简单命令行项目中编译相同的代码时,它仍然会在我的机器上引发相同的链接器错误。我习惯静态成员需要在单独的编译单元中定义,这就是为什么我将它们放入单独的 .cpp 文件中
-
你可以把你的静态成员变量放在一个只返回它的静态方法中。