Variadic Templates Frej Soya Jorgen Haahr May 9, 2008
What is ”Variadic Templates”? • Variable number of template parameters Short example template < typename . . . Values > c l a s s t u p l e ; main () { i n t tuple < int , double , char const ∗ > something (1 , 2. 2 , ” t e s t ” ) ; return 0; }
Motivation • Fixed numbers of template parameters
Motivation • Fixed numbers of template parameters • Emulating variable number of template parameters with preprocessing
Motivation • Fixed numbers of template parameters • Emulating variable number of template parameters with preprocessing • printf is not typesafe.
Motivation • Fixed numbers of template parameters • Emulating variable number of template parameters with preprocessing • printf is not typesafe. • tuples in boost has limited size.
Motivation • Fixed numbers of template parameters • Emulating variable number of template parameters with preprocessing • printf is not typesafe. • tuples in boost has limited size. • Improves argument forwarding for variable arguments.
Fixing printf (and varargs) in c++ printf crashes on non-POD continued... p r i n t f ( ” H e l l o %s ” , std : : s t r i n g ( ”World” ) ) template < typename T, typename . . . Args > void p r i n t f ( const char ∗ s ,T value , Args Good compilers warn you. . . . args ) { ( ∗ s ) { while ( ∗ s == ’%’ && ∗ ++s != ’%’ ) { i f With variadic templates std : : cout < < v a l u e ; p r i n t f (++s , args . . . ) ; return } void p r i n t f ( const char ∗ s ) { std : : cout < < ∗ s++; while ( ∗ s ) { } i f ( ∗ s == ’%’ && ∗ ++s != ”%” ) std : : runtime e r r o r ( ” e x t r a throw throw . . . . arguments pr ov ided to p r i n t f ” ) ; std : : cout < < ∗ s++; } } }
What just happened? Example i n t count () { return 0; } • The ellipsis operator ”...” template < typename T, typename . . . Args > i n t count (T head , Args . . . t a i l ) { • Parameter packs return 1+count ( t a i l . . . ) ; } i n t main () { • Parameter packing cout < < count < int , double , double > (1 ,2.3 , 3 . 5 ) ; • Parameter unpacking } • Typeinformation is retained Shortcut for count const int size = sizeof(Args..)
Tuples template < typename Head , typename . . . Tail > c l a s s tuple < Head , T a i l ... > : p r i v a t e tuple < T a i l ... > { Head head ; } ; Different sized tuples template < typename . . Elements1 , typename . . . Elements2 > operator ==( const tuple < Elements1 . . . & t1 , const tuple < bool Elements2 ... > & t2 ) ; Equally sized tuples template < typename . . Elements > bool operator ==( const tuple < Elements . . . & t1 , const tuple < Elements ... > & t2 ) ;
Initializer lists • Interaction with generalized initializer lists template < typename . . . Values > c l a s s t u p l e { p u b l i c : t u p l e ( const Values & . . . v a l u e s ) ; } ; This is nice for tuples tuple < int , f l o a t , s t r i n g > t = { 42 , 2.71828 , ” Hello , world ! ” }
Usage • No imperative access to types • Use is often recursive • E.g. count and printf functions • However, by using the unpacking operator the template arguments can unpacked anywhere.
References Wikipedia http://en.wikipedia.org/wiki/C%2B%2B0x#Variadic templates C++ Standards Communittee http://www.open-std.org/jtc1/sc22/wg21/docs/papers/ Douglas Gregor, Ph.D http://www.osl.iu.edu/ dgregor/
Recommend
More recommend