問(wèn)題描述
我很驚訝在各種采樣版本的 g++ 上,以下編譯沒(méi)有錯(cuò)誤或警告:
I am very surprised that on various sampled versions of g++, the following compiles without error or warning:
// Adapted from boost::checked_delete()
template <class T> inline void assert_complete()
{
typedef char type_must_be_complete[ sizeof(T) ? 1 : -1 ];
(void) sizeof(type_must_be_complete);
}
class X;
void f()
{
assert_complete<X>();
}
class X {};
int main() {}
如果 X
的定義缺失或在不同的翻譯單元中,我會(huì)得到錯(cuò)誤.
If the definition of X
is missing or in a different translation unit, I do get errors.
但是在上面的程序中,f
的定義不是我模板的單個(gè)實(shí)例化點(diǎn)嗎?在那個(gè)實(shí)例化點(diǎn) X
的不完整性難道不是語(yǔ)義錯(cuò)誤嗎?
But in the program as above, isn't the definition of f
the single instantiation point of my template? And isn't the incompleteness of X
at that instantiation point a semantic error?
(C++03 和/或 C++11 草案)標(biāo)準(zhǔn)是否稱此程序?yàn)楦袷搅己谩⒏袷藉e(cuò)誤、格式錯(cuò)誤但不需要診斷或未定義的行為?
Does the (C++03 and/or C++11 Draft) Standard call this program well-formed, ill-formed, ill-formed but diagnostic not required, or undefined behavior?
@David Rodriguez - dribeas 報(bào)告說(shuō),clang++、comeau 和 Visual Studio 2010 也接受類似的代碼.
@David Rodriguez - dribeas reports that clang++, comeau, and Visual Studio 2010 also accept similar code.
推薦答案
(我一直在等 Alf Steinbach 發(fā)布答案,但由于他不這樣做,我將發(fā)布他在 Lounge C++ chat 中提到的參考):
(I was waiting to Alf Steinbach to post an answer, but since he is not doing it, I will post the reference that he mentioned in the Lounge C++ chat):
標(biāo)準(zhǔn)表明模板實(shí)例化在翻譯單元已經(jīng)翻譯之后執(zhí)行,因此及時(shí),模板實(shí)例化發(fā)生在所有非模板化元素已經(jīng)被處理.這在第 2.2 部分翻譯階段中進(jìn)行了描述:
The standard indicates that template instantiations are performed after the translation unit has already been translated, so that in time, template instantiations happen after all the non templated elements have already been processed. This is described in section 2.2 Phases of translation:
第 1-6 段定義了預(yù)處理器的工作和基本的文本操作(字符集的轉(zhuǎn)換、文字的連接......)
Paragraphs 1-6 define the preprocessor work and basic textual operations (conversions of the character set, concatenation of literals...)
7/分隔標(biāo)記的空白字符不再重要.每個(gè)預(yù)處理令牌都被轉(zhuǎn)換為一個(gè)令牌.(2.7).生成的標(biāo)記在句法和語(yǔ)義上進(jìn)行分析并作為翻譯單元進(jìn)行翻譯.
7/ White-space characters separating tokens are no longer significant. Each preprocessing token is converted into a token. (2.7). The resulting tokens are syntactically and semantically analyzed and translated as a translation unit.
8/翻譯的翻譯單元和實(shí)例化單元的組合如下:檢查每個(gè)翻譯的翻譯單元以生成所需實(shí)例化的列表.找到所需模板的定義.是否需要包含這些定義的翻譯單元的源是實(shí)現(xiàn)定義的.執(zhí)行所有必需的實(shí)例化以生成實(shí)例化單元.[ 注意:這些類似于翻譯的翻譯單元,但不包含對(duì)未實(shí)例化模板的引用,也沒(méi)有模板定義.— end note ] 如果任何實(shí)例化失敗,程序就是格式錯(cuò)誤的.
8/ Translated translation units and instantiation units are combined as follows: Each translated translation unit is examined to produce a list of required instantiations. The definitions of the required templates are located. It is implementation-defined whether the source of the translation units containing these definitions is required to be available. All the required instantiations are performed to produce instantiation units. [ Note: These are similar to translated translation units, but contain no references to uninstantiated templates and no template definitions. — end note ] The program is ill-formed if any instantiation fails.
為簡(jiǎn)潔起見(jiàn),我刪除了一些注釋.現(xiàn)在重要的一點(diǎn)似乎是在一步中轉(zhuǎn)換代碼而不觸發(fā)模板實(shí)例化,然后在后面的步驟中實(shí)例化模板.這反過(guò)來(lái)意味著,如果類型在翻譯單元中的任何位置完整,那么在編譯器進(jìn)行實(shí)例化時(shí)它就會(huì)被處理.
I have removed some of the notes for brevity. Now the important bit seems to be that the code is translated without triggering template instantiations in one step, and then in a later step the templates are instantiated. This in turn means that if the type is complete anywhere in the translation unit, it will have been processed by the time the compiler gets to the instantiation.
免責(zé)聲明:對(duì)于我嘗試過(guò)的所有編譯器都表現(xiàn)出完全相同的行為(gcc、clang、comeau、VS 2010),這似乎是一個(gè)很好的理由,但這僅說(shuō)明了當(dāng)及時(shí)執(zhí)行實(shí)例化時(shí),它沒(méi)有明確聲明類型在模板實(shí)例化點(diǎn)可能是不完整的.
Disclaimer: This seems like a good reason for all of the compilers that I have tried showing the exact same behavior (gcc, clang, comeau, VS 2010), but this only states when in time the instantiation is performed, it does not explicitly state that the type can be incomplete at the point of instantiation of the template.
這篇關(guān)于模板中的類使用不完整的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!