【发布时间】:2015-11-08 20:18:23
【问题描述】:
我想检查 extern 关键字是否确实阻止了在翻译单元中生成类代码:
template<class> struct always_false : std::false_type {};
template <typename T> class A{
static_assert(always_false<T>::value, "If this fires, 'A' is instantiated");
};
extern template class A<int>; //error: static assertion failed: If this fires, 'A' is instantiated|
int main(){
// A<int> f;
}
如果这是我唯一的源文件,为什么前面的代码仍然会从static_assert 产生错误?据我从extern 的显式使用中了解到,这应该会阻止为类A<int> 生成任何代码,并且链接器会负责查找稍后的显式实例化定义(在实际编写代码的翻译单元中) ) 来匹配A<int> 的任何使用。
但是,正如编译错误所指示的那样,显式实例化声明似乎正在此翻译单元本身中生成代码。如果我注释掉 extern template class A<int> 一切正常。我使用的是 GCC 4.9.2。但似乎clang 3.5.1 也会引发此错误。
另外,这也会引发相同的断言错误:
template<class> struct always_false : std::false_type {};
template <typename T> class A{
public:
void test() { static_assert(always_false<T>::value, "If this fires, 'test()' is instantiated"); }
};
extern template void A<int>::test();
int main(){
A<int> a;
a.test();
}
在这里,我预计成员函数 A<int>::test() 甚至不会被实例化,并再次等待链接,然后再“查找”该函数的代码,但看起来代码是在同一个翻译单元中生成的。但是,如果我取出static_assert:
template <typename T> class A{
public:
void test() { }
};
extern template void A<int>::test();
int main(){
A<int> a;
a.test();
}
然后我得到了我期望的错误,表明A<int>::test() 没有被实例化并且存在链接器错误:
**undefined reference to `A<int>::test()'|**
如果test() 从未实例化,为什么static_assert 会抛出错误?
【问题讨论】:
标签: c++ c++11 instantiation explicit