從我在此處發布的上一個示例中,何時template實體化?,我得到的答案是,只有在使用模板時,編譯器才會實體化它。但是看看這個例子:
template <typename T>
struct Pow{
T operator()(T const& x){ return x * x; }
};
extern template struct Pow<int>; // explicit instantiation declaration
struct Foo{
Pow<int> pi{};
void fn(Pow<int>);
};
void Foo::fn(Pow<int> pw){
// std::cout << pw(7) << '\n';
}
void bar(Pow<int> pwi){
// std::cout << pwi(10) << '\n';
}
int main(){
Foo f;
}
如您所見,我已經宣告了一個顯式模板實體化,
Pow<int>但尚未定義它。該程式運行良好,并且不會抱怨缺少Pow<int>!在上一個主題中,我已經回答了如果我使用模板型別作為函式定義(不是宣告)的引數型別,那么模板將被實體化,但在這里您可以看到:定義了成員函式
Foo::fn(Pow<int>)和普通函式函式bar(Pow<int>)但是編譯器不會抱怨Pow<int>?!!!如果我取消注釋上述函式中的行,程式將無法編譯。那么這是否意味著
Pow<int>在用作函式定義中的函式引數和像 in 中的成員資料時不會實體化Foo::Pow<int> pi{};?我覺得很困惑:
void f(Pow<int>); // function declaration: Pow<int> is not instantiated yet. void f2(Pow<int>){} // function definition: Pow<int> instantiated? void f3(pow<int> Pwi){ std::cout << Pwi(10);} // function definition and usage of `Pow<int>`: Pow<int> instantiated?在主要:
Foo f; // f has pi of type Pow<int>. so Pow<int> is instantiated?
uj5u.com熱心網友回復:
Pow<int> 被定義。它被定義為Pow<T>用T=int。
uj5u.com熱心網友回復:
該程式運行良好,并且不會抱怨缺少
Pow<int>!
因為它不缺。顯式實體化的兩種形式(宣告和定義)都會導致類模板的實體化。顯式實體化定義會導致成員函式的實體化(通常僅在需要時才延遲實體化)。另一方面,顯式實體化宣告將抑制成員函式的隱式實體化。即使那個成員函式體是可見的!
它是一種為一組受約束的型別撰寫模板的工具,同時隱藏它們的實作。它允許一個人這樣做:
//pow.h
template <typename T>
struct Pow{
T operator()(T const& x); // Just a declaration
};
extern template struct Pow<int>; // The class is instantiated, the member is
// assumed to be explicitly instantiated elsewhere
//pow.cpp
#include "pow.h"
template <typename T>
T Pow<T>::operator()(T const& x) { return x * x; }
template struct Pow<int>; // Explicit instantiation. The member function is defined
// in **this** translation unit.
這正是您的程式無法鏈接的原因。該成員operator()永遠不會在您的程式中的任何地方實體化。您可以通過在某處提供顯式實體化定義來修復它。例如
template <typename T>
struct Pow{
T operator()(T const& x){ return x * x; }
};
// ...
int main() {
// ...
}
template struct Pow<int>; // Now the member function is emitted
另一個用途是潛在地改進編譯時間。如果你有一個類模板,你知道通常實體化一組特定的型別,可以幫助沿著連接器。
// my_string.h
template<typename charT>
class my_string {
// Everything, members and all
};
extern template class my_string<char>;
extern template class my_string<wchar_t>;
// my_string.cpp
#include <my_string.h>
// This file can be part of a shared object that ships with your library
// The common declarations are here
template class my_string<char>;
template class my_string<wchar_t>;
現在,聯結器不必對由常用my_string<char>and 的隱式實體化產生的許多重復符號進行排序my_string<wchar_t>。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/328466.html
上一篇:神秘的C 可變引數模板擴展
