2012-02-28 90 views
-2

我很感興趣,引用標準中的具體段落,而不僅僅是一般意見。這是合法的C++代碼嗎?

template <class T> struct wrapped 
{ 
     wrapped(const T&) {} 
}; 

template <class T> wrapped<T> wrappit(const T& x) 
{ 
     return wrapped<T>(x); 
} 

template <class T> int run_function(const T& x, bool wrapped) 
{ 
     if (wrapped) { 
       return 0; 
     } else { 
       return run_function(wrappit(x), true) + 1; 
     } 
} 

int main() 
{ 
     const int result = run_function(0.5, false); 
     return result; 
} 
+0

這應該做什麼?它所做的一切就是讓'main'以迂迴的方式返回1。 – 2012-02-28 22:50:59

+6

是什麼讓你認爲這是非法的C++?儘管不定式實例化深度最有可能殺死一個愚蠢的編譯器?我的意思是,「int main(){}」是一個合法的C++代碼嗎?請給我一個關於它的標準。 – 2012-02-28 22:53:19

+1

這是一個關於「合法」一詞定義的問題嗎?我猜編譯器會遞歸地將T封裝在'wrapped Qwertie 2012-02-28 22:53:37

回答

4

從14.7.1(15):

的實例化中無限遞歸的結果是未定義的。


關於你的代碼:你不能這樣做靜態條件語句與if。相反,你需要某種功能的辦法,和部分專業化:

template <typename T, bool> struct run_function; 
template <typename T> struct run_function<T, true> 
{ 
    static int go(T const & x) { return 0; } 
}; 
template <typename T> struct run_function<T, false> 
{ 
    static int go(T const & x) 
    { return 1 + run_function<T, true>::go(wrappit(x)); } 
}; 

現在有沒有更多的無限遞歸,因爲兩個分支使用不同模板,最終沒有進一步實例化模板。

+0

感謝您的建議,但我需要在運行時設置布爾開關。解決這個問題的正確方法是從第一個函數調用一個不同的函數。 – 2012-02-29 09:04:10

5

符合實現可能會拒絕此代碼。見標準附錄B.

你的實現應該包括在其文檔中的某些限制,其中包括:

  • 遞歸嵌套的模板實例
+1

Ben,我認爲每個編譯器都會因爲遞歸嵌套實例化或者因爲他們會崩潰或停留在不定式循環中而拒絕它,直到它們耗盡內存並崩潰:-D – 2012-02-28 23:06:22

+0

@Vlad:一個足夠聰明的優化器可能會破壞無限遞歸。 – 2012-02-28 23:46:09

+0

GCC很聰明!哇噢! – 2012-02-29 00:34:20