問題描述
我很驚訝在各種采樣版本的 g++ 上,以下編譯沒有錯誤或警告:
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
的定義缺失或在不同的翻譯單元中,我會得到錯誤.
If the definition of X
is missing or in a different translation unit, I do get errors.
但是在上面的程序中,f
的定義不是我模板的單個實例化點嗎?在那個實例化點 X
的不完整性難道不是語義錯誤嗎?
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 草案)標準是否稱此程序為格式良好、格式錯誤、格式錯誤但不需要診斷或未定義的行為?
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 報告說,clang++、comeau 和 Visual Studio 2010 也接受類似的代碼.
@David Rodriguez - dribeas reports that clang++, comeau, and Visual Studio 2010 also accept similar code.
推薦答案
(我一直在等 Alf Steinbach 發布答案,但由于他不這樣做,我將發布他在 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):
標準表明模板實例化在翻譯單元已經翻譯之后執行,因此及時,模板實例化發生在所有非模板化元素已經被處理.這在第 2.2 部分翻譯階段中進行了描述:
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 段定義了預處理器的工作和基本的文本操作(字符集的轉換、文字的連接......)
Paragraphs 1-6 define the preprocessor work and basic textual operations (conversions of the character set, concatenation of literals...)
7/分隔標記的空白字符不再重要.每個預處理令牌都被轉換為一個令牌.(2.7).生成的標記在句法和語義上進行分析并作為翻譯單元進行翻譯.
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/翻譯的翻譯單元和實例化單元的組合如下:檢查每個翻譯的翻譯單元以生成所需實例化的列表.找到所需模板的定義.是否需要包含這些定義的翻譯單元的源是實現定義的.執行所有必需的實例化以生成實例化單元.[ 注意:這些類似于翻譯的翻譯單元,但不包含對未實例化模板的引用,也沒有模板定義.— end note ] 如果任何實例化失敗,程序就是格式錯誤的.
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.
為簡潔起見,我刪除了一些注釋.現在重要的一點似乎是在一步中轉換代碼而不觸發模板實例化,然后在后面的步驟中實例化模板.這反過來意味著,如果類型在翻譯單元中的任何位置完整,那么在編譯器進行實例化時它就會被處理.
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.
免責聲明:對于我嘗試過的所有編譯器都表現出完全相同的行為(gcc、clang、comeau、VS 2010),這似乎是一個很好的理由,但這僅說明了當及時執行實例化時,它沒有明確聲明類型在模板實例化點可能是不完整的.
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.
這篇關于模板中的類使用不完整的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!