如何避免到处链接某个目标文件
所以我得到了一个类,它为每种类型指定一个具有特殊含义的常量。 我将类似的东西
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 样式指南),特别是字符串。虽然我通常可以使用 const char[] 代替,但我不知道在这种情况下该怎么做,因为我希望为字符串实例化模板。使用模板(即使用我的使用 SpecialKeyProvider 的容器类)和 char* 会非常痛苦。
我真的很感谢任何建议。
So I got a class that specifies a constant with a special meaning for each type.
I use something like this
template<class Type>
class SpecialKeyProvider
{
static const Type SPECIAL_KEY;
}
with one or more specializations for Types that will also be used but are not numeric.
So I initialize the static member outside the class' definition like I have to:
// 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();
Unfortunately the SpecialKeyProvider is used in a very central Container class. This container has lots of methods that should be inlined for performance reasons and is used in numerous places. So I put the whole container in the header file. But now that the SpecialKeyProvider is used, I still have to link SpecialKeyProvider.o to pretty much every single binary in my project.
Is there any way to get rid of that and to do the template specialization in the header without getting an error due to "multiple definitions"?
Second question concerning the string constant.
// I know this is bad code but I don't know how to do it better.
template<>
string SpecialKeyProvider<string>::SPECIAL_KEY = "__SPECIAL";
I know (and the linter reminds me), that using constants of any class type is generally a bad idea due to indeterminant order of construction (google style guide), in particular strings. While I can normally use a const char[] instead, I don't know what to do in this case, since I want the template to be instantiated for strings. Using the template (i.e. using my container class that used the SpecialKeyProvider) with char* instead would be incredibly painful.
I'm really thankful for any advice.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
将带有
static const
的class
放在头文件的未命名命名空间中:即使您在 a 中声明变量,也不会导致任何链接器错误头文件;因为对于每个
.cpp
文件都会创建一个不同的未命名命名空间
。对于您的情况,您只声明了 const 变量,因此可以保证所有 .cpp 文件都读取相同的值。编辑:关于你的第二个问题,我不知道上述方法可能存在什么问题,因为对于每个翻译单元都会创建不同的
const
副本。看看 lint 是否仍然抱怨。Put the
class
withstatic const
in an unnamed namespace in your header file:This will not cause any linker error even if you declare variables in a header file; Because for every
.cpp
file a different unnamednamespace
is created. For your case you have onlyconst
variables declared, so there is an assurity that all the .cpp files are reading the same value.Edit: Regarding your second question, I don't know what could be the problem with the above approach as for every translation unit a different
const
copy will be created. See if the lint still complains.首先,拥有需要编译并链接到每个项目的 SpecialKeyProvider.cpp 并没有什么问题。你正在制造一个本来不存在问题的问题。你的 makefile 或 IDE 应该能够处理这个问题。
更好的是,静态(或动态)库没有任何问题,其成员之一是 SpecialKeyProvider.o,需要与每个项目链接。再次强调,您的 makefile 或 IDE 应该能够处理库。
关于谷歌风格指南,这不是最好的之一。它是一种更适合称为 C±(而不是 C++)的语言的风格指南。他们禁止使用非常量引用,因为有时人们可能会感到困惑。在这里,他们禁止使用类类型的静态全局变量,因为有时这可能会导致静态初始化顺序失败。
禁止某些批发,因为在某些情况下人们可能会滥用该东西,恕我直言,这是不好的做法。哎呀,请说出一些狡猾的程序员尚未找到滥用方法的 C++ 部分。
确切地说,您的那些
SpecialKeyProvider::SPECIAL_KEY
定义中的相互依赖关系在哪里,甚至导致静态初始化顺序惨败?First off, there's nothing wrong with having a SpecialKeyProvider.cpp that needs to be compiled and linked in with every project. You are creating a problem where no problem exists. Your makefile or IDE should be able to handle this.
Better yet, there is nothing wrong with a static (or dynamic) library, one of whose members is SpecialKeyProvider.o, that needs to be linked in with every project. Once again, your makefile or IDE should be able to handle libraries.
Regarding the google style guide, that is not one of the best. It is a style guide for a language better called C± rather than C++. They ban use of non-const references because sometimes people might be confused. Here they ban use of static globals of class type because sometimes it might result in static initialization order fiasco.
Banning some wholesale because under some circumstances people might abuse that thing is IMHO bad practice. Heck, name one part of C++ that some devious programmer hasn't found a way to abuse.
Where, exactly, are the interdependencies in your definitions of those
SpecialKeyProvider<Type>::SPECIAL_KEY
that even make the static initialization order fiasco apply?