如何避免到处链接某个对象文件

时间:2011-07-16 09:03:32

标签: c++ templates linker constants header-files

所以我得到了一个类,它为每种类型指定一个具有特殊含义的常量。 我使用这样的东西

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 *会非常痛苦。

我非常感谢任何建议。

2 个答案:

答案 0 :(得分:1)

classstatic 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的定义中的相互依赖性是否会使静态初始化顺序失败?