所以我得到了一个类,它为每种类型指定一个具有特殊含义的常量。 我使用这样的东西
template<class Type>
class SpecialKeyProvider
{
static const Type SPECIAL_KEY;
}
有一个或多个类型的特化,也将使用但不是数字。 所以我在类定义之外初始化静态成员,就像我必须:
// This seems to have to be in a cpp as having it in the same header,
// will result in duplicate definitions of SPECIAL_KEY;
// This particular instantiation is kind of problematic anyways, see
// the end of my question for another question on this one.
template<>
string SpecialKeyProvider<string>::SPECIAL_KEY = "__SPECIAL";
template <class Type>
Type SpecialKeyProvider<Type> = std::numeric_limits<Type>::max();
不幸的是,SpecialKeyProvider用于非常集中的Container类。此容器有许多方法,出于性能原因应该内联,并在许多地方使用。所以我将整个容器放在头文件中。但是现在使用了SpecialKeyProvider,我仍然需要将SpecialKeyProvider.o链接到我项目中的几乎所有二进制文件。
有没有办法摆脱它并在标题中进行模板特化而不会因“多个定义”而出错?
关于字符串常量的第二个问题。
// I know this is bad code but I don't know how to do it better.
template<>
string SpecialKeyProvider<string>::SPECIAL_KEY = "__SPECIAL";
我知道(并且linter提醒我),使用任何类类型的常量通常是一个坏主意,因为构造的顺序不确定(google style guide),特别是字符串。虽然我通常可以使用const char [],但我不知道在这种情况下该怎么做,因为我希望模板可以实例化为字符串。使用模板(即使用我使用SpecialKeyProvider的容器类)而不是char *会非常痛苦。
我非常感谢任何建议。
答案 0 :(得分:1)
将class
与static const
放在头文件中的未命名的名称空间中:
namespace
{
template<class Type>
class SpecialKeyProvider
{
static const Type SPECIAL_KEY;
};
template<>
const string SpecialKeyProvider<string>::SPECIAL_KEY = "__SPECIAL"; //<--- const
template<>
const double SpecialKeyProvider<double>::SPECIAL_KEY = 3.3; //<--- const
}
即使您在头文件中声明变量,也不会导致任何链接器错误;因为每个.cpp
文件都会创建一个不同的未命名namespace
。对于您的情况,您只声明了const
个变量,因此确实存在所有.cpp文件读取相同值的情况。
修改:关于您的第二个问题,我不知道上述方法可能会出现什么问题,因为每个翻译单元都会创建一个不同的const
副本。看看棉绒是否还在抱怨。
答案 1 :(得分:1)
首先,使用需要编译并与每个项目链接的SpecialKeyProvider.cpp没有任何问题。您正在创建一个没有问题的问题。您的makefile或IDE应该能够处理这个问题。
更好的是,静态(或动态)库,其中一个成员是SpecialKeyProvider.o,需要与每个项目链接。再一次,你的makefile或IDE应该能够处理库。
关于谷歌风格指南,这不是最好的之一。它是一种更好地称为C±而不是C ++的语言的风格指南。他们禁止使用非常规引用,因为有时人们可能会感到困惑。在这里,他们禁止使用类类型的静态全局变量,因为有时它可能会导致静态初始化顺序失败。
禁止一些批发,因为在某些情况下人们可能滥用那个东西是恕我直言的坏习惯。哎呀,说出一些狡猾的程序员没有找到滥用方法的C ++的一部分。
确切地说,那些SpecialKeyProvider<Type>::SPECIAL_KEY
的定义中的相互依赖性是否会使静态初始化顺序失败?