考虑以下代码(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)
它是编译器中的错误吗?还是预期的行为?有什么办法可以解决?