简体   繁体   English

显式模板实例化如何影响链接器可以找到的内容?

[英]How do explicit template instantiations affect what the linker can find?

See the following code and please clear my doubts. 请参阅以下代码,请清除我的疑虑。

  1. As ABC is a template, why does it not show an error when we put the definition of the ABC class member function in test.cpp? 由于ABC是一个模板,为什么当我们在test.cpp中放置ABC类成员函数的定义时它不显示错误?

  2. If I put test.cpp code in test.h and remve 2, then it works fine. 如果我在test.h和remve 2中放入test.cpp代码,那么它可以正常工作。 Why? 为什么?

.

// test.h 
template <typename T> 
class ABC { 
public: 
   void foo( T& ); 
   void bar( T& ); 
}; 
// test.cpp 
template <typename T> 
void ABC<T>::foo( T& ) {} // definition 
template <typename T> 
void ABC<T>::bar( T& ) {} // definition 

template void ABC<char>::foo( char & );  // 1 
template class ABC<char>;                // 2 
// main.cpp 
#include "test.h" 
int main() { 
   ABC<char> a; 
   a.foo();     // valid with 1 or 2 
   a.bar();     // link error if only 1, valid with 2 
} 

In both cases you are doing an explicit instantiation. 在这两种情况下,您都在进行显式实例化。 In the second case, only ABC<char>::foo is being instantiated, while in the first case ABC<char>::bar is also being instantiated. 在第二种情况下,只有ABC<char>::foo被实例化,而在第一种情况下, ABC<char>::bar也被实例化。

A different similar example may clarify the implications: 一个不同的类似例子可以澄清其含义:

// test.h
template <typename T>
class ABC {
public:
   void foo( T& );
   void bar( T& );
};
// test.cpp
template <typename T>
void ABC<T>::foo( T& ) {} // definition
template <typename T>
void ABC<T>::bar( T& ) {} // definition

template void ABC<char>::foo( char & );  // 1
template class ABC<char>;                // 2
// main.cpp
#include "test.h"
int main() {
   ABC<char> a;
   a.foo();     // valid with 1 or 2
   a.bar();     // link error if only 1, valid with 2
}

In the example, in main the compiler cannot see foo nor bar definitions, so it cannot instantiate the methods. 在示例中,在main ,编译器无法看到foobar定义,因此无法实例化方法。 The compiler, when processing main.cpp will accept the code in main gladly, since you are telling it that ABC is a template and that it has those two functions, and will assume that they will be defined in some other translation unit. 编译器在处理main.cpp时会很乐意接受main中的代码,因为你告诉它ABC是一个模板并且它具有这两个函数,并假设它们将在其他一些翻译单元中定义。

In the translation unit that contains test.cpp the compiler is seeing both method definitions, and the both of the instantiations (method/class) can be fully processed. 在包含test.cpp的转换单元中,编译器会看到两个方法定义,并且可以完全处理这两个实例(方法/类)。 If only the method instantiation ([1]) is present, the compiler will only generate that method, and will leave bar undefined. 如果仅存在方法实例化([1]),则编译器将仅生成该方法,并且将保留未定义的bar So any code that includes test.h, links against the compiled test.cpp and uses only foo method will compile and link, but usage of bar will fail to link due to it being undefined. 因此,任何包含test.h的代码,与编译的test.cpp链接并仅使用foo方法的代码都将进行编译和链接,但由于未定义, bar使用将无法链接。

Explicitly instantiating the class template generates the symbols for all the member methods, and in that case, any translation unit that includes test.h and links against the compiled test.cpp object file will both compile and link. 显式实例化类模板会为所有成员方法生成符号,在这种情况下,任何包含test.h的翻译单元和编译的test.cpp对象文件的链接都将编译和链接。

(This is an edited version of my original answer, prompted by David Rodriguez's observation.) (这是我的原始答案的编辑版本,由David Rodriguez的观察提示。)

#1 instantiates the class template, and as part of that instantiates all its methods. #1实例化类模板,并作为其中一部分实例化其所有方法。

#2 instantiates one member method of the class. #2实例化该类的一个成员方法。 As part of that it has to instantiate the class template, but not all its other methods. 作为其中的一部分,它必须实例化类模板,但不是所有其他方法。

The difference can be seen if you introduce a type-dependent error into bar() (eg a statement like void *x = b; ). 如果在bar()中引入类型相关的错误(例如像void *x = b;这样的语句),则可以看出差异。 You'll get a compiler error with #1 but not with #2 . 你会得到#1的编译器错误,但#2没有。 Also note that the compiler (gcc at least) would not compile #1 followed by #2 , but would compile either of them without the other, or if #2 were followed by #1 . 另请注意,编译器(至少gcc)不会编译#1后跟#2 ,但会编译其中任何一个而没有另一个,或者如果#2后跟#1

I guess you wanted to have {} instead of ; 我想你想要{}代替; in #1. 在#1。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我怎样才能简明扼要地编写大量显式函数模板实例? - How can I concisely write a lot of explicit function template instantiations? 模板类的许多实例会影响性能吗? - Do many instantiations of template class affect performance? 具有显式模板实例化的未解析的外部。什么是声明语法? - Unresolved externals with explicit template instantiations. What is the declaration syntax? 我可以使用decltype()来避免显式模板实例化中的代码重复吗? - Can I use decltype() to avoid code duplication in explicit template instantiations? extern模板'不一致的显式实例化' - extern template 'inconsistent explicit instantiations' 链接器如何处理跨翻译单元的相同模板实例化? - How does the linker handle identical template instantiations across translation units? 如何通过Clang编译模板实例化? - How do template instantiations get compiled by Clang? 在可以区分比较和模板实例之前,C ++的解析器会做什么? - What does a parser for C++ do until it can differentiate between comparisons and template instantiations? 用显式实例设置类模板的方法 - Way to set up class template with explicit instantiations 创建一系列显式函数模板实例化 - Create a sequence of explicit function template instantiations
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM