std::string & 在 gcc 5 中作为模板参数和 abi_tag
std::string & as template parameter and abi_tag in gcc 5
考虑以下代码 (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 引用为模板参数,则如果它只是声明为外部,则将被视为未标记。并且它在定义后被视为标记。
我项目中的一些 class 被实例化了两次,而应该只有一个 class。比较不爽。
gcc version 5.2.1 20151010 (Ubuntu 5.2.1-22ubuntu2)
是不是编译器的bug?或者这是预期的行为?
有什么解决方法?
这绝对是一个编译器错误;我无法在 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
考虑以下代码 (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 引用为模板参数,则如果它只是声明为外部,则将被视为未标记。并且它在定义后被视为标记。
我项目中的一些 class 被实例化了两次,而应该只有一个 class。比较不爽。
gcc version 5.2.1 20151010 (Ubuntu 5.2.1-22ubuntu2)
是不是编译器的bug?或者这是预期的行为? 有什么解决方法?
这绝对是一个编译器错误;我无法在 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