[英]What's the right way to specialize a template when using “extern template”?
我希望有人可以指出在模板類中專門化方法的正確方法,同時使用“extern模板類”和“模板類”進行gnu c ++的顯式實例化。 我試圖通過模仿我真實問題的最簡單的例子來解決這個問題。 似乎聲明“extern模板”意味着模板實例化,這在專門化方法時會導致錯誤。 給出一個驅動程序:
main.cc
#include A_H
#include <iostream>
int main()
{
A<int> ai;
A<long> al;
std::cout << "ai=" << ai.get() << " al=" << al.get() << std::endl;
return 0;
}
以及A的以下實現
啊
template<typename T>
struct A
{
int get() const;
};
extern template class A<int>;
extern template class A<long>;
a.cc
#include "a.h"
template<typename T>
int A<T>::get() const
{
return 0;
}
template<>
int A<long>::get() const
{
return 1;
}
template class A<int>;
template class A<long>;
使用g ++ 4.1.2或4.4.4編譯時收到以下錯誤
% g++ -Wall -g -D'A_H="a.h"' a.cc main.cc
a.cc:10: error: specialization of 'int A<T>::get() const [with T = long int]' after instantiation
%
如果我在ah中注釋掉兩個“extern模板”行,那么兩個編譯器都會按預期編譯和工作。 我假設在沒有“extern模板”的情況下存在明確的實例化,即使在C ++ 0x中也是未指定的行為,否則,C ++ 0x添加“extern模板”的重點是什么?
如果我改為將A實現為:
A-hack.h
template<typename T>
struct A
{
int get() const;
};
template<typename T>
int A<T>::get() const
{
return 0;
}
template<>
inline
int A<long>::get() const
{
return 1;
}
extern template class A<int>;
extern template class A<long>;
a-hack.cc
#include "a-hack.h"
template class A<int>;
template class A<long>;
並再次編譯,這按預期工作
% g++ -Wall -g -D'A_H="a-hack.h"' a-hack.cc main.cc
% ./a.out
ai=0 al=1
但是,在我的真實示例中,這會導致程序崩潰,使用g ++ 4.1.2(在使用g ++ 4.4.4時)。 我沒有縮小崩潰的確切原因(分段錯誤)。 它看起來好像堆棧指針在對A <> :: get()的調用中被破壞了。
我意識到顯式模板實例化在這一點上是非標准的,但是有人會期望我上面所做的工作嗎? 如果沒有,這樣做的正確方法是什么?
謝謝
extern template class A<long>;
這一行說明A<long>
將根據編譯器已經看到的定義顯式實例化。 稍后添加專業化時,您會破壞其含義。
將您的專業化聲明添加到頭文件中。
template <typename T> struct A { /*...*/ };
template<> int A<long>::get() const;
extern template class A<int>;
extern template class A<long>;
通常,最好在與主模板相同的頭文件中放置盡可能多的特化聲明,以減少編譯器關於應該對任何特定實例使用哪個聲明的意外。
請注意,如果您正在處理單個模板實體,則不需要extern template
聲明(與此情況相反,我們必須向編譯器指示類 A<long>
和函數 A<long>::get()
)。 如果要在另一個翻譯單元中專門化一個功能模板,只需編寫template<>
。
template<typename T> int freeGet() { return 0; } // you can even add "inline" here safely!
template<> int freeGet<long>(); // this function is not inline (14.7.3/12)
但你必須有<>
。 如果省略<>
,聲明將變為默認實現的顯式實例化( return 0
),這可能不是您想要的! 即使您添加extern
,也允許編譯器內聯該默認實現; 如果你的代碼在傳遞-O2
時意外中斷,你可能不小心忽略了<>
某處。
添加此答案以解決標題中的問題(模板實例化,而不一定是模板方法實例化)。
這非常類似於函數聲明/定義。
extern template class
是一個聲明,通常應該放在標題中。 template class
是一個定義,通常應該放在cpp中。 更多信息在這里 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.