header only files tips

當開發header only library時,有時候會需要static or global物件,但因為C++ ODR的原因,
當物件被重複定義時在link階段會報錯。

例如

//X.h
class X
{
public:
  static int m; //這只是declaration
};

//main.cpp
#include "X.h"
int main()
{
  X a;
  a.m = 0;
  return 0;
}


/tmp/ccaFpbvF.o: In function `main':
t.cc:(.text+0x6): undefined reference to `X::m'
collect2: error: ld returned 1 exit status

因為沒有定義

所以需要加上out of class definition, int X::m; (static int default to 0)
但是理論上這是需要library開發者處理的, 使用者只需要include file

但不應該寫在.h檔 因為有可能會出現在多個translation unit內 這樣會違反ODR – one definition rule

最簡單的方式是提供一個cpp 把所有需要定義的變數寫在裡面。
請使用者在編譯時加進去

然而如果是template,這樣子做就行不通了,因為有可能會有使用者自定義的型別,這在一開始是無法知道的。

事實上,碰到static or global需要定義的變數時,可以用
singleton的方式來處理,利用把定義藏在function內,而function本身又是可以被inline來達成

//test.h
template 
class X
{
  X()
  {
    x = T();
  }
public:
  inline static X& get();
  T x;
};

template
inline X& X::get()
{
  static X m;
  return m;
}

//test.cc
#include "test.h"
#include 

int main ()
{
  typedef X XInt;
  XInt& x = XInt::get();
  std::cout << x.x << std::endl;
  return 0;
}

參考: http://en.cppreference.com/w/cpp/language/definition

This entry was posted in C++ Language. Bookmark the permalink.

Leave a Reply