Index: gcc/doc/cpp.texi =================================================================== --- gcc/doc/cpp.texi (.../vendor/gcc-4.1.1) (revision 425) +++ gcc/doc/cpp.texi (.../branches/variadic-templates) (revision 425) @@ -2128,6 +2128,9 @@ use. This macro is defined, with value 2, when @option{-fstack-protector-all} is in use. +@item__VARIADIC_TEMPLATES +This macro is defined if support is provided for the variadic templates +extension to C++. @end table @node System-specific Predefined Macros Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (.../vendor/gcc-4.1.1) (revision 425) +++ gcc/doc/invoke.texi (.../branches/variadic-templates) (revision 425) @@ -182,7 +182,7 @@ in the following sections. -fno-optional-diags -fpermissive @gol -frepo -fno-rtti -fstats -ftemplate-depth-@var{n} @gol -fno-threadsafe-statics -fuse-cxa-atexit -fno-weak -nostdinc++ @gol --fno-default-inline -fvisibility-inlines-hidden @gol +-fno-default-inline -fno-variadic-templates -fvisibility-inlines-hidden @gol -Wabi -Wctor-dtor-privacy @gol -Wnon-virtual-dtor -Wreorder @gol -Weffc++ -Wno-deprecated -Wstrict-null-sentinel @gol @@ -1579,6 +1579,12 @@ This option is required for fully standa destructors, but will only work if your C library supports @code{__cxa_atexit}. +@item -fno-variadic-templates +@opindex fno-variadic-templates +Disable support for the "variadic templates" extension to GNU +C++. Variadic templates provide the ability for a template to accept a +variable-length argument list through the use of the ellipsis operator. + @item -fvisibility-inlines-hidden @opindex fvisibility-inlines-hidden Causes all inlined methods to be marked with Index: gcc/c-cppbuiltin.c =================================================================== --- gcc/c-cppbuiltin.c (.../vendor/gcc-4.1.1) (revision 425) +++ gcc/c-cppbuiltin.c (.../branches/variadic-templates) (revision 425) @@ -334,6 +334,8 @@ c_cpp_builtins (cpp_reader *pfile) cpp_define (pfile, "__GXX_WEAK__=0"); if (warn_deprecated) cpp_define (pfile, "__DEPRECATED"); + if (flag_variadic_templates) + cpp_define (pfile, "__VARIADIC_TEMPLATES"); } /* Note that we define this for C as well, so that we know if __attribute__((cleanup)) will interface with EH. */ Index: gcc/testsuite/g++.dg/template/variadic-function.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic-function.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic-function.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,95 @@ +// { dg-do "run" } +// A basic implementation of TR1's function using variadic teplates +// Contributed by Douglas Gregor +#include + +template +class function; + +template +class invoker_base +{ + public: + virtual ~invoker_base() { } + virtual R invoke(Args...) = 0; + virtual invoker_base* clone() = 0; +}; + +template +class functor_invoker : public invoker_base +{ + public: + explicit functor_invoker(const F& f) : f(f) { } + R invoke(Args... args) { return f(args...); } + functor_invoker* clone() { return new functor_invoker(f); } + + private: + F f; +}; + +template +class function { + public: + typedef R result_type; + + function() : invoker (0) { } + + function(const function& other) : invoker(0) { + if (other.invoker) + invoker = other.invoker->clone(); + } + + template + function(const F& f) : invoker(0) { + invoker = new functor_invoker(f); + } + + ~function() { + if (invoker) + delete invoker; + } + + function& operator=(const function& other) { + function(other).swap(*this); + return *this; + } + + template + function& operator=(const F& f) { + function(f).swap(*this); + return *this; + } + + void swap(function& other) { + invoker_base* tmp = invoker; + invoker = other.invoker; + other.invoker = tmp; + } + + result_type operator()(Args... args) const { + assert(invoker); + return invoker->invoke(args...); + } + + private: + invoker_base* invoker; +}; + +struct plus { + template T operator()(T x, T y) { return x + y; } +}; + +struct multiplies { + template T operator()(T x, T y) { return x * y; } +}; + +int main() +{ + function f1 = plus(); + assert(f1(3, 5) == 8); + + f1 = multiplies(); + assert(f1(3, 5) == 15); + + return 0; +} Index: gcc/testsuite/g++.dg/template/variadic69.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic69.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic69.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,33 @@ +template +struct stored_value +{ + explicit stored_value() : value() { } + + explicit stored_value(const T& value) : value(value) { } + + stored_value(int, const T& value) : value(value) { } + + T value; +}; + +template +struct myclass : public stored_value... +{ + myclass() { } + + explicit myclass(const Values&... values) + : stored_value(values)... { } + + explicit myclass(int x, const Values&... values) + : stored_value(x, values)... { } + +}; + +void f() +{ + int i; + float f; + myclass ifp1; + myclass ifp2(&i, &f); + myclass ifp3(1, &i, &f); +} Index: gcc/testsuite/g++.dg/template/variadic11.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic11.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic11.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,17 @@ +template struct count; + +template<> +struct count<> { + static const int value = 0; +}; + +template +struct count { + static const int value = 1 + count::value; +}; + +int a0[count<>::value == 0? 1 : -1]; +int a1[count::value == 1? 1 : -1]; +int a2[count::value == 2? 1 : -1]; +int a3[count::value == 3? 1 : -1]; +int a4[count::value == 4? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic20.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic20.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic20.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,44 @@ +template struct add_pointer; +template struct add_reference; + +template class... Metafunctions> +struct metatuple { + static const int value = 0; +}; + +template<> +struct metatuple { + static const int value = 1; +}; + +template class Meta> +struct metatuple { + static const int value = 2; +}; + +template class... Metafunctions> +struct metatuple { + static const int value = 3; +}; + +template class First, + template class... Metafunctions> +struct metatuple { + static const int value = 4; +}; + +template class First, + template class Second, + template class... Metafunctions> +struct metatuple { + static const int value = 5; +}; + +int a0[metatuple<>::value == 0? 1 : -1]; +int a1[metatuple::value == 1? 1 : -1]; +int a2a[metatuple::value == 2? 1 : -1]; +int a2b[metatuple::value == 2? 1 : -1]; +int a3[metatuple::value == 3? 1 : -1]; +int a4[metatuple::value == 4? 1 : -1]; +int a5[metatuple::value == 5? 1 : -1]; + Index: gcc/testsuite/g++.dg/template/variadic12.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic12.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic12.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,41 @@ +// A tuple type +template struct tuple { }; + +// Determine if two types are the same +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + static const bool value = true; +}; + +// Append 'T' to the end of Tuple +template +struct append_to_tuple; + +template +struct append_to_tuple > { + typedef tuple type; +}; + +// Reverse a sequence of arguments (and return the result as a tuple) +template struct reverse; + +template +struct reverse { + typedef typename append_to_tuple::type>::type + type; +}; + +template<> +struct reverse<> { + typedef tuple<> type; +}; + +int a0[is_same::type, tuple<> >::value? 1 : -1]; +int a1[is_same::type, tuple >::value? 1 : -1]; +int a2[is_same::type, tuple >::value? 1 : -1]; +int a3[is_same::type, tuple >::value? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic21.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic21.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic21.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,6 @@ +template +struct array { }; + +array a0; +array a1; +array a1234; Index: gcc/testsuite/g++.dg/template/variadic30.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic30.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic30.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,10 @@ +template +void eat(T...); + +void f() +{ + eat(); + eat(1); + eat(1, 2); + eat(17, 3.14159, "Hello, World!"); +} Index: gcc/testsuite/g++.dg/template/variadic13.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic13.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic13.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,18 @@ +template struct tuple1 { }; +template struct tuple2 { }; + +template +struct same_tuple_args { + static const bool value = false; +}; + +template +struct same_tuple_args, tuple2 > { + static const bool value = true; +}; + +int same0[same_tuple_args, tuple2<> >::value? 1 : -1]; +int same1[same_tuple_args, tuple2 >::value? 1 : -1]; +int same2[same_tuple_args, tuple2 >::value? 1 : -1]; +int diff0[!same_tuple_args, tuple2 >::value? 1 : -1]; +int diff1[!same_tuple_args, tuple2 >::value? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic22.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic22.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic22.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,20 @@ +template +struct make_function_type +{ + typedef R type(ArgTypes... args); +}; + +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + static const bool value = true; +}; + +int a0[is_same::type, int()>::value? 1 : -1]; +int a1[is_same::type, int(float)>::value? 1 : -1]; +int a2[is_same::type, int(float)>::value? 1 : -1]; +int a3[is_same::type, int(float, double const)>::value? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic31.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic31.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic31.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,10 @@ +template +void eat(T...) { } + +void f() +{ + eat(); + eat(1); + eat(1, 2); + eat(17, 3.14159, "Hello, World!"); +} Index: gcc/testsuite/g++.dg/template/variadic14.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic14.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic14.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,20 @@ +template +struct make_function_type +{ + typedef R type(ArgTypes...); +}; + +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + static const bool value = true; +}; + +int a0[is_same::type, int()>::value? 1 : -1]; +int a1[is_same::type, int(float)>::value? 1 : -1]; +int a2[is_same::type, int(float)>::value? 1 : -1]; +int a3[is_same::type, int(float, double)>::value? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic40.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic40.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic40.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,2 @@ +template +struct backward_tuple {}; // { dg-error "end" } Index: gcc/testsuite/g++.dg/template/variadic23.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic23.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic23.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,24 @@ +template +struct array { + static const int value = 0; +}; + +template<> +struct array { + static const int value = 1; +}; + +template +struct array { + static const int value = 2; +}; + +template +struct array { + static const int value = 3; +}; + +int a0[array::value == 0? 1 : -1]; +int a1[array::value == 1? 1 : -1]; +int a2[array::value == 2? 1 : -1]; +int a3[array::value == 3? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic32.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic32.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic32.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,10 @@ +template +void eat(const T&...) { } + +void f() +{ + eat(); + eat(1); + eat(1, 2); + eat(17, 3.14159, "Hello, World!"); +} Index: gcc/testsuite/g++.dg/template/variadic15.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic15.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic15.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,20 @@ +template +struct make_function_type +{ + typedef R type(const ArgTypes&...); +}; + +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + static const bool value = true; +}; + +int a0[is_same::type, int()>::value? 1 : -1]; +int a1[is_same::type, int(const float&)>::value? 1 : -1]; +int a2[is_same::type, int(const float&)>::value? 1 : -1]; +int a3[is_same::type, int(const float&, double const&)>::value? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic1.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic1.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic1.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,9 @@ +template +class tuple; + +template +class tuple { }; + +template +class tuple1p { }; + Index: gcc/testsuite/g++.dg/template/variadic41.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic41.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic41.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,2 @@ +template +void f(const Args&... args, int oops); // { dg-error "end" } Index: gcc/testsuite/g++.dg/template/variadic24.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic24.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic24.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,5 @@ +template +struct vector_c { }; + +vector_c intvec; +vector_c charvec; Index: gcc/testsuite/g++.dg/template/variadic50.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic50.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic50.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,8 @@ +int& f(int, double, ...); + +template +float& f(Args...); + +float& g() { + return f(17, 3.14159, 3); +} Index: gcc/testsuite/g++.dg/template/variadic33.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic33.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic33.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,15 @@ +void print_all() {} + +template +void print_all(const T& t, const Rest&... rest) +{ + print_all(rest...); +} + +void f() +{ + print_all(); + print_all(1); + print_all(1, 3.14159); + print_all("Hello, World!", 17, 3.14159); +} Index: gcc/testsuite/g++.dg/template/variadic16.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic16.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic16.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,20 @@ +template +struct make_function_type +{ + typedef R type(const ArgTypes&... args); +}; + +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + static const bool value = true; +}; + +int a0[is_same::type, int()>::value? 1 : -1]; +int a1[is_same::type, int(const float&)>::value? 1 : -1]; +int a2[is_same::type, int(const float&)>::value? 1 : -1]; +int a3[is_same::type, int(const float&, double const&)>::value? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic2.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic2.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic2.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,16 @@ +template // { dg-error "default argument" } +class tuple2; + +template // { dg-error "default argument" } +class tuple3; + +template +struct two_or_more {}; // { dg-error "provided for" } + +typedef two_or_more bad; // { dg-error "2 or more" } +// { dg-error "invalid type" "" { target *-*-* } 10 } + +void f() +{ + two_or_more z = 5; // { dg-error "two_or_more" } +} Index: gcc/testsuite/g++.dg/template/variadic42.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic42.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic42.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,11 @@ +// { dg-do compile } +template +void f(Args...) { } + +void g() +{ + f(0, 0, 0); + f(0,0,0); +} +// { dg-final { scan-assembler "_Z1fIPiPfPdEvU10__variadicT_" } } +// { dg-final { scan-assembler "_Z1fIPiiiEvU10__variadicT_" } } Index: gcc/testsuite/g++.dg/template/variadic25.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic25.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic25.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,15 @@ +template +struct sum; + +template<> +struct sum<> { + static const int value = 0; +}; + +template +struct sum { + static const int value = Value + sum::value; +}; + +int a0[sum<>::value == 0? 1 : -1]; +int a1[sum<1, 2, 3, 4, 5>::value == 15? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic51.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic51.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic51.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,9 @@ +template +float& f(T1, T2); + +template +int& f(Args...); + +float& g() { + return f(17, 3.14159); +} Index: gcc/testsuite/g++.dg/template/variadic34.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic34.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic34.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,10 @@ +template +void get_ith(const Args&... args); + +void f() +{ + get_ith<1>(1, 2, 3); + get_ith<1, int>(1, 2.0, 'x'); + get_ith<1, int, double>(1, 2.0, 'x'); + get_ith<1, int, double, char>(1, 2.0, 'x'); +} Index: gcc/testsuite/g++.dg/template/variadic17.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic17.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic17.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,20 @@ +template +struct make_function_type +{ + typedef R type(const ArgTypes&......); +}; + +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + static const bool value = true; +}; + +int a0[is_same::type, int(...)>::value? 1 : -1]; +int a1[is_same::type, int(const float&...)>::value? 1 : -1]; +int a2[is_same::type, int(const float&,...)>::value? 1 : -1]; +int a3[is_same::type, int(const float&, double const&...)>::value? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic3.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic3.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic3.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,9 @@ +template +class tuple {}; + +void f() +{ + tuple<> x; + tuple y; + tuple z; +} Index: gcc/testsuite/g++.dg/template/variadic60.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic60.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic60.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,18 @@ +template + struct _Index_tuple { }; + +template > +struct _Build_index_tuple; + +template +struct _Build_index_tuple<_Num, _Index_tuple<_Indexes...> > + : _Build_index_tuple<_Num - 1, + _Index_tuple<_Indexes..., sizeof...(_Indexes)> > +{ +}; + +template +struct _Build_index_tuple<0, _Index_tuple<_Indexes...> > +{ + typedef _Index_tuple<_Indexes...> __type; +}; Index: gcc/testsuite/g++.dg/template/variadic43.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic43.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic43.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,7 @@ +template +int f(const Args&...); + +void g() +{ + int (*fp)(const int&, const float&) = &f; +} Index: gcc/testsuite/g++.dg/template/variadic26.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic26.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic26.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,23 @@ +template class Meta, int Initial, int... Values> +struct accumulate { + static const int value = Initial; +}; + +template class Meta, int Initial, int Value, int... Rest> +struct accumulate { + static const int value = + Meta::value>::value; +}; + +template +struct sum { + static const int value = X + Y; +}; + +template +struct prod { + static const int value = X * Y; +}; + +int a0[accumulate::value == 15? 1 : -1]; +int a1[accumulate::value == 120? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic-bind.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic-bind.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic-bind.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,475 @@ +// { dg-do "run" } +// A basic implementation of TR1's bind using variadic teplates +// Contributed by Douglas Gregor +#include + +// Trivial reference_wrapper +template +struct reference_wrapper +{ + reference_wrapper(T& x) : ptr(&x) { } + + operator T&() const { return *ptr; } + + T& get() const { return *ptr; } + + T* ptr; +}; + +template reference_wrapper ref(T& x) { return x; } +template reference_wrapper cref(const T& x) { return x; } + +// Simple type-traits we'll need +template +struct add_reference +{ + typedef T& type; +}; + +template +struct add_reference +{ + typedef T& type; +}; + +template +struct is_same +{ + static const bool value = false; +}; + +template +struct is_same +{ + static const bool value = true; +}; + +// For creating the constructor parameters of tuple<> +template +struct add_const_reference +{ + typedef const T& type; +}; + +template +struct add_const_reference +{ + typedef T& type; +}; + +// 6.1.3 Class template tuple: Needed for bind() implementation +template +class tuple; + +template<> class tuple<> { }; + +template +class tuple + : private tuple +{ + typedef tuple inherited; + + public: + tuple() { } + + // implicit copy-constructor is okay + + tuple(typename add_const_reference::type v, + typename add_const_reference::type... vtail) + : m_head(v), inherited(vtail...) { } + + template + tuple(const tuple& other) + : m_head(other.head()), inherited(other.tail()) { } + + template + tuple& operator=(const tuple& other) + { + m_head = other.head(); + tail() = other.tail(); + return *this; + } + + typename add_reference::type head() { return m_head; } + typename add_reference::type head() const { return m_head; } + inherited& tail() { return *this; } + const inherited& tail() const { return *this; } + + protected: + Head m_head; +}; + +template +struct make_tuple_result +{ + typedef T type; +}; + +template +struct make_tuple_result > +{ + typedef T& type; +}; + +// 6.1.3.2 Tuple creation functions +struct ignore_t { + template ignore_t& operator=(const T&) { return *this; } +} ignore; + +template +tuple::type...> +make_tuple(const Values&... values) +{ + return tuple::type...>(values...); +} + +template +tuple tie(Values&... values) +{ + return tuple(values...); +} + +// 6.1.3.3 Tuple helper classes +template +struct tuple_size; + +template<> +struct tuple_size > +{ + static const __SIZE_TYPE__ value = 0; +}; + +template +struct tuple_size > +{ + static const __SIZE_TYPE__ value = 1 + tuple_size >::value; +}; + +template +struct tuple_element; + +template +struct tuple_element > +{ + typedef typename tuple_element >::type type; +}; + +template +struct tuple_element<0, tuple > +{ + typedef Head type; +}; + +// 6.1.3.4 Element access +template +class get_impl; + +template +class get_impl > +{ + typedef typename tuple_element >::type Element; + typedef typename add_reference::type RJ; + typedef typename add_const_reference::type PJ; + typedef get_impl > Next; + + public: + static RJ get(tuple& t) + { return Next::get(t.tail()); } + + static PJ get(const tuple& t) + { return Next::get(t.tail()); } +}; + +template +class get_impl<0, tuple > +{ + typedef typename add_reference::type RJ; + typedef typename add_const_reference::type PJ; + + public: + static RJ get(tuple& t) { return t.head(); } + static PJ get(const tuple& t) { return t.head(); } +}; + +template +typename add_reference< + typename tuple_element >::type + >::type +get(tuple& t) +{ + return get_impl >::get(t); +} + +template +typename add_const_reference< + typename tuple_element >::type + >::type +get(const tuple& t) +{ + return get_impl >::get(t); +} + +// 6.1.3.5 Relational operators +inline bool operator==(const tuple<>&, const tuple<>&) { return true; } + +template +bool operator==(const tuple& t, const tuple& u) +{ + return t.head() == u.head() && t.tail() == u.tail(); +} + +template +bool operator!=(const tuple& t, const tuple& u) +{ + return !(t == u); +} + +inline bool operator<(const tuple<>&, const tuple<>&) { return false; } + +template +bool operator<(const tuple& t, const tuple& u) +{ + return (t.head() < u.head() || + (!(t.head() < u.head()) && t.tail() < u.tail())); +} + +template +bool operator>(const tuple& t, const tuple& u) +{ + return u < t; +} + +template +bool operator<=(const tuple& t, const tuple& u) +{ + return !(u < t); +} + +template +bool operator>=(const tuple& t, const tuple& u) +{ + return !(t < u); +} + +// enable_if, the breakfast of champions +template +struct enable_if { + typedef Type type; +}; + +template +struct enable_if { }; + +// 3.6 Function object binders + +// 3.6.1 Class template is_bind_expression +template +struct is_bind_expression { + static const bool value = false; +}; + +// 3.6.2 Class template is_placeholder +template +struct is_placeholder { + static const int value = 0; +}; + +// 3.6.3 Function template bind +template struct placeholder {} ; + +template struct int_c { }; + +// A tuple of integer values +template struct int_tuple {}; + +// make_indexes_impl is a helper for make_indexes +template +struct make_indexes_impl; + + +template +struct make_indexes_impl, T, Types...> +{ + typedef typename make_indexes_impl, + Types...>::type type; +}; + +template +struct make_indexes_impl > { + typedef int_tuple type; +}; + +// make_indexes takes a variable-length number of N types and +// generates an int_tuple that contains <0, 1, 2, ..., N-1>. These can +// be used as indexes for tuple's get or tuple_element operation. +template +struct make_indexes : make_indexes_impl<0, int_tuple<>, Types...> { }; + +// Get the Ith tuple element, but only if I is in bounds. +template +struct safe_tuple_element{ }; + +template +struct safe_tuple_element, + typename enable_if<(I >= 0 && + I < tuple_size >::value) + >::type> +{ + typedef typename tuple_element >::type type; +}; + +// mu maps a bound argument to an actual argument, given a tuple of +// the arguments passed to the function object returned by bind(). + +// Return the stored reference from reference_wrapper +template +inline T& mu(reference_wrapper& bound_arg, const tuple&) +{ + return bound_arg.get(); +} + +// Unwrap a tuple into separate arguments and forward to the function +// object f. +template +inline typename F::result_type +unwrap_and_forward(F& f, int_tuple, const tuple& args) +{ + return f(get(args)...); +} + +// Evaluate the inner bind expression +template +inline typename enable_if::value, + typename Bound::result_type>::type +mu(Bound& bound_arg, const tuple& args) +{ + typedef typename make_indexes::type Indexes; + return unwrap_and_forward(bound_arg, Indexes(), args); +} + +// Retrieve the Ith argument from args +template +inline typename safe_tuple_element::value - 1, + tuple >::type +mu(Bound& bound_arg, const tuple& args) +{ + return get::value-1>(args); +} + +// Return the stored value. +template +struct is_reference_wrapper { + static const bool value = false; +}; + +template +struct is_reference_wrapper > { + static const bool value = true; +}; + +template +inline typename enable_if<(!is_bind_expression::value + && !is_placeholder::value + && !is_reference_wrapper::value), + Bound&>::type +mu(Bound& bound_arg, const tuple&) +{ + return bound_arg; +} + +// +template +typename F::result_type +apply_functor(F& f, tuple& bound_args, int_tuple, + const tuple& args) +{ + return f(mu(get(bound_args), args)...); +} + +template +class bound_functor +{ + typedef typename make_indexes::type indexes; + + public: + typedef typename F::result_type result_type; + + explicit bound_functor(const F& f, const BoundArgs&... bound_args) + : f(f), bound_args(bound_args...) { } + + template + typename F::result_type operator()(Args&... args) { + return apply_functor(f, bound_args, indexes(), tie(args...)); + } + + private: + F f; + tuple bound_args; +}; + +template +struct is_bind_expression > { + static const bool value = true; +}; + +template +inline bound_functor +bind(const F& f, const BoundArgs&... bound_args) +{ + return bound_functor(f, bound_args...); +} + + +// 3.6.4 Placeholders +template +struct is_placeholder > { + static const int value = I; +}; + +placeholder<1> _1; +placeholder<2> _2; +placeholder<3> _3; +placeholder<4> _4; +placeholder<5> _5; +placeholder<6> _6; +placeholder<7> _7; +placeholder<8> _8; +placeholder<9> _9; + +// Test code +template +struct plus { + typedef T result_type; + + T operator()(T x, T y) { return x + y; } +}; + +template +struct multiplies { + typedef T result_type; + + T operator()(T x, T y) { return x * y; } +}; + +template +struct negate { + typedef T result_type; + + T operator()(T x) { return -x; } +}; + +int main() +{ + int seventeen = 17; + int forty_two = 42; + + assert(bind(plus(), _1, _2)(seventeen, forty_two) == 59); + assert(bind(plus(), _1, _1)(seventeen, forty_two) == 34); + assert(bind(plus(), _2, _1)(seventeen, forty_two) == 59); + assert(bind(plus(), 5, _1)(seventeen, forty_two) == 22); + assert(bind(plus(), ref(seventeen), _2)(seventeen, forty_two) == 59); + assert(bind(plus(), bind(multiplies(), 3, _1), _2)(seventeen, forty_two) + == 93); + return 0; +} Index: gcc/testsuite/g++.dg/template/variadic52.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic52.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic52.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,6 @@ +template +struct vector_c { }; + +vector_c v1; +vector_c v2; +vector_c v3; Index: gcc/testsuite/g++.dg/template/variadic35.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic35.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic35.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,8 @@ +template +void get_ith(const Args&... args); + +void f() +{ + get_ith<1, float>(1, 2.0, 'x'); + get_ith<1, int, double, char, int>(1, 2.0, 'x'); // { dg-error "no matching function" } +} Index: gcc/testsuite/g++.dg/template/variadic18.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic18.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic18.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,46 @@ +template class tuple { }; + +template class... Metafunctions> +struct apply_all +{ + typedef tuple::type...> type; +}; + +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + static const bool value = true; +}; + +template +struct add_pointer { + typedef T* type; +}; + +template +struct add_pointer +{ + typedef T& type; +}; + +template +struct add_reference { + typedef T& type; +}; + +template +struct add_reference +{ + typedef T& type; +}; + +int a0[is_same::type,tuple<> >::value? 1 : -1]; +int a1[is_same::type,tuple >::value? 1 : -1]; +int a2[is_same::type,tuple >::value? 1 : -1]; +int a3[is_same::type,tuple >::value? 1 : -1]; + + Index: gcc/testsuite/g++.dg/template/variadic4.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic4.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic4.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,14 @@ +// { dg-do compile } +template +class tuple {}; + +void f_none(tuple<>) {} +void f_one(tuple) {} +void f_two(tuple) {} +void f_nested(tuple, float>) { } + + +// { dg-final { scan-assembler "_Z6f_none5tupleIE" } } +// { dg-final { scan-assembler "_Z5f_one5tupleIiE" } } +// { dg-final { scan-assembler "_Z5f_two5tupleIifE" } } +// { dg-final { scan-assembler "_Z8f_nested5tupleIiS_IdcEfE" } } Index: gcc/testsuite/g++.dg/template/variadic61.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic61.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic61.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,7 @@ +struct unused; +template +struct tuple {}; + +template +void foo(tuple) { } // { dg-error "cannot unpack" } Index: gcc/testsuite/g++.dg/template/variadic44.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic44.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic44.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,12 @@ +// { dg-do compile } +template +int f(const Args&...); + +template void g(T) { } + +void h() +{ + g(&f); +} + +// { dg-final { scan-assembler "_Z1gIPFiRKiRKfEEvT_"} } Index: gcc/testsuite/g++.dg/template/variadic27.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic27.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic27.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,21 @@ +template +struct function_traits; + +template +struct function_traits { + typedef R result_type; +}; + +template +struct same_type { + static const bool value = false; +}; + +template +struct same_type { + static const bool value = true; +}; + +int a0[same_type::result_type, int>::value? 1 : -1]; +int a1[same_type::result_type, int>::value? 1 : -1]; +int a2[same_type::result_type, int>::value? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic53.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic53.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic53.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,16 @@ +template +class bound_functor +{ + public: + typedef typename F::result_type result_type; + + template + typename F::result_type operator()(Args&... args); +}; + +template +template +typename F::result_type +bound_functor::operator()(Args&... args) +{ +} Index: gcc/testsuite/g++.dg/template/variadic36.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic36.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic36.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,14 @@ +template +void f(const T&, const Args&... args) +{ + f(args); // { dg-error "packs not unpacked" } +} + +template +struct tuple_base { }; + +template +struct tuple : tuple_base { }; // { dg-error "packs not unpacked" } + +// { dg-error "args" "" { target *-*-* } 4 } +// { dg-error "Values" "" { target *-*-* } 11 } Index: gcc/testsuite/g++.dg/template/variadic19.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic19.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic19.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,18 @@ +template +struct tuple { + static const int value = 0; +}; + +template class... Metafunctions> +struct tuple...> { + static const int value = 1; +}; + +template struct add_pointer; +template struct add_reference; + +int a0[tuple::value == 0? 1 : -1]; +int a1[tuple, add_pointer >::value == 0? 1 : -1]; +int a2[tuple<>::value == 0? 1 : -1]; +int a3[tuple >::value == 1? 1 : -1]; +int a4[tuple, add_reference >::value == 1? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic5.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic5.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic5.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,37 @@ +template +struct tuple { + static const int value = 0; +}; + +template<> +struct tuple<> { + static const int value = 1; +}; + +template<> +struct tuple { + static const int value = 2; +}; + + +template<> +struct tuple { + static const int value = 3; +}; + +template +struct tuple { + static const int value = 4; +}; + +template<> +struct tuple { + static const int value = 5; +}; + +int a0[tuple::value == 0? 1 : -1]; +int a1[tuple<>::value == 1? 1 : -1]; +int a2[tuple::value == 2? 1 : -1]; +int a3[tuple::value == 3? 1 : -1]; +int a4[tuple::value == 4? 1 : -1]; +int a5[tuple::value == 5? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic-tuple.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic-tuple.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic-tuple.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,293 @@ +// { dg-do "run" } +// An implementation of TR1's using variadic teplates +// Contributed by Douglas Gregor + +#include +#include +#include + +// Trivial reference_wrapper +template +struct reference_wrapper +{ + reference_wrapper(T& x) : ptr(&x) { } + + operator T&() const { return *ptr; } + + T* ptr; +}; + +template reference_wrapper ref(T& x) { return x; } +template reference_wrapper cref(const T& x) { return x; } + +// Simple type-traits we'll need +template +struct add_reference +{ + typedef T& type; +}; + +template +struct add_reference +{ + typedef T& type; +}; + +template +struct is_same +{ + static const bool value = false; +}; + +template +struct is_same +{ + static const bool value = true; +}; + +// For creating the constructor parameters of tuple<> +template +struct add_const_reference +{ + typedef const T& type; +}; + +template +struct add_const_reference +{ + typedef T& type; +}; + +// 6.1.3 Class template tuple +template +class tuple; + +template<> class tuple<> { }; + +template +class tuple + : private tuple +{ + typedef tuple inherited; + + public: + tuple() { } + + // implicit copy-constructor is okay + + tuple(typename add_const_reference::type v, + typename add_const_reference::type... vtail) + : m_head(v), inherited(vtail...) { } + + template + tuple(const tuple& other) + : m_head(other.head()), inherited(other.tail()) { } + + template + tuple& operator=(const tuple& other) + { + m_head = other.head(); + tail() = other.tail(); + return *this; + } + + typename add_reference::type head() { return m_head; } + typename add_reference::type head() const { return m_head; } + inherited& tail() { return *this; } + const inherited& tail() const { return *this; } + + protected: + Head m_head; +}; + +template +struct make_tuple_result +{ + typedef T type; +}; + +template +struct make_tuple_result > +{ + typedef T& type; +}; + +// 6.1.3.2 Tuple creation functions +struct ignore_t { + template ignore_t& operator=(const T&) { return *this; } +} ignore; + +template +tuple::type...> +make_tuple(const Values&... values) +{ + return tuple::type...>(values...); +} + +template +tuple tie(Values&... values) +{ + return tuple(values...); +} + +// 6.1.3.3 Tuple helper classes +template +struct tuple_size; + +template<> +struct tuple_size > +{ + static const std::size_t value = 0; +}; + +template +struct tuple_size > +{ + static const std::size_t value = 1 + tuple_size >::value; +}; + +template +struct tuple_element; + +template +struct tuple_element > +{ + typedef typename tuple_element >::type type; +}; + +template +struct tuple_element<0, tuple > +{ + typedef Head type; +}; + +// 6.1.3.4 Element access +template +class get_impl; + +template +class get_impl > +{ + typedef typename tuple_element >::type Element; + typedef typename add_reference::type RJ; + typedef typename add_const_reference::type PJ; + typedef get_impl > Next; + + public: + static RJ get(tuple& t) + { return Next::get(t.tail()); } + + static PJ get(const tuple& t) + { return Next::get(t.tail()); } +}; + +template +class get_impl<0, tuple > +{ + typedef typename add_reference::type RJ; + typedef typename add_const_reference::type PJ; + + public: + static RJ get(tuple& t) { return t.head(); } + static PJ get(const tuple& t) { return t.head(); } +}; + +template +typename add_reference< + typename tuple_element >::type + >::type +get(tuple& t) +{ + return get_impl >::get(t); +} + +template +typename add_const_reference< + typename tuple_element >::type + >::type +get(const tuple& t) +{ + return get_impl >::get(t); +} + +// 6.1.3.5 Relational operators +inline bool operator==(const tuple<>&, const tuple<>&) { return true; } + +template +bool operator==(const tuple& t, const tuple& u) +{ + return t.head() == u.head() && t.tail() == u.tail(); +} + +template +bool operator!=(const tuple& t, const tuple& u) +{ + return !(t == u); +} + +inline bool operator<(const tuple<>&, const tuple<>&) { return false; } + +template +bool operator<(const tuple& t, const tuple& u) +{ + return (t.head() < u.head() || + (!(t.head() < u.head()) && t.tail() < u.tail())); +} + +template +bool operator>(const tuple& t, const tuple& u) +{ + return u < t; +} + +template +bool operator<=(const tuple& t, const tuple& u) +{ + return !(u < t); +} + +template +bool operator>=(const tuple& t, const tuple& u) +{ + return !(t < u); +} + +int a0[tuple_size >::value == 0? 1 : -1]; +int a1[tuple_size >::value == 3? 1 : -1]; +int a2a[is_same >::type, int> + ::value? 1 : -1]; +int a2b[is_same >::type, float> + ::value? 1 : -1]; +int a2c[is_same >::type, double> + ::value? 1 : -1]; + +int main() +{ + tuple<> t0; + tuple t1(1); + tuple t2(1, 3.14159f); + tuple t3a(1, 3.14159f, "Hello, world!"); + tuple t3b(t3a); + t3b = t3a; + // t3a = t3b; DPG: triggers an error, as it should. + + tuple t3c = + make_tuple(17, 2.718281828, std::string("Fun")); + + int seventeen = 17; + double pi = 3.14159; + tuple seventeen_pi = make_tuple(ref(seventeen), ref(pi)); + tuple seventeen_pi2 = + make_tuple(ref(seventeen), cref(pi)); + tuple seventeen_pi_tied = tie(seventeen, pi); + assert(get<0>(t3a) == 1); + assert(get<1>(t3a) == 3.14159f); + assert(std::strcmp(get<2>(t3a), "Hello, world!") == 0); + + assert(t3a == t3b); + assert(!(t3a != t3b)); + assert(!(t3a < t3b)); + assert(!(t3a > t3b)); + assert(t3a <= t3b && t3b <= t3a); + assert(t3a >= t3b && t3b >= t3a); +} Index: gcc/testsuite/g++.dg/template/variadic62.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic62.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic62.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,7 @@ +template +Result bind(Functor, ArgTypes...) { } + +void f() +{ + bind(17, 20, 22); +} Index: gcc/testsuite/g++.dg/template/variadic45.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic45.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic45.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,9 @@ +template +int& f(Args...); + +template +float& f(T1, T2); + +float& g() { + return f(17, 3.14159); +} Index: gcc/testsuite/g++.dg/template/variadic28.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic28.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic28.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,24 @@ +template +struct function_traits; + +template +struct function_traits { + typedef R result_type; +}; + +template +struct same_type { + static const bool value = false; +}; + +template +struct same_type { + static const bool value = true; +}; + +int a0[same_type::result_type, int>::value? 1 : -1]; +int a1[same_type::result_type, int>::value? 1 : -1]; +int a2[same_type::result_type, int>::value? 1 : -1]; +int a3[same_type::result_type, int>::value? 1 : -1]; +int a4[same_type::result_type, int>::value? 1 : -1]; +int a5[same_type::result_type, int>::value? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic54.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic54.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic54.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,11 @@ +template +class bound_functor +{ + public: + bound_functor(); +}; + +template +bound_functor::bound_functor() +{ +} Index: gcc/testsuite/g++.dg/template/variadic37.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic37.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic37.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,9 @@ +template +struct tuple +{ + static const __SIZE_TYPE__ length = sizeof...(Values); +}; + +int a0[tuple<>::length == 0? 1 : -1]; +int a1[tuple::length == 1? 1 : -1]; +int a2[tuple::length == 2? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic6.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic6.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic6.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,11 @@ +template +struct tuple_base {}; + +template +struct tuple : public tuple_base +{ +}; + +tuple<> zero; +tuple one; +tuple two; Index: gcc/testsuite/g++.dg/template/variadic63.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic63.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic63.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,23 @@ +template struct tuple {}; + +template +struct nested +{ + typedef tuple...> type; +}; + +template +struct is_same +{ + static const bool value = false; +}; + +template +struct is_same +{ + static const bool value = true; +}; + +int a0[is_same::type, + tuple, + tuple > >::value? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic46.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic46.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic46.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,10 @@ +template +int& f(Args&...); + +template +float& f(const Args&...); + +int& g(int x, float y) +{ + return f(x, y); +} Index: gcc/testsuite/g++.dg/template/variadic29.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic29.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic29.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,34 @@ +template +struct function_traits; + +template +struct function_traits { + typedef R result_type; +}; + +template +struct function_traits { + typedef R result_type; +}; + +template +struct function_traits { + typedef R result_type; +}; + +template +struct same_type { + static const bool value = false; +}; + +template +struct same_type { + static const bool value = true; +}; + +struct X {}; + +int a0[same_type::result_type, int>::value? 1 : -1]; +int a1[same_type::result_type, int>::value? 1 : -1]; +int a2[same_type::result_type, int>::value? 1 : -1]; +int a3[same_type::result_type, int>::value? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic55.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic55.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic55.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,11 @@ +template +class bound_functor +{ + public: + bound_functor(const BoundArgs&... bound_args); +}; + +template +bound_functor::bound_functor(const BoundArgs&...) +{ +} Index: gcc/testsuite/g++.dg/template/variadic38.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic38.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic38.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,5 @@ +template +struct int_vec {}; + +template +struct int_vec<0, (Values+1)...> {}; // { dg-error "involves template parameter" } Index: gcc/testsuite/g++.dg/template/variadic7.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic7.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic7.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,32 @@ +template +struct tuple_base { + static const int value = 0; +}; + +template<> +struct tuple_base { + static const int value = 1; +}; + +template<> +struct tuple_base { + static const int value = 2; +}; + +template<> +struct tuple_base { + static const int value = 3; +}; + +template +struct int_tuple : tuple_base { }; + +template +struct tuple_int : tuple_base { }; + +int a0a[int_tuple::value == 0? 1 : -1]; +int a0b[int_tuple::value == 0? 1 : -1]; +int a1a[int_tuple<>::value == 1? 1 : -1]; +int a1b[tuple_int<>::value == 1? 1 : -1]; +int a2[int_tuple::value == 2? 1 : -1]; +int a3[tuple_int::value == 3? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic64.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic64.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic64.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,21 @@ +// { dg-do "run" } +template struct bomb; + +template +struct bomb { + static const T value = 0; +}; + +template +struct bomb { + static const T value = v + bomb::value; +}; + +extern "C" void abort(); + +int main() { + bomb b; + if (b.value != 10) + abort(); + return 0; +} Index: gcc/testsuite/g++.dg/template/variadic47.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic47.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic47.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,17 @@ +template struct wrap { }; + +template +int& f(const Args&...); + +template +float& f(const wrap&...); + +int& g(int x, float y, double z) +{ + return f(x, y, z); +} + +float& h(wrap x, wrap y, wrap z) +{ + return f(x, y, z); +} Index: gcc/testsuite/g++.dg/template/variadic56.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic56.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic56.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,18 @@ +template +struct tuple { }; + +template +struct tuple { + int foo(); +}; + +template +struct tuple { + int bar(); +}; + +template +int tuple::foo() { return 0; } + +template +int tuple::bar() { return 0; } Index: gcc/testsuite/g++.dg/template/variadic39.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic39.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic39.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,12 @@ +template +struct tuple {}; + +template +struct tuple { }; // { dg-error "end" } + + +template +struct int_vec { }; + +template +struct int_vec { }; // { dg-error "end" } Index: gcc/testsuite/g++.dg/template/variadic8.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic8.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic8.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,22 @@ +template +struct tuple_base { + static const int value = 0; +}; + +template<> +struct tuple_base +{ + static const int value = 1; +}; + +template +struct tuple_base +{ + static const int value = 2; +}; + +template +struct tuple_of_pointers : tuple_base { }; + +int a1[tuple_of_pointers::value == 1? 1 : -1]; +int a2[tuple_of_pointers::value == 2? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic65.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic65.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic65.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,11 @@ +template struct list {}; + +template +struct push_front; + +template +struct push_front, Head> { + typedef list type; // { dg-error "parameter packs not unpacked" } +}; + +// { dg-error "Elements" "" { target *-*-* } 8 } Index: gcc/testsuite/g++.dg/template/variadic48.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic48.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic48.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,9 @@ +template +int& f(const T&, Args...); + +template +float& f(const T&); + +float& g() { + return f(17); +} Index: gcc/testsuite/g++.dg/template/variadic-mem_fn.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic-mem_fn.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic-mem_fn.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,49 @@ +// { dg-do "run" } +// A basic implementation of TR1's mem_fn using variadic teplates +// Contributed by Douglas Gregor +#include + +template +class Mem_fn +{ + public: + explicit Mem_fn(R (Class::*pmf)(Args...)) : pmf(pmf) { } + + R operator()(Class& object, Args... args) + { + return (object.*pmf)(args...); + } + + R operator()(Class* object, Args... args) + { + return (object->*pmf)(args...); + } + + R (Class::*pmf)(Args...); +}; + +template +inline Mem_fn +mem_fn(R (Class::* pmf)(Args...)) +{ + return Mem_fn(pmf); +} + +class X { + public: + int negate(int x) { return -x; } + int plus(int x, int y) { return x + y; } +}; + +int main() +{ + X x; + X* xp = &x; + + assert(mem_fn(&X::negate)(x, 17) == -17); + assert(mem_fn(&X::negate)(xp, 17) == -17); + assert(mem_fn(&X::plus)(x, 17, 25) == 42); + assert(mem_fn(&X::plus)(xp, 17, 25) == 42); + + return 0; +} Index: gcc/testsuite/g++.dg/template/variadic57.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic57.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic57.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,15 @@ +template +struct array { + int foo(); +}; + +template +struct array { + int bar(); +}; + +template +int array::foo() { } + +template +int array::bar() { } Index: gcc/testsuite/g++.dg/template/variadic9.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic9.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic9.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,37 @@ +template +struct pair {}; + +template +struct tuple { + static const int value = 0; +}; + +template<> +struct tuple > { + static const int value = 1; +}; + +template +struct tuple > { + static const int value = 2; +}; + +template +struct tuple, pair > { + static const int value = 3; +}; + + +template +struct X { + template + struct Y + { + typedef tuple...> type; + }; +}; + +int a0[X::Y::type::value == 0? 1 : -1]; +int a1[X::Y::type::value == 1? 1 : -1]; +int a2[X::Y::type::value == 2? 1 : -1]; +int a3[X::Y::type::value == 3? 1 : -1]; Index: gcc/testsuite/g++.dg/template/variadic66.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic66.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic66.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,20 @@ +struct A {}; +struct B {}; +struct C {}; + +template +struct mixed_up : public Mixins... +{ +}; + +void fA(A); +void fB(B); +void fC(C); + +void g() +{ + mixed_up m; + fA(m); + fB(m); + fC(m); +} Index: gcc/testsuite/g++.dg/template/variadic49.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic49.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic49.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,8 @@ +int& f(...); + +template +float& f(Args...); + +float& g() { + return f(17, 3.14159); +} Index: gcc/testsuite/g++.dg/template/variadic58.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic58.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic58.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,15 @@ +#include + +template +void foo(Args...) { } + +template +void bar(Args... args) { + foo(Args()...); + foo(args = args...); + foo(reinterpret_cast(&args)...); + foo(const_cast(args)...); + foo(static_cast(&args)...); + foo(dynamic_cast(&args)...); + foo(typeid(Args)...); +} Index: gcc/testsuite/g++.dg/template/variadic67.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic67.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic67.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,32 @@ +// { dg-do "run" } +struct A {}; +struct B {}; +struct C {}; + +template void f(int idx) throw(Exceptions...) { + if (idx == 0) throw A(); + else if (idx == 1) throw B(); + else if (idx == 2) throw C(); +} + +extern "C" void abort(); + +int main() +{ + try { + f(0); + abort(); + } catch (A) { + } + try { + f(1); + abort(); + } catch (B) { + } + try { + f(2); + abort(); + } catch (C) { + } + return 0; +} Index: gcc/testsuite/g++.dg/template/variadic59.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic59.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic59.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,3 @@ +template +void print(T t, VarArgs args); // { dg-error "packs not unpacked" } +// { dg-error "VarArgs" "" { target *-*-* } 2 } Index: gcc/testsuite/g++.dg/template/variadic68.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic68.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic68.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,23 @@ +// { dg-do "run" } + +extern "C" void abort(); + +template +void f(T* expected_values, int n) +{ + if (sizeof...(Values) != n) + abort (); + + T values[] = { Values... }; + for (int i = 0; i < n; ++i) + if (values[i] != expected_values[i]) + abort(); +} + +int main() +{ + int test_arr1[3] = { 1, 2, 3 }; + f(test_arr1, 3); + + return 0; +} Index: gcc/testsuite/g++.dg/template/variadic10.C =================================================================== --- gcc/testsuite/g++.dg/template/variadic10.C (.../vendor/gcc-4.1.1) (revision 0) +++ gcc/testsuite/g++.dg/template/variadic10.C (.../branches/variadic-templates) (revision 425) @@ -0,0 +1,21 @@ +template +struct pair {}; + +template +struct tuple { + static const int value = 0; +}; + +template<> +struct tuple > { }; + +template +struct X { + template + struct Y + { + typedef tuple...> type; // { dg-error "mismatched argument pack lengths" } + }; +}; + +X::Y::type honk; Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c (.../vendor/gcc-4.1.1) (revision 425) +++ gcc/cp/typeck.c (.../branches/variadic-templates) (revision 425) @@ -997,7 +997,9 @@ comptypes (tree t1, tree t2, int strict) case TEMPLATE_TEMPLATE_PARM: case BOUND_TEMPLATE_TEMPLATE_PARM: if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2) - || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)) + || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2) + || (TEMPLATE_TYPE_PARAMETER_PACK (t1) + != TEMPLATE_TYPE_PARAMETER_PACK (t2))) return false; if (!comp_template_parms (DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t1)), @@ -1056,7 +1058,9 @@ comptypes (tree t1, tree t2, int strict) case TEMPLATE_TYPE_PARM: if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2) - || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)) + || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2) + || (TEMPLATE_TYPE_PARAMETER_PACK (t1) + != TEMPLATE_TYPE_PARAMETER_PACK (t2))) return false; break; @@ -1086,6 +1090,9 @@ comptypes (tree t1, tree t2, int strict) return false; break; + case PACK_UNPACK_TYPE: + return same_type_p (PACK_UNPACK_PATTERN (t1), PACK_UNPACK_PATTERN (t2)); + default: return false; } Index: gcc/cp/decl.c =================================================================== --- gcc/cp/decl.c (.../vendor/gcc-4.1.1) (revision 425) +++ gcc/cp/decl.c (.../branches/variadic-templates) (revision 425) @@ -6682,6 +6682,7 @@ grokdeclarator (const cp_declarator *dec cp_storage_class storage_class; bool unsigned_p, signed_p, short_p, long_p, thread_p; bool type_was_error_mark_node = false; + bool pack_unpack_p = declarator? declarator->pack_unpack_p : false; signed_p = declspecs->specs[(int)ds_signed]; unsigned_p = declspecs->specs[(int)ds_unsigned]; @@ -7636,6 +7637,16 @@ grokdeclarator (const cp_declarator *dec attrlist = &returned_attrs; } + /* Handle parameter packs. */ + if (pack_unpack_p) + { + if (decl_context == PARM) + /* Turn the type into a pack/unpack type.*/ + type = make_argument_pack_unpack (type); + else + error ("non-parameter %qs cannot be a parameter pack", name); + } + /* Did array size calculations overflow? */ if (TREE_CODE (type) == ARRAY_TYPE @@ -8632,6 +8643,13 @@ grokparms (cp_parameter_declarator *firs init = check_default_argument (decl, init); } + if (TREE_CODE (decl) == PARM_DECL + && FUNCTION_PARAMETER_PACK_P (decl) + && parm->next) + /* Function parameter packs must be last in the parameter + list. */ + error ("parameter packs must be at the end of the parameter list"); + TREE_CHAIN (decl) = decls; decls = decl; result = tree_cons (init, type, result); @@ -9599,6 +9617,8 @@ xref_basetypes (tree ref, tree base_list if (access == access_default_node) access = default_access; + if (PACK_UNPACK_P (basetype)) + basetype = PACK_UNPACK_PATTERN (basetype); if (TREE_CODE (basetype) == TYPE_DECL) basetype = TREE_TYPE (basetype); if (TREE_CODE (basetype) != RECORD_TYPE @@ -9644,6 +9664,11 @@ xref_basetypes (tree ref, tree base_list error ("duplicate base type %qT invalid", basetype); continue; } + + if (PACK_UNPACK_P (TREE_VALUE (base_list))) + /* Regenerate the pack/unpack type for the bases. */ + basetype = make_argument_pack_unpack (basetype); + TYPE_MARKED_P (basetype) = 1; base_binfo = copy_binfo (base_binfo, basetype, ref, Index: gcc/cp/cp-tree.def =================================================================== --- gcc/cp/cp-tree.def (.../vendor/gcc-4.1.1) (revision 425) +++ gcc/cp/cp-tree.def (.../branches/variadic-templates) (revision 425) @@ -342,6 +342,65 @@ DEFTREECODE (STMT_EXPR, "stmt_expr", tcc is applied. */ DEFTREECODE (UNARY_PLUS_EXPR, "unary_plus_expr", tcc_unary, 1) +/* Represents an argument pack of types (or templates). An argument + pack stores zero or more arguments that will be used to instantiate + a parameter pack. + + ARGUMENT_PACK_ARGS retrieves the arguments stored in the argument + pack. + + Example: + template + class tuple { ... }; + + tuple t; + + Values is a (template) parameter pack. When tuple is instantiated, the Values parameter pack is instantiated + with the argment pack . ARGUMENT_PACK_ARGS will + be a TREE_VEC containing int, float, and double. */ +DEFTREECODE (TYPE_ARGUMENT_PACK, "type_argument_pack", tcc_type, 0) + +/* Represents an argument pack of values, which can be used either for + non-type template arguments or function call arguments. + + NONTYPE_ARGUMENT_PACK plays precisely the same role as + TYPE_ARGUMENT_PACK, but will be used for packing non-type template + arguments (e.g., "int... Dimensions") or function arguments ("const + Args&... args"). +*/ +DEFTREECODE (NONTYPE_ARGUMENT_PACK, "nontype_argument_pack", tcc_expression, 1) + +/* Represents a type expression that will be packed into or unpacked + from an argument pack. + + PACK_UNPACK_PATTERN retrieves the packing/unpacked pattern. This is + the type or expression that we will substitute into with each + argument in an argument pack. + + SET_PACK_UNPACK_PATTERN sets the packing/unpacking pattern. + + PACK_UNPACK_PARAMETER_PACKS contains a TREE_LIST of the parameter + packs that are used in this pack/unpack expression. + + Example: + template + struct tied : tuple { + // ... + }; + + The derivation from tuple contains a PACK_UNPACK_TYPE for the + template arguments. Its PACK_UNPACK_EXPR is "Values&" and its + PACK_UNPACK_PARAMETER_PACKS will contain "Values". */ +DEFTREECODE (PACK_UNPACK_TYPE, "pack_unpack_type", tcc_type, 0) + +/* Represents an expression that will be packed into or unpacked + from an argument pack. + + PACK_UNPACK_EXPR plays precisely the same role as PACK_UNPACK_TYPE, + but will be used for packing/unpacking expressions. */ +DEFTREECODE (PACK_UNPACK_EXPR, "pack_unpack_expr", tcc_expression, 1) + /* Local variables: mode:c Index: gcc/cp/cp-objcp-common.c =================================================================== --- gcc/cp/cp-objcp-common.c (.../vendor/gcc-4.1.1) (revision 425) +++ gcc/cp/cp-objcp-common.c (.../branches/variadic-templates) (revision 425) @@ -123,6 +123,15 @@ cp_tree_size (enum tree_code code) case TEMPLATE_PARM_INDEX: return sizeof (template_parm_index); case DEFAULT_ARG: return sizeof (struct tree_default_arg); case OVERLOAD: return sizeof (struct tree_overload); + + case TYPE_ARGUMENT_PACK: + case PACK_UNPACK_TYPE: + return sizeof (struct tree_common); + + case NONTYPE_ARGUMENT_PACK: + case PACK_UNPACK_EXPR: + return sizeof (struct tree_exp); + default: gcc_unreachable (); } Index: gcc/cp/error.c =================================================================== --- gcc/cp/error.c (.../vendor/gcc-4.1.1) (revision 425) +++ gcc/cp/error.c (.../branches/variadic-templates) (revision 425) @@ -136,7 +136,9 @@ dump_scope (tree scope, int flags) static void dump_template_argument (tree arg, int flags) { - if (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL) + if (ARGUMENT_PACK_P (arg)) + dump_template_argument_list (ARGUMENT_PACK_ARGS (arg), flags); + else if (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL) dump_type (arg, flags & ~TFF_CLASS_KEY_OR_ENUM); else dump_expr (arg, (flags | TFF_EXPR_IN_PARENS) & ~TFF_CLASS_KEY_OR_ENUM); @@ -154,9 +156,17 @@ dump_template_argument_list (tree args, for (i = 0; i< n; ++i) { - if (need_comma) + tree arg = TREE_VEC_ELT (args, i); + + /* Only print a comma if we know there is an argument coming. In + the case of an empty template argument pack, no actual + argument will be printed. */ + if (need_comma + && (!ARGUMENT_PACK_P (arg) + || TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg)) > 0)) pp_separate_with_comma (cxx_pp); - dump_template_argument (TREE_VEC_ELT (args, i), flags); + + dump_template_argument (arg, flags); need_comma = 1; } } @@ -174,6 +184,8 @@ dump_template_parameter (tree parm, int if (flags & TFF_DECL_SPECIFIERS) { pp_cxx_identifier (cxx_pp, "class"); + if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (p))) + pp_cxx_identifier (cxx_pp, "..."); if (DECL_NAME (p)) pp_cxx_tree_identifier (cxx_pp, DECL_NAME (p)); } @@ -370,6 +382,11 @@ dump_type (tree t, int flags) pp_cxx_right_paren (cxx_pp); break; + case PACK_UNPACK_TYPE: + dump_type (PACK_UNPACK_PATTERN (t), flags); + pp_cxx_identifier (cxx_pp, "..."); + break; + default: pp_unsupported_tree (cxx_pp, t); /* Fall through to error. */ @@ -1216,14 +1233,19 @@ dump_template_parms (tree info, int prim { tree arg = TREE_VEC_ELT (args, ix); - if (ix) - pp_separate_with_comma (cxx_pp); - - if (!arg) - pp_identifier (cxx_pp, "