我有与此类似的问题:

"undefined reference" to static field template specialization

但是他们使用的解决方法对我不起作用。

我有一个带有静态数据成员的CRTP类,其中之一是std::mutex。不幸的是,GCC的(4.8.2)链接程序给我这个互斥锁一个“ undefined reference ”错误。 lang(3.4)不会。有解决方法吗?最初的问题(在上面链接)调用了强制GCC发出符号的静态数据成员上的拷贝构造函数,但是由于我的数据成员是std::mutex,所以这不是一个选择-复制拷贝构造函数,然后删除不是参数构造函数。我只是在用软管吗?

我不认为问题出在std::mutex上,我认为问题在于GCC如何处理依赖默认构造函数的模板类中的静态数据成员。

谢谢你的帮助!

这是我的问题的一个简短版本:
测试

#include <mutex>

template < class T >
class CRTP_class {
public:
  T * ptr_;
  static std::mutex mutex_; // linker error here
  static int clearly_a_problem_with_mutex_; // no linker error here
};

class Foo : public CRTP_class< Foo >
{
public:
  void set_bar( int setting );
  int bar_;
};

测试文件
#include <test.hh>

template<> std::mutex CRTP_class< Foo >::mutex_;
template<> int CRTP_class< Foo >::clearly_a_problem_with_mutex_( 0 );

void Foo::set_bar( int setting ) {
  std::lock_guard< std::mutex > locker( mutex_ );
  ++clearly_a_problem_with_mutex_;
  bar_ = setting;
}

main.cc
#include <test.hh>

int main() {
  Foo foo;
  foo.set_bar( 5 );
}

然后使用以下命令进行编译:
g++ -std=c++0x main.cc test.cc -I.

得到错误
/tmp/cclyxUfC.o: In function `Foo::set_bar(int)':
test.cc:(.text+0x86): undefined reference to `CRTP_class<Foo>::mutex_'
collect2: error: ld returned 1 exit status

(编辑1:回应评论者的建议,这是一个重复的错误,带有“为什么模板必须放在头文件中”-将单独的模板专长放入.cc文件而不是.cc文件并不奇怪。 .hh文件-在拥有互斥锁的情况下,这确实是您所需要的,由于明显的原因,您只想要该互斥锁的一个拷贝。如果在头文件中声明了静态数据成员,则#包含 header 的每个翻译单元最终都会拥有自己的互斥体拷贝,在这种情况下,互斥体将无法确保相互排斥)

(编辑2:糟糕!我链接到错误的先前错误。)

最佳答案

在bugzilla上来自GCC的Jonathan Wakely:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63876

问题似乎是我没有为互斥量提供初始化器。其语法是提供一个打开和关闭大括号

template<> std::mutex CRTP_class< Foo >::mutex_;

变成
template<> std::mutex CRTP_class< Foo >::mutex_{};

(将互斥体保存在.cc文件中没有问题)

10-08 04:58