2012-08-09 67 views
2

我碰到什麼樣子從鐺++編譯器sizeof運算奇怪的行爲...()操作:這是一個使用sizeof ...()運算符的錯誤嗎?

template <typename... Args> 
void test(tuple<Args...> t) { 
    cout << "size: " << sizeof...(Args) << endl; 
} 

... 
test(make_tuple(1, 2)); // prints 'size: 10' 

我意識到,更標準的方法是:

template <typename... Args> 
void test(tuple<Args...> t) { 
    cout << "size: " << tuple_size<tuple<Args...> >::value << endl; 
} 

test(make_tuple(1, 2)); // prints 'size: 2' 

但我我仍然很好奇,爲什麼我會爲第一個版本得到奇怪的值。 sizeof ...()的值是否定義爲這種情況,還是編譯器行爲不當?

+2

你使用'boost :: tuple'而不是'std :: tuple'嗎?這將解釋這些症狀,我可以發佈答案。如果不是,你的編譯器/標準庫是什麼版本? – 2012-08-09 02:34:17

+0

什麼編譯器/版本? – 2012-08-09 02:35:11

+0

我使用std :: tuple和clang ++版本:Apple clang版本4.0(tags/Apple/clang-421.0.57)(基於LLVM 3.1svn) Target:x86_64-apple-darwin12.0.0 Thread model:posix – 2012-08-09 03:14:45

回答

9

這聽起來很像舊的可變模板模擬和真正的可變模板之間的不匹配。

之前可變參數模板來了,人們可以用有限數量的違約模板參數模仿他們:

struct void_ {}; // marker type not used anywhere else 

template <typename T0 = void_, 
      typename T1 = void_, 
      typename T2 = void_, 
      typename T3 = void_, 
      typename T4 = void_, 
      typename T5 = void_, 
      typename T6 = void_, 
      typename T7 = void_, 
      typename T8 = void_, 
      typename T9 = void_> 
struct tuple { /* blah blah magic here */ }; 

這可以寫出tuple<int>tuple<int, double>,等等,多達十個參數。

tuple_size然後可以通過計數在第一個void_之前的模板參數的數量來實現。功能集的其餘部分以類似的方式實現。不幸的是,這個技巧與真正的可變模板相互作用很差。當給出tuple<int, double>時,tuple<Args...>上的類型扣除將推斷出Args數據包爲{int,double,void_,void_,void_,void_,void_,void_,void_,void_}。這就是爲什麼sizeof...(Args)返回10:這個包中的確有十種類型,即使它們中的八個只是我們決定賦予「無類型在這裏看到,移動」的標記。

編譯器不知道我們的約定,所以它計數一切。 tuple_size瞭解這個約定,只計算我們關心的實際類型。

+0

很高興我點擊這個問題,我一直在想如何去模擬可變宏,因爲VS 2012團隊花費了所有時間醜陋 - 如果使用界面而不是增加對C++ 11功能的支持。在第一個'void_'之前,我會如何計算模板參數的數量?你有這個小竅門的好參考嗎? – 2012-08-09 03:13:02

+0

@CodyGray最直接的解決方案將是十個部分專精:)。我不認爲有任何智能可以幫助你(我沒有看過助推實施,但檢查這是一個好主意)。或者,您可以使用Boost.MPL;我確定那裏面有類似的東西。 – 2012-08-09 03:16:25

+0

該死的,十個部分專精比我現在的複製粘貼好不了多少。 :-(我希望減少我在每個專業領域中需要複製的代碼量 – 2012-08-09 03:19:09