c++ - 忽略类模板的显式实例化?

标签 c++ c++11 instantiation explicit

我想检查 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()'|**

为什么 static_assert如果 test() 则抛出错误从未被实例化?

最佳答案

你的前提是错误的。 extern template 会阻止函数模板(包括类模板的成员函数)的目标代码生成,但不会阻止类主体的实例化。

编辑: 回答更新后的问题:成员函数是在类中内联定义的,因此编译器仍会对其进行实例化,以便在必要时将其内联。如果您定义的函数不符合行,您将不会收到错误(通过 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();
}

关于c++ - 忽略类模板的显式实例化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33598558/

相关文章:

c++ - 线程池(大概)锁定条件变量和互斥量的问题

c++ - unordered_map如何用树型数据结构高效实现?

c++ - 无法理解零规则中的 C++11 语法

c++ - 在类外定义的模板类中的模板方法

使用 Block 实例化 Java 类

c++ - 如何调用移动构造函数?

c++ - 实现非成员 IO 操作符

python - 使用 __init__.py 加载动态 python 模块时出现问题

c++ - GNU C++ 和 Clang 中的模板实例化

c++ - 如何使用memset清除char数组