class 模板的显式实例化被忽略?
Explicit instantiation of class templates is ignored?
我想检查 extern
关键字是否确实阻止 class 代码在翻译单元中生成:
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
的显式使用中了解到,这应该可以防止为 class 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()
甚至不会被实例化,并再次等待直到在函数的 "finding" 代码之前链接,但看起来代码是在同一个翻译单位。但是,如果我取出 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
会抛出错误?
你的前提是错误的。 extern template
阻止函数模板(包括 class 模板的成员函数)的目标代码生成,但它不会阻止 class 主体的实例化。
编辑: 回答更新后的问题:成员函数是在 class 中内联定义的,所以编译器仍然会实例化它,以便它可以内联它如有必要。如果你定义的函数不在行内,你不会得到一个错误(通过 godbolt 尝试了 GCC 5.2.0)。
#include <type_traits>
template<class> struct always_false : std::false_type {};
template <typename T> class A{
public:
void test();
};
template <typename T>
void A<T>::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();
}
我想检查 extern
关键字是否确实阻止 class 代码在翻译单元中生成:
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
的显式使用中了解到,这应该可以防止为 class 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()
甚至不会被实例化,并再次等待直到在函数的 "finding" 代码之前链接,但看起来代码是在同一个翻译单位。但是,如果我取出 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
会抛出错误?
你的前提是错误的。 extern template
阻止函数模板(包括 class 模板的成员函数)的目标代码生成,但它不会阻止 class 主体的实例化。
编辑: 回答更新后的问题:成员函数是在 class 中内联定义的,所以编译器仍然会实例化它,以便它可以内联它如有必要。如果你定义的函数不在行内,你不会得到一个错误(通过 godbolt 尝试了 GCC 5.2.0)。
#include <type_traits>
template<class> struct always_false : std::false_type {};
template <typename T> class A{
public:
void test();
};
template <typename T>
void A<T>::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();
}