And*_*rew 5 c++ gcc templates static-members c++11
我有一个与此类似的问题:
但他们使用的解决方法对我不起作用。
我有一个带有静态数据成员的 CRTP 类,其中一个是 std::mutex。不幸的是,GCC 的 (4.8.2) 链接器给了我这个互斥锁的“未定义引用”错误。Clang (3.4) 没有。有解决方法吗?最初的问题(上面链接)在静态数据成员上调用了复制构造函数,迫使 GCC 发出一个符号,但由于我的数据成员是 std::mutex,这不是一个选项——复制构造函数被删除,然后没有参数构造函数。我只是被冲洗了吗?
我不相信问题出在 std::mutex 上,我认为问题在于 GCC 如何处理依赖默认构造函数的模板类中的静态数据成员。
谢谢你的帮助!
这是我的问题的精简版:test.hh
#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_;
};
Run Code Online (Sandbox Code Playgroud)
测试.cc
#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;
}
Run Code Online (Sandbox Code Playgroud)
主文件
#include <test.hh>
int main() {
Foo foo;
foo.set_bar( 5 );
}
Run Code Online (Sandbox Code Playgroud)
然后我用这个命令编译:
g++ -std=c++0x main.cc test.cc -I.
Run Code Online (Sandbox Code Playgroud)
得到错误
/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
Run Code Online (Sandbox Code Playgroud)
(编辑 1:回应评论者,他认为这是一个重复的错误,“为什么模板必须在头文件中”——将单独的模板专业化放入 .cc 文件而不是放入.hh 文件——如果你有一个互斥锁,并且出于显而易见的原因,你只需要该互斥锁的一个副本,这正是你所需要的。如果你在头文件中声明了一个静态数据成员,那么#includes 标头的每个翻译单元最终都将拥有自己的互斥锁副本,在这种情况下,它无法确保互斥的工作)
(编辑 2:糟糕!我链接到错误的先前错误。)
来自 GCC 的 Jonathan Wakely 在 bugzilla 上的发言:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63876
问题似乎是我没有为互斥体提供初始化程序。其语法是提供左花括号和右花括号
template<> std::mutex CRTP_class< Foo >::mutex_;
Run Code Online (Sandbox Code Playgroud)
变成
template<> std::mutex CRTP_class< Foo >::mutex_{};
Run Code Online (Sandbox Code Playgroud)
(将互斥锁存在于 .cc 文件中没有问题)