2013-11-05 50 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/

相关问题