考虑以下代码段(test1.cpp):
#include <string>
extern std::string test_string;
template<std::string &s>
class test{
public:
static void bar(){ }
};
std::string test_string("test string");
void foo(){test<test_string>::bar();}
现在让我们切换最后两行代码(test2.cpp)的顺序:
#include <string>
extern std::string test_string;
template<std::string &s>
class test{
public:
static void bar(){ }
};
void foo(){test<test_string>::bar();}
std::string test_string("test string");
什么都不应该改变.但是如果你通过objdump查看编译文件,你会发现不同之处:
objdump -t -C test*.o | grep bar
在一个案例中,模板测试被实例化为:
test<test_string[abi:cxx11]>::bar()
在另一个作为:
test<test_string>::bar()
两个文件都只是使用编译
gcc -c test*.cpp
因此,将std :: string作为模板参数的引用视为未标记,如果它只是声明为extern.并且它在定义后被视为标记.
我的项目中的一些类被实例化两次,其中应该只有一个类.这是相当不愉快的.
gcc version 5.2.1 20151010 (Ubuntu 5.2.1-22ubuntu2)
这是编译器中的错误吗?或者是预期的行为?
什么是解决方法?
最佳答案 这绝对是一个编译器错误;我找不到GCC Bugzilla中的确切错误,但它看起来与
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66971类似 – 虽然更简单,因为它不需要使用thread_local关键字,它可能具有相同的根本原因.
作为一种解决方法,似乎将引用模板参数更改为指针将使其工作:
template<std::string *s> class test { .... };
void foo(){test<&test_string>::bar();}
编辑:我已经将此错误与gcc一起提交为https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69621