开发者

How to avoid linking a certain object file everywhere

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 SpecialKeyProvid开发者_高级运维er<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.


Put the class with static const in an unnamed namespace in your header file:

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
}

This will not cause any linker error even if you declare variables in a header file; Because for every .cpp file a different unnamed namespace is created. For your case you have only const 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.


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?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜