2013-11-05 52 views
4

我發現C++ 14 make_index_sequence的實行 '算法':當我更換的sizeof爲什麼sizeof ...(T)這麼慢?實現C++ 14 make_index_sequence沒有...的sizeof(T)

template< int ... > struct index_sequence{ using type = index_sequence; }; 

template< typename T> using invoke = typename T :: type ; 

template< typename T, typename U > struct concate; 
template< int ...i, int ... j> 
struct concate< index_sequence<i...>, index_sequence<j...> > 
     : index_sequence< i... , (j + sizeof ... (i))... > {}; 
    //         \  /
    //         ---------- 
//         I think here is slowly. 
template< int n> 
struct make_index_sequence_help : concate< 
          invoke< make_index_sequence_help<n/2>>, 
          invoke< make_index_sequence_help<n-n/2>> 
          > {}; 

template<> struct make_index_sequence_help <0> : index_sequence<>{}; 
template<> struct make_index_sequence_help <1> : index_sequence<0>{}; 

template< int n> using make_index_sequence = invoke< make_index_sequence_help<n> >; 


int main() 
{ 
    using iseq = make_index_sequence<1024> ; // successfull 
    using jseq = make_index_sequence< 1024 * 16 > ; // a lot of compile time!!! 
    using kseq = make_index_sequence< 1024 * 64 > ; // can't compile: memory exhauted!!! 
}; 

但是,...(我)從'concate'轉換爲具體數字,然後make_index_sequence < 1024 * 64> - 編譯得非常快。

template< int s, typename T, typename U > struct concate; 
template< int s, int ...i, int ...j > 
struct concate< s, index_sequence<i...>, index_sequence<j...> > 
: index_sequence< i..., (j + s) ... > {}; 

// and 
template< int n > 
struct make_index_sequence_help : concate< 
            n/2 , 
          invoke< make_index_sequence_help<n/2> >, 
          invoke< make_index_sequence_help< n - n/2 > > 
          >{}; 

問:爲什麼sizeof ...(i)這麼慢?

對於第一種情況:(僅1024和1024 * 16)

我用gcc 4.8.1 更新測試。

g++ -Wall -c "ctx_fptr.cpp" -g -O2 -std=c++11 -ftime-report 
Execution times (seconds) 
garbage collection : 0.06 (1%) usr 0.00 (0%) sys 0.06 (0%) wall  0 kB (0%) ggc 
preprocessing   : 0.03 (0%) usr 0.04 (2%) sys 0.09 (1%) wall  293 kB (0%) ggc 
parser    : 10.41 (97%) usr 1.61 (95%) sys 12.01 (96%) wall 2829842 kB (99%) ggc 
name lookup   : 0.12 (1%) usr 0.04 (2%) sys 0.23 (2%) wall 7236 kB (0%) ggc 
dead store elim1  : 0.01 (0%) usr 0.00 (0%) sys 0.00 (0%) wall  0 kB (0%) ggc 
symout    : 0.15 (1%) usr 0.00 (0%) sys 0.15 (1%) wall 12891 kB (0%) ggc 
unaccounted todo  : 0.00 (0%) usr 0.01 (1%) sys 0.00 (0%) wall  0 kB (0%) ggc 
TOTAL     : 10.78    1.70   12.55   2850835 kB 

對於第二種情況:(所有1024,1024 * 16和1024 * 64)

g++ -Wall -c "ctx_fptr.cpp" -g -O2 -std=c++11 -ftime-report 
Execution times (seconds) 
preprocessing   : 0.02 (2%) usr 0.01 (5%) sys 0.05 (4%) wall  293 kB (0%) ggc 
parser    : 0.54 (45%) usr 0.10 (53%) sys 0.71 (50%) wall 95339 kB (58%) ggc 
name lookup   : 0.47 (39%) usr 0.04 (21%) sys 0.47 (33%) wall 20197 kB (12%) ggc 
tree PRE    : 0.01 (1%) usr 0.00 (0%) sys 0.00 (0%) wall  1 kB (0%) ggc 
varconst    : 0.00 (0%) usr 0.01 (5%) sys 0.00 (0%) wall  17 kB (0%) ggc 
symout    : 0.17 (14%) usr 0.03 (16%) sys 0.18 (13%) wall 47092 kB (29%) ggc 
TOTAL     : 1.21    0.19    1.41    163493 kB 
+4

模板擴張和處理「解釋」的GCC編譯器內緩慢的*編譯時間*(而不是在編譯的代碼的運行時)。編譯器需要生成大的AST(具有大量的元數據,例如精確的源位置) –

+4

Q.您的證據在哪裏?是什麼讓你認爲它是所有東西的大小?這只是編譯時的符號表查找。 – EJP

+0

您可以使用在線編譯器進行測試。 http://ideone.com/TLuDiA。我問關於編譯時間,而不是運行時。 –

回答

3

彙編是緩慢的,並且使用了大量的內存,因爲你是遞歸擴展模板。這是在編譯時完成的,它創建了大量的類型,並且這可以使用大量的內存。這不是由sizeof或任何其他個人陳述造成的。這是遞歸導致模板擴展的每一位都很昂貴。

我碰到了與VC++完全相同的問題 - 我發現我的編譯會隨意傳遞,因爲我將較大的常量傳遞給我編寫的模板函數。

當然,在我的情況下,我是試圖使編譯器運行緩慢。但儘管如此,也許這將是有益的:

https://randomascii.wordpress.com/2014/03/10/making-compiles-slow/

相關問題