This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Variadic templates, third revision (2/3)
- From: "Doug Gregor" <doug dot gregor at gmail dot com>
- To: "GCC Patches" <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 1 Nov 2006 11:18:56 -0500
- Subject: [C++ PATCH] Variadic templates, third revision (2/3)
This patch addresses PR c++/20599 by introducing support for variadic
templates:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20599
This is the third revision of the variadic templates patch. It
addresses several small bugs, cleans up the terminology used in the
patch, tweaks the syntax slightly, and allows the use of variadic
templates in several more C++ contexts:
- Base specifier list
- Throw specifier list
- Initializer list
- Base class initializer list
This patch is dependent on the experimental C++0x mode patch, posted here:
http://gcc.gnu.org/ml/gcc-patches/2006-11/msg00024.html
More information about variadic templates is available here:
http://www.generic-programming.org/~dgregor/cpp/variadic-templates.html
This is part 2 of 3. It contains tests for variadic templates.
Tested on mainline with i686-pc-linux-gnu; no new regressions. All new
tests pass.
Okay for mainline?
Doug Gregor
Open Systems Lab @ Indiana University
2006-11-01 Douglas Gregor <doug.gregor@gmail.com>
PR c++/20599
* g++.dg/template/variadic-bind.C: New.
* g++.dg/template/variadic-function.C: New.
* g++.dg/template/variadic-mem_fn.C: New.
* g++.dg/template/variadic-tuple.C: New.
* g++.dg/template/variadic1.C: New.
* g++.dg/template/variadic2.C: New.
* g++.dg/template/variadic3.C: New.
* g++.dg/template/variadic4.C: New.
* g++.dg/template/variadic5.C: New.
* g++.dg/template/variadic6.C: New.
* g++.dg/template/variadic7.C: New.
* g++.dg/template/variadic8.C: New.
* g++.dg/template/variadic9.C: New.
* g++.dg/template/variadic10.C: New.
* g++.dg/template/variadic11.C: New.
* g++.dg/template/variadic12.C: New.
* g++.dg/template/variadic13.C: New.
* g++.dg/template/variadic14.C: New.
* g++.dg/template/variadic15.C: New.
* g++.dg/template/variadic16.C: New.
* g++.dg/template/variadic17.C: New.
* g++.dg/template/variadic18.C: New.
* g++.dg/template/variadic19.C: New.
* g++.dg/template/variadic20.C: New.
* g++.dg/template/variadic21.C: New.
* g++.dg/template/variadic22.C: New.
* g++.dg/template/variadic23.C: New.
* g++.dg/template/variadic24.C: New.
* g++.dg/template/variadic25.C: New.
* g++.dg/template/variadic26.C: New.
* g++.dg/template/variadic27.C: New.
* g++.dg/template/variadic28.C: New.
* g++.dg/template/variadic29.C: New.
* g++.dg/template/variadic30.C: New.
* g++.dg/template/variadic31.C: New.
* g++.dg/template/variadic32.C: New.
* g++.dg/template/variadic33.C: New.
* g++.dg/template/variadic34.C: New.
* g++.dg/template/variadic35.C: New.
* g++.dg/template/variadic36.C: New.
* g++.dg/template/variadic37.C: New.
* g++.dg/template/variadic38.C: New.
* g++.dg/template/variadic39.C: New.
* g++.dg/template/variadic40.C: New.
* g++.dg/template/variadic41.C: New.
* g++.dg/template/variadic42.C: New.
* g++.dg/template/variadic43.C: New.
* g++.dg/template/variadic44.C: New.
* g++.dg/template/variadic45.C: New.
* g++.dg/template/variadic46.C: New.
* g++.dg/template/variadic47.C: New.
* g++.dg/template/variadic48.C: New.
* g++.dg/template/variadic49.C: New.
* g++.dg/template/variadic50.C: New.
* g++.dg/template/variadic51.C: New.
* g++.dg/template/variadic52.C: New.
* g++.dg/template/variadic53.C: New.
* g++.dg/template/variadic54.C: New.
* g++.dg/template/variadic55.C: New.
* g++.dg/template/variadic56.C: New.
* g++.dg/template/variadic57.C: New.
* g++.dg/template/variadic58.C: New.
* g++.dg/template/variadic59.C: New.
* g++.dg/template/variadic60.C : New.
* g++.dg/template/variadic61.C : New.
* g++.dg/template/variadic62.C : New.
* g++.dg/template/variadic63.C : New.
* g++.dg/template/variadic64.C : New.
* g++.dg/template/variadic65.C : New.
* g++.dg/template/variadic66.C : New.
* g++.dg/template/variadic67.C : New.
* g++.dg/template/variadic68.C : New.
* g++.dg/template/variadic69.C : New.
* g++.dg/template/variadic70.C : New.
* g++.dg/template/variadic71.C : New.
* g++.dg/template/variadic72.C : New.
* g++.dg/template/variadic73.C : New.
Index: g++.dg/template/variadic-function.C
===================================================================
--- g++.dg/template/variadic-function.C (revision 0)
+++ g++.dg/template/variadic-function.C (revision 0)
@@ -0,0 +1,96 @@
+// { dg-options "-std=c++0x" }
+// { dg-do "run" }
+// A basic implementation of TR1's function using variadic teplates
+// Contributed by Douglas Gregor <doug.gregor@gmail.com>
+#include <cassert>
+
+template<typename Signature>
+class function;
+
+template<typename R, typename... Args>
+class invoker_base
+{
+ public:
+ virtual ~invoker_base() { }
+ virtual R invoke(Args...) = 0;
+ virtual invoker_base* clone() = 0;
+};
+
+template<typename F, typename R, typename... Args>
+class functor_invoker : public invoker_base<R, Args...>
+{
+ 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<typename R, typename... Args>
+class function<R (Args...)> {
+ public:
+ typedef R result_type;
+
+ function() : invoker (0) { }
+
+ function(const function& other) : invoker(0) {
+ if (other.invoker)
+ invoker = other.invoker->clone();
+ }
+
+ template<typename F>
+ function(const F& f) : invoker(0) {
+ invoker = new functor_invoker<F, R, Args...>(f);
+ }
+
+ ~function() {
+ if (invoker)
+ delete invoker;
+ }
+
+ function& operator=(const function& other) {
+ function(other).swap(*this);
+ return *this;
+ }
+
+ template<typename F>
+ function& operator=(const F& f) {
+ function(f).swap(*this);
+ return *this;
+ }
+
+ void swap(function& other) {
+ invoker_base<R, Args...>* tmp = invoker;
+ invoker = other.invoker;
+ other.invoker = tmp;
+ }
+
+ result_type operator()(Args... args) const {
+ assert(invoker);
+ return invoker->invoke(args...);
+ }
+
+ private:
+ invoker_base<R, Args...>* invoker;
+};
+
+struct plus {
+ template<typename T> T operator()(T x, T y) { return x + y; }
+};
+
+struct multiplies {
+ template<typename T> T operator()(T x, T y) { return x * y; }
+};
+
+int main()
+{
+ function<int(int, int)> f1 = plus();
+ assert(f1(3, 5) == 8);
+
+ f1 = multiplies();
+ assert(f1(3, 5) == 15);
+
+ return 0;
+}
Index: g++.dg/template/variadic69.C
===================================================================
--- g++.dg/template/variadic69.C (revision 0)
+++ g++.dg/template/variadic69.C (revision 0)
@@ -0,0 +1,34 @@
+// { dg-options "-std=c++0x" }
+template<typename T>
+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<typename... Values>
+struct myclass : public stored_value<Values>...
+{
+ myclass() { }
+
+ explicit myclass(const Values&... values)
+ : stored_value<Values>(values)... { }
+
+ explicit myclass(int x, const Values&... values)
+ : stored_value<Values>(x, values)... { }
+
+};
+
+void f()
+{
+ int i;
+ float f;
+ myclass<int*, float*> ifp1;
+ myclass<int*, float*> ifp2(&i, &f);
+ myclass<int*, float*> ifp3(1, &i, &f);
+}
Index: g++.dg/template/variadic11.C
===================================================================
--- g++.dg/template/variadic11.C (revision 0)
+++ g++.dg/template/variadic11.C (revision 0)
@@ -0,0 +1,18 @@
+// { dg-options "-std=c++0x" }
+template<typename...> struct count;
+
+template<>
+struct count<> {
+ static const int value = 0;
+};
+
+template<typename T, typename... Args>
+struct count<T, Args...> {
+ static const int value = 1 + count<Args...>::value;
+};
+
+int a0[count<>::value == 0? 1 : -1];
+int a1[count<char>::value == 1? 1 : -1];
+int a2[count<char, short>::value == 2? 1 : -1];
+int a3[count<char, short, int>::value == 3? 1 : -1];
+int a4[count<char, short, int, long>::value == 4? 1 : -1];
Index: g++.dg/template/variadic20.C
===================================================================
--- g++.dg/template/variadic20.C (revision 0)
+++ g++.dg/template/variadic20.C (revision 0)
@@ -0,0 +1,45 @@
+// { dg-options "-std=c++0x" }
+template<typename T> struct add_pointer;
+template<typename T> struct add_reference;
+
+template<template<class T> class... Metafunctions>
+struct metatuple {
+ static const int value = 0;
+};
+
+template<>
+struct metatuple<add_pointer> {
+ static const int value = 1;
+};
+
+template<template<class T> class Meta>
+struct metatuple<Meta, Meta> {
+ static const int value = 2;
+};
+
+template<template<class T> class... Metafunctions>
+struct metatuple<add_pointer, Metafunctions...> {
+ static const int value = 3;
+};
+
+template<template<class T> class First,
+ template<class T> class... Metafunctions>
+struct metatuple<First, Metafunctions...> {
+ static const int value = 4;
+};
+
+template<template<class T> class First,
+ template<class T> class Second,
+ template<class T> class... Metafunctions>
+struct metatuple<First, Second, Metafunctions...> {
+ static const int value = 5;
+};
+
+int a0[metatuple<>::value == 0? 1 : -1];
+int a1[metatuple<add_pointer>::value == 1? 1 : -1];
+int a2a[metatuple<add_pointer, add_pointer>::value == 2? 1 : -1];
+int a2b[metatuple<add_reference, add_reference>::value == 2? 1 : -1];
+int a3[metatuple<add_pointer, add_reference>::value == 3? 1 : -1];
+int a4[metatuple<add_reference>::value == 4? 1 : -1];
+int a5[metatuple<add_reference, add_pointer>::value == 5? 1 : -1];
+
Index: g++.dg/template/variadic12.C
===================================================================
--- g++.dg/template/variadic12.C (revision 0)
+++ g++.dg/template/variadic12.C (revision 0)
@@ -0,0 +1,42 @@
+// { dg-options "-std=c++0x" }
+// A tuple type
+template<typename... Args> struct tuple { };
+
+// Determine if two types are the same
+template<typename T, typename U>
+struct is_same {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T> {
+ static const bool value = true;
+};
+
+// Append 'T' to the end of Tuple
+template<typename T, typename Tuple>
+struct append_to_tuple;
+
+template<typename T, typename... Args>
+struct append_to_tuple<T, tuple<Args...> > {
+ typedef tuple<Args..., T> type;
+};
+
+// Reverse a sequence of arguments (and return the result as a tuple)
+template<typename... Args> struct reverse;
+
+template<typename T, typename... Args>
+struct reverse<T, Args...> {
+ typedef typename append_to_tuple<T, typename reverse<Args...>::type>::type
+ type;
+};
+
+template<>
+struct reverse<> {
+ typedef tuple<> type;
+};
+
+int a0[is_same<reverse<>::type, tuple<> >::value? 1 : -1];
+int a1[is_same<reverse<int>::type, tuple<int> >::value? 1 : -1];
+int a2[is_same<reverse<char, int>::type, tuple<int, char> >::value? 1 : -1];
+int a3[is_same<reverse<char, int, long>::type, tuple<long, int, char> >::value? 1 : -1];
Index: g++.dg/template/variadic21.C
===================================================================
--- g++.dg/template/variadic21.C (revision 0)
+++ g++.dg/template/variadic21.C (revision 0)
@@ -0,0 +1,7 @@
+// { dg-options "-std=c++0x" }
+template<typename T, int... Dims>
+struct array { };
+
+array<int> a0;
+array<int, 1> a1;
+array<int, 1, 2, 3, 4> a1234;
Index: g++.dg/template/variadic30.C
===================================================================
--- g++.dg/template/variadic30.C (revision 0)
+++ g++.dg/template/variadic30.C (revision 0)
@@ -0,0 +1,11 @@
+// { dg-options "-std=c++0x" }
+template<typename... T>
+void eat(T...);
+
+void f()
+{
+ eat();
+ eat(1);
+ eat(1, 2);
+ eat(17, 3.14159, "Hello, World!");
+}
Index: g++.dg/template/variadic13.C
===================================================================
--- g++.dg/template/variadic13.C (revision 0)
+++ g++.dg/template/variadic13.C (revision 0)
@@ -0,0 +1,19 @@
+// { dg-options "-std=c++0x" }
+template<typename... Args> struct tuple1 { };
+template<typename... Args> struct tuple2 { };
+
+template<typename T, typename U>
+struct same_tuple_args {
+ static const bool value = false;
+};
+
+template<typename... Args>
+struct same_tuple_args<tuple1<Args...>, tuple2<Args...> > {
+ static const bool value = true;
+};
+
+int same0[same_tuple_args<tuple1<>, tuple2<> >::value? 1 : -1];
+int same1[same_tuple_args<tuple1<int>, tuple2<int> >::value? 1 : -1];
+int same2[same_tuple_args<tuple1<float, int>, tuple2<float, int> >::value? 1 : -1];
+int diff0[!same_tuple_args<tuple1<>, tuple2<int> >::value? 1 : -1];
+int diff1[!same_tuple_args<tuple1<int, float>, tuple2<float, int> >::value? 1 : -1];
Index: g++.dg/template/variadic22.C
===================================================================
--- g++.dg/template/variadic22.C (revision 0)
+++ g++.dg/template/variadic22.C (revision 0)
@@ -0,0 +1,21 @@
+// { dg-options "-std=c++0x" }
+template<typename R, typename... ArgTypes>
+struct make_function_type
+{
+ typedef R type(ArgTypes... args);
+};
+
+template<typename T, typename U>
+struct is_same {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T> {
+ static const bool value = true;
+};
+
+int a0[is_same<make_function_type<int>::type, int()>::value? 1 : -1];
+int a1[is_same<make_function_type<int, float>::type, int(float)>::value? 1 : -1];
+int a2[is_same<make_function_type<int, float>::type, int(float)>::value? 1 : -1];
+int a3[is_same<make_function_type<int, float, double>::type, int(float, double const)>::value? 1 : -1];
Index: g++.dg/template/variadic31.C
===================================================================
--- g++.dg/template/variadic31.C (revision 0)
+++ g++.dg/template/variadic31.C (revision 0)
@@ -0,0 +1,11 @@
+// { dg-options "-std=c++0x" }
+template<typename... T>
+void eat(T...) { }
+
+void f()
+{
+ eat();
+ eat(1);
+ eat(1, 2);
+ eat(17, 3.14159, "Hello, World!");
+}
Index: g++.dg/template/variadic14.C
===================================================================
--- g++.dg/template/variadic14.C (revision 0)
+++ g++.dg/template/variadic14.C (revision 0)
@@ -0,0 +1,21 @@
+// { dg-options "-std=c++0x" }
+template<typename R, typename... ArgTypes>
+struct make_function_type
+{
+ typedef R type(ArgTypes...);
+};
+
+template<typename T, typename U>
+struct is_same {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T> {
+ static const bool value = true;
+};
+
+int a0[is_same<make_function_type<int>::type, int()>::value? 1 : -1];
+int a1[is_same<make_function_type<int, float>::type, int(float)>::value? 1 : -1];
+int a2[is_same<make_function_type<int, float>::type, int(float)>::value? 1 : -1];
+int a3[is_same<make_function_type<int, float, double>::type, int(float, double)>::value? 1 : -1];
Index: g++.dg/template/variadic40.C
===================================================================
--- g++.dg/template/variadic40.C (revision 0)
+++ g++.dg/template/variadic40.C (revision 0)
@@ -0,0 +1,3 @@
+// { dg-options "-std=c++0x" }
+template<typename... Values, typename T>
+struct backward_tuple {}; // { dg-error "end" }
Index: g++.dg/template/variadic23.C
===================================================================
--- g++.dg/template/variadic23.C (revision 0)
+++ g++.dg/template/variadic23.C (revision 0)
@@ -0,0 +1,25 @@
+// { dg-options "-std=c++0x" }
+template<typename T, int... Dims>
+struct array {
+ static const int value = 0;
+};
+
+template<>
+struct array<int, 17> {
+ static const int value = 1;
+};
+
+template<int... Dims>
+struct array<float, 1, Dims...> {
+ static const int value = 2;
+};
+
+template<typename T, int... Dims>
+struct array<T, 1, Dims...> {
+ static const int value = 3;
+};
+
+int a0[array<int>::value == 0? 1 : -1];
+int a1[array<int, 17>::value == 1? 1 : -1];
+int a2[array<float, 1, 2, 3>::value == 2? 1 : -1];
+int a3[array<double, 1, 2, 3>::value == 3? 1 : -1];
Index: g++.dg/template/variadic32.C
===================================================================
--- g++.dg/template/variadic32.C (revision 0)
+++ g++.dg/template/variadic32.C (revision 0)
@@ -0,0 +1,11 @@
+// { dg-options "-std=c++0x" }
+template<typename... T>
+void eat(const T&...) { }
+
+void f()
+{
+ eat();
+ eat(1);
+ eat(1, 2);
+ eat(17, 3.14159, "Hello, World!");
+}
Index: g++.dg/template/variadic15.C
===================================================================
--- g++.dg/template/variadic15.C (revision 0)
+++ g++.dg/template/variadic15.C (revision 0)
@@ -0,0 +1,21 @@
+// { dg-options "-std=c++0x" }
+template<typename R, typename... ArgTypes>
+struct make_function_type
+{
+ typedef R type(const ArgTypes&...);
+};
+
+template<typename T, typename U>
+struct is_same {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T> {
+ static const bool value = true;
+};
+
+int a0[is_same<make_function_type<int>::type, int()>::value? 1 : -1];
+int a1[is_same<make_function_type<int, float>::type, int(const float&)>::value? 1 : -1];
+int a2[is_same<make_function_type<int, float>::type, int(const float&)>::value? 1 : -1];
+int a3[is_same<make_function_type<int, float, double>::type, int(const float&, double const&)>::value? 1 : -1];
Index: g++.dg/template/variadic1.C
===================================================================
--- g++.dg/template/variadic1.C (revision 0)
+++ g++.dg/template/variadic1.C (revision 0)
@@ -0,0 +1,10 @@
+// { dg-options "-std=c++0x" }
+template<typename...>
+class tuple;
+
+template<typename... Args>
+class tuple { };
+
+template<typename T1, class... Args>
+class tuple1p { };
+
Index: g++.dg/template/variadic41.C
===================================================================
--- g++.dg/template/variadic41.C (revision 0)
+++ g++.dg/template/variadic41.C (revision 0)
@@ -0,0 +1,3 @@
+// { dg-options "-std=c++0x" }
+template<typename... Args>
+void f(const Args&... args, int oops); // { dg-error "end" }
Index: g++.dg/template/variadic24.C
===================================================================
--- g++.dg/template/variadic24.C (revision 0)
+++ g++.dg/template/variadic24.C (revision 0)
@@ -0,0 +1,6 @@
+// { dg-options "-std=c++0x" }
+template<typename T, T... Values>
+struct vector_c { };
+
+vector_c<int, 17, 42> intvec;
+vector_c<char, 'a', 'b', 'c'> charvec;
Index: g++.dg/template/variadic50.C
===================================================================
--- g++.dg/template/variadic50.C (revision 0)
+++ g++.dg/template/variadic50.C (revision 0)
@@ -0,0 +1,9 @@
+// { dg-options "-std=c++0x" }
+int& f(int, double, ...);
+
+template<typename... Args>
+float& f(Args...);
+
+float& g() {
+ return f(17, 3.14159, 3);
+}
Index: g++.dg/template/variadic33.C
===================================================================
--- g++.dg/template/variadic33.C (revision 0)
+++ g++.dg/template/variadic33.C (revision 0)
@@ -0,0 +1,16 @@
+// { dg-options "-std=c++0x" }
+void print_all() {}
+
+template<typename T, typename... Rest>
+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: g++.dg/template/variadic16.C
===================================================================
--- g++.dg/template/variadic16.C (revision 0)
+++ g++.dg/template/variadic16.C (revision 0)
@@ -0,0 +1,21 @@
+// { dg-options "-std=c++0x" }
+template<typename R, typename... ArgTypes>
+struct make_function_type
+{
+ typedef R type(const ArgTypes&... args);
+};
+
+template<typename T, typename U>
+struct is_same {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T> {
+ static const bool value = true;
+};
+
+int a0[is_same<make_function_type<int>::type, int()>::value? 1 : -1];
+int a1[is_same<make_function_type<int, float>::type, int(const float&)>::value? 1 : -1];
+int a2[is_same<make_function_type<int, float>::type, int(const float&)>::value? 1 : -1];
+int a3[is_same<make_function_type<int, float, double>::type, int(const float&, double const&)>::value? 1 : -1];
Index: g++.dg/template/variadic2.C
===================================================================
--- g++.dg/template/variadic2.C (revision 0)
+++ g++.dg/template/variadic2.C (revision 0)
@@ -0,0 +1,17 @@
+// { dg-options "-std=c++0x" }
+template<typename... Args = int> // { dg-error "default argument" }
+class tuple2;
+
+template<typename... = int> // { dg-error "default argument" }
+class tuple3;
+
+template<typename T1, typename T2, typename... Rest>
+struct two_or_more {}; // { dg-error "provided for" }
+
+typedef two_or_more<int> bad; // { dg-error "2 or more" }
+// { dg-error "invalid type" "" { target *-*-* } 11 }
+
+void f()
+{
+ two_or_more<int, float> z = 5; // { dg-error "two_or_more<int, float>" }
+}
Index: g++.dg/template/variadic42.C
===================================================================
--- g++.dg/template/variadic42.C (revision 0)
+++ g++.dg/template/variadic42.C (revision 0)
@@ -0,0 +1,12 @@
+// { dg-options "-std=c++0x" }
+// { dg-do compile }
+template<typename... Args>
+void f(Args...) { }
+
+void g()
+{
+ f<int*, float*, double*>(0, 0, 0);
+ f<int*>(0,0,0);
+}
+// { dg-final { scan-assembler "_Z1fIPiPfPdEvU10__variadicT_" } }
+// { dg-final { scan-assembler "_Z1fIPiiiEvU10__variadicT_" } }
Index: g++.dg/template/variadic25.C
===================================================================
--- g++.dg/template/variadic25.C (revision 0)
+++ g++.dg/template/variadic25.C (revision 0)
@@ -0,0 +1,16 @@
+// { dg-options "-std=c++0x" }
+template<int... Values>
+struct sum;
+
+template<>
+struct sum<> {
+ static const int value = 0;
+};
+
+template<int Value, int... Values>
+struct sum<Value, Values...> {
+ static const int value = Value + sum<Values...>::value;
+};
+
+int a0[sum<>::value == 0? 1 : -1];
+int a1[sum<1, 2, 3, 4, 5>::value == 15? 1 : -1];
Index: g++.dg/template/variadic51.C
===================================================================
--- g++.dg/template/variadic51.C (revision 0)
+++ g++.dg/template/variadic51.C (revision 0)
@@ -0,0 +1,10 @@
+// { dg-options "-std=c++0x" }
+template<typename T1, typename T2>
+float& f(T1, T2);
+
+template<typename... Args>
+int& f(Args...);
+
+float& g() {
+ return f(17, 3.14159);
+}
Index: g++.dg/template/variadic34.C
===================================================================
--- g++.dg/template/variadic34.C (revision 0)
+++ g++.dg/template/variadic34.C (revision 0)
@@ -0,0 +1,11 @@
+// { dg-options "-std=c++0x" }
+template<int I, typename... Args>
+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: g++.dg/template/variadic17.C
===================================================================
--- g++.dg/template/variadic17.C (revision 0)
+++ g++.dg/template/variadic17.C (revision 0)
@@ -0,0 +1,21 @@
+// { dg-options "-std=c++0x" }
+template<typename R, typename... ArgTypes>
+struct make_function_type
+{
+ typedef R type(const ArgTypes&......);
+};
+
+template<typename T, typename U>
+struct is_same {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T> {
+ static const bool value = true;
+};
+
+int a0[is_same<make_function_type<int>::type, int(...)>::value? 1 : -1];
+int a1[is_same<make_function_type<int, float>::type, int(const float&...)>::value? 1 : -1];
+int a2[is_same<make_function_type<int, float>::type, int(const float&,...)>::value? 1 : -1];
+int a3[is_same<make_function_type<int, float, double>::type, int(const float&, double const&...)>::value? 1 : -1];
Index: g++.dg/template/variadic3.C
===================================================================
--- g++.dg/template/variadic3.C (revision 0)
+++ g++.dg/template/variadic3.C (revision 0)
@@ -0,0 +1,10 @@
+// { dg-options "-std=c++0x" }
+template<typename... Args>
+class tuple {};
+
+void f()
+{
+ tuple<> x;
+ tuple<int> y;
+ tuple<int, float> z;
+}
Index: g++.dg/template/variadic60.C
===================================================================
--- g++.dg/template/variadic60.C (revision 0)
+++ g++.dg/template/variadic60.C (revision 0)
@@ -0,0 +1 @@
+template<typename... Args> class tuple; // { dg-warning "variadic templates" }
Index: g++.dg/template/variadic43.C
===================================================================
--- g++.dg/template/variadic43.C (revision 0)
+++ g++.dg/template/variadic43.C (revision 0)
@@ -0,0 +1,8 @@
+// { dg-options "-std=c++0x" }
+template<typename... Args>
+int f(const Args&...);
+
+void g()
+{
+ int (*fp)(const int&, const float&) = &f;
+}
Index: g++.dg/template/variadic26.C
===================================================================
--- g++.dg/template/variadic26.C (revision 0)
+++ g++.dg/template/variadic26.C (revision 0)
@@ -0,0 +1,24 @@
+// { dg-options "-std=c++0x" }
+template<template<int, int> class Meta, int Initial, int... Values>
+struct accumulate {
+ static const int value = Initial;
+};
+
+template<template<int, int> class Meta, int Initial, int Value, int... Rest>
+struct accumulate<Meta, Initial, Value, Rest...> {
+ static const int value =
+ Meta<Value, accumulate<Meta, Initial, Rest...>::value>::value;
+};
+
+template<int X, int Y>
+struct sum {
+ static const int value = X + Y;
+};
+
+template<int X, int Y>
+struct prod {
+ static const int value = X * Y;
+};
+
+int a0[accumulate<sum,0,1,2,3,4,5>::value == 15? 1 : -1];
+int a1[accumulate<prod,1,1,2,3,4,5>::value == 120? 1 : -1];
Index: g++.dg/template/variadic-bind.C
===================================================================
--- g++.dg/template/variadic-bind.C (revision 0)
+++ g++.dg/template/variadic-bind.C (revision 0)
@@ -0,0 +1,476 @@
+// { dg-options "-std=c++0x" }
+// { dg-do "run" }
+// A basic implementation of TR1's bind using variadic teplates
+// Contributed by Douglas Gregor <doug.gregor@gmail.com>
+#include <cassert>
+
+// Trivial reference_wrapper
+template<typename T>
+struct reference_wrapper
+{
+ reference_wrapper(T& x) : ptr(&x) { }
+
+ operator T&() const { return *ptr; }
+
+ T& get() const { return *ptr; }
+
+ T* ptr;
+};
+
+template<typename T> reference_wrapper<T> ref(T& x) { return x; }
+template<typename T> reference_wrapper<const T> cref(const T& x) { return x; }
+
+// Simple type-traits we'll need
+template<typename T>
+struct add_reference
+{
+ typedef T& type;
+};
+
+template<typename T>
+struct add_reference<T&>
+{
+ typedef T& type;
+};
+
+template<typename T, typename U>
+struct is_same
+{
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T>
+{
+ static const bool value = true;
+};
+
+// For creating the constructor parameters of tuple<>
+template<typename T>
+struct add_const_reference
+{
+ typedef const T& type;
+};
+
+template<typename T>
+struct add_const_reference<T&>
+{
+ typedef T& type;
+};
+
+// 6.1.3 Class template tuple: Needed for bind() implementation
+template<typename... Values>
+class tuple;
+
+template<> class tuple<> { };
+
+template<typename Head, typename... Tail>
+class tuple<Head, Tail...>
+ : private tuple<Tail...>
+{
+ typedef tuple<Tail...> inherited;
+
+ public:
+ tuple() { }
+
+ // implicit copy-constructor is okay
+
+ tuple(typename add_const_reference<Head>::type v,
+ typename add_const_reference<Tail>::type... vtail)
+ : m_head(v), inherited(vtail...) { }
+
+ template<typename... VValues>
+ tuple(const tuple<VValues...>& other)
+ : m_head(other.head()), inherited(other.tail()) { }
+
+ template<typename... VValues>
+ tuple& operator=(const tuple<VValues...>& other)
+ {
+ m_head = other.head();
+ tail() = other.tail();
+ return *this;
+ }
+
+ typename add_reference<Head>::type head() { return m_head; }
+ typename add_reference<const Head>::type head() const { return m_head; }
+ inherited& tail() { return *this; }
+ const inherited& tail() const { return *this; }
+
+ protected:
+ Head m_head;
+};
+
+template<typename T>
+struct make_tuple_result
+{
+ typedef T type;
+};
+
+template<typename T>
+struct make_tuple_result<reference_wrapper<T> >
+{
+ typedef T& type;
+};
+
+// 6.1.3.2 Tuple creation functions
+struct ignore_t {
+ template<typename T> ignore_t& operator=(const T&) { return *this; }
+} ignore;
+
+template<typename... Values>
+tuple<typename make_tuple_result<Values>::type...>
+make_tuple(const Values&... values)
+{
+ return tuple<typename make_tuple_result<Values>::type...>(values...);
+}
+
+template<typename... Values>
+tuple<Values&...> tie(Values&... values)
+{
+ return tuple<Values&...>(values...);
+}
+
+// 6.1.3.3 Tuple helper classes
+template<typename Tuple>
+struct tuple_size;
+
+template<>
+struct tuple_size<tuple<> >
+{
+ static const __SIZE_TYPE__ value = 0;
+};
+
+template<typename Head, typename... Tail>
+struct tuple_size<tuple<Head, Tail...> >
+{
+ static const __SIZE_TYPE__ value = 1 + tuple_size<tuple<Tail...> >::value;
+};
+
+template<int I, typename Tuple>
+struct tuple_element;
+
+template<int I, typename Head, typename... Tail>
+struct tuple_element<I, tuple<Head, Tail...> >
+{
+ typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
+};
+
+template<typename Head, typename... Tail>
+struct tuple_element<0, tuple<Head, Tail...> >
+{
+ typedef Head type;
+};
+
+// 6.1.3.4 Element access
+template<int I, typename Tuple>
+class get_impl;
+
+template<int I, typename Head, typename... Values>
+class get_impl<I, tuple<Head, Values...> >
+{
+ typedef typename tuple_element<I-1, tuple<Values...> >::type Element;
+ typedef typename add_reference<Element>::type RJ;
+ typedef typename add_const_reference<Element>::type PJ;
+ typedef get_impl<I-1, tuple<Values...> > Next;
+
+ public:
+ static RJ get(tuple<Head, Values...>& t)
+ { return Next::get(t.tail()); }
+
+ static PJ get(const tuple<Head, Values...>& t)
+ { return Next::get(t.tail()); }
+};
+
+template<typename Head, typename... Values>
+class get_impl<0, tuple<Head, Values...> >
+{
+ typedef typename add_reference<Head>::type RJ;
+ typedef typename add_const_reference<Head>::type PJ;
+
+ public:
+ static RJ get(tuple<Head, Values...>& t) { return t.head(); }
+ static PJ get(const tuple<Head, Values...>& t) { return t.head(); }
+};
+
+template<int I, typename... Values>
+typename add_reference<
+ typename tuple_element<I, tuple<Values...> >::type
+ >::type
+get(tuple<Values...>& t)
+{
+ return get_impl<I, tuple<Values...> >::get(t);
+}
+
+template<int I, typename... Values>
+typename add_const_reference<
+ typename tuple_element<I, tuple<Values...> >::type
+ >::type
+get(const tuple<Values...>& t)
+{
+ return get_impl<I, tuple<Values...> >::get(t);
+}
+
+// 6.1.3.5 Relational operators
+inline bool operator==(const tuple<>&, const tuple<>&) { return true; }
+
+template<typename T, typename... TTail, typename U, typename... UTail>
+bool operator==(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u)
+{
+ return t.head() == u.head() && t.tail() == u.tail();
+}
+
+template<typename... TValues, typename... UValues>
+bool operator!=(const tuple<TValues...>& t, const tuple<UValues...>& u)
+{
+ return !(t == u);
+}
+
+inline bool operator<(const tuple<>&, const tuple<>&) { return false; }
+
+template<typename T, typename... TTail, typename U, typename... UTail>
+bool operator<(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u)
+{
+ return (t.head() < u.head() ||
+ (!(t.head() < u.head()) && t.tail() < u.tail()));
+}
+
+template<typename... TValues, typename... UValues>
+bool operator>(const tuple<TValues...>& t, const tuple<UValues...>& u)
+{
+ return u < t;
+}
+
+template<typename... TValues, typename... UValues>
+bool operator<=(const tuple<TValues...>& t, const tuple<UValues...>& u)
+{
+ return !(u < t);
+}
+
+template<typename... TValues, typename... UValues>
+bool operator>=(const tuple<TValues...>& t, const tuple<UValues...>& u)
+{
+ return !(t < u);
+}
+
+// enable_if, the breakfast of champions
+template<bool Cond, typename Type = void>
+struct enable_if {
+ typedef Type type;
+};
+
+template<typename Type>
+struct enable_if<false, Type> { };
+
+// 3.6 Function object binders
+
+// 3.6.1 Class template is_bind_expression
+template<typename T>
+struct is_bind_expression {
+ static const bool value = false;
+};
+
+// 3.6.2 Class template is_placeholder
+template<typename T>
+struct is_placeholder {
+ static const int value = 0;
+};
+
+// 3.6.3 Function template bind
+template<int I> struct placeholder {} ;
+
+template<int N> struct int_c { };
+
+// A tuple of integer values
+template<int...> struct int_tuple {};
+
+// make_indexes_impl is a helper for make_indexes
+template<int I, typename IntTuple, typename... Types>
+struct make_indexes_impl;
+
+
+template<int I, int... Indexes, typename T, typename... Types>
+struct make_indexes_impl<I, int_tuple<Indexes...>, T, Types...>
+{
+ typedef typename make_indexes_impl<I+1,
+ int_tuple<Indexes..., I>,
+ Types...>::type type;
+};
+
+template<int I, int... Indexes>
+struct make_indexes_impl<I, int_tuple<Indexes...> > {
+ typedef int_tuple<Indexes...> 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<typename... Types>
+struct make_indexes : make_indexes_impl<0, int_tuple<>, Types...> { };
+
+// Get the Ith tuple element, but only if I is in bounds.
+template<int I, typename Tuple, typename = void>
+struct safe_tuple_element{ };
+
+template<int I, typename... Values>
+struct safe_tuple_element<I, tuple<Values...>,
+ typename enable_if<(I >= 0 &&
+ I < tuple_size<tuple<Values...> >::value)
+ >::type>
+{
+ typedef typename tuple_element<I, tuple<Values...> >::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<typename T, typename... Args>
+inline T& mu(reference_wrapper<T>& bound_arg, const tuple<Args&...>&)
+{
+ return bound_arg.get();
+}
+
+// Unwrap a tuple into separate arguments and forward to the function
+// object f.
+template<typename F, int... Indexes, typename... Args>
+inline typename F::result_type
+unwrap_and_forward(F& f, int_tuple<Indexes...>, const tuple<Args&...>& args)
+{
+ return f(get<Indexes>(args)...);
+}
+
+// Evaluate the inner bind expression
+template<typename Bound, typename... Args>
+inline typename enable_if<is_bind_expression<Bound>::value,
+ typename Bound::result_type>::type
+mu(Bound& bound_arg, const tuple<Args&...>& args)
+{
+ typedef typename make_indexes<Args...>::type Indexes;
+ return unwrap_and_forward(bound_arg, Indexes(), args);
+}
+
+// Retrieve the Ith argument from args
+template<typename Bound, typename... Args>
+inline typename safe_tuple_element<is_placeholder<Bound>::value - 1,
+ tuple<Args...> >::type
+mu(Bound& bound_arg, const tuple<Args&...>& args)
+{
+ return get<is_placeholder<Bound>::value-1>(args);
+}
+
+// Return the stored value.
+template<typename T>
+struct is_reference_wrapper {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_reference_wrapper<reference_wrapper<T> > {
+ static const bool value = true;
+};
+
+template<typename Bound, typename... Args>
+inline typename enable_if<(!is_bind_expression<Bound>::value
+ && !is_placeholder<Bound>::value
+ && !is_reference_wrapper<Bound>::value),
+ Bound&>::type
+mu(Bound& bound_arg, const tuple<Args&...>&)
+{
+ return bound_arg;
+}
+
+//
+template<typename F, typename... BoundArgs, int... Indexes, typename... Args>
+typename F::result_type
+apply_functor(F& f, tuple<BoundArgs...>& bound_args, int_tuple<Indexes...>,
+ const tuple<Args&...>& args)
+{
+ return f(mu(get<Indexes>(bound_args), args)...);
+}
+
+template<typename F, typename... BoundArgs>
+class bound_functor
+{
+ typedef typename make_indexes<BoundArgs...>::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... Args>
+ typename F::result_type operator()(Args&... args) {
+ return apply_functor(f, bound_args, indexes(), tie(args...));
+ }
+
+ private:
+ F f;
+ tuple<BoundArgs...> bound_args;
+};
+
+template<typename F, typename... BoundArgs>
+struct is_bind_expression<bound_functor<F, BoundArgs...> > {
+ static const bool value = true;
+};
+
+template<typename F, typename... BoundArgs>
+inline bound_functor<F, BoundArgs...>
+bind(const F& f, const BoundArgs&... bound_args)
+{
+ return bound_functor<F, BoundArgs...>(f, bound_args...);
+}
+
+
+// 3.6.4 Placeholders
+template<int I>
+struct is_placeholder<placeholder<I> > {
+ 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<typename T>
+struct plus {
+ typedef T result_type;
+
+ T operator()(T x, T y) { return x + y; }
+};
+
+template<typename T>
+struct multiplies {
+ typedef T result_type;
+
+ T operator()(T x, T y) { return x * y; }
+};
+
+template<typename T>
+struct negate {
+ typedef T result_type;
+
+ T operator()(T x) { return -x; }
+};
+
+int main()
+{
+ int seventeen = 17;
+ int forty_two = 42;
+
+ assert(bind(plus<int>(), _1, _2)(seventeen, forty_two) == 59);
+ assert(bind(plus<int>(), _1, _1)(seventeen, forty_two) == 34);
+ assert(bind(plus<int>(), _2, _1)(seventeen, forty_two) == 59);
+ assert(bind(plus<int>(), 5, _1)(seventeen, forty_two) == 22);
+ assert(bind(plus<int>(), ref(seventeen), _2)(seventeen, forty_two) == 59);
+ assert(bind(plus<int>(), bind(multiplies<int>(), 3, _1), _2)(seventeen, forty_two)
+ == 93);
+ return 0;
+}
Index: g++.dg/template/variadic52.C
===================================================================
--- g++.dg/template/variadic52.C (revision 0)
+++ g++.dg/template/variadic52.C (revision 0)
@@ -0,0 +1,7 @@
+// { dg-options "-std=c++0x" }
+template<typename T, T... Values>
+struct vector_c { };
+
+vector_c<int, 1, 2, 3> v1;
+vector_c<char, 'a', 'b', 'c'> v2;
+vector_c<long, 1u, 2, 3l> v3;
Index: g++.dg/template/variadic35.C
===================================================================
--- g++.dg/template/variadic35.C (revision 0)
+++ g++.dg/template/variadic35.C (revision 0)
@@ -0,0 +1,9 @@
+// { dg-options "-std=c++0x" }
+template<int I, typename... Args>
+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: g++.dg/template/variadic18.C
===================================================================
--- g++.dg/template/variadic18.C (revision 0)
+++ g++.dg/template/variadic18.C (revision 0)
@@ -0,0 +1,47 @@
+// { dg-options "-std=c++0x" }
+template<typename...> class tuple { };
+
+template<typename T, template<typename T> class... Metafunctions>
+struct apply_all
+{
+ typedef tuple<typename Metafunctions<T>::type...> type;
+};
+
+template<typename T, typename U>
+struct is_same {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T> {
+ static const bool value = true;
+};
+
+template<typename T>
+struct add_pointer {
+ typedef T* type;
+};
+
+template<typename T>
+struct add_pointer<T&>
+{
+ typedef T& type;
+};
+
+template<typename T>
+struct add_reference {
+ typedef T& type;
+};
+
+template<typename T>
+struct add_reference<T&>
+{
+ typedef T& type;
+};
+
+int a0[is_same<apply_all<int>::type,tuple<> >::value? 1 : -1];
+int a1[is_same<apply_all<int, add_pointer>::type,tuple<int*> >::value? 1 : -1];
+int a2[is_same<apply_all<int, add_pointer, add_reference>::type,tuple<int*, int&> >::value? 1 : -1];
+int a3[is_same<apply_all<int&, add_pointer, add_reference>::type,tuple<int&, int&> >::value? 1 : -1];
+
+
Index: g++.dg/template/variadic4.C
===================================================================
--- g++.dg/template/variadic4.C (revision 0)
+++ g++.dg/template/variadic4.C (revision 0)
@@ -0,0 +1,15 @@
+// { dg-options "-std=c++0x" }
+// { dg-do compile }
+template<typename... Args>
+class tuple {};
+
+void f_none(tuple<>) {}
+void f_one(tuple<int>) {}
+void f_two(tuple<int, float>) {}
+void f_nested(tuple<int, tuple<double, char>, 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: g++.dg/template/variadic61.C
===================================================================
--- g++.dg/template/variadic61.C (revision 0)
+++ g++.dg/template/variadic61.C (revision 0)
@@ -0,0 +1,2 @@
+// { dg-options "-pedantic" }
+template<typename... Args> class tuple; // { dg-warning "variadic templates" }
Index: g++.dg/template/variadic44.C
===================================================================
--- g++.dg/template/variadic44.C (revision 0)
+++ g++.dg/template/variadic44.C (revision 0)
@@ -0,0 +1,13 @@
+// { dg-options "-std=c++0x" }
+// { dg-do compile }
+template<typename... Args>
+int f(const Args&...);
+
+template<typename T> void g(T) { }
+
+void h()
+{
+ g(&f<int, float>);
+}
+
+// { dg-final { scan-assembler "_Z1gIPFiRKiRKfEEvT_"} }
Index: g++.dg/template/variadic27.C
===================================================================
--- g++.dg/template/variadic27.C (revision 0)
+++ g++.dg/template/variadic27.C (revision 0)
@@ -0,0 +1,22 @@
+// { dg-options "-std=c++0x" }
+template<typename Signature>
+struct function_traits;
+
+template<typename R, typename... ArgTypes>
+struct function_traits<R(ArgTypes...)> {
+ typedef R result_type;
+};
+
+template<typename T, typename U>
+struct same_type {
+ static const bool value = false;
+};
+
+template<typename T>
+struct same_type<T, T> {
+ static const bool value = true;
+};
+
+int a0[same_type<function_traits<int()>::result_type, int>::value? 1 : -1];
+int a1[same_type<function_traits<int(float)>::result_type, int>::value? 1 : -1];
+int a2[same_type<function_traits<int(double, char)>::result_type, int>::value? 1 : -1];
Index: g++.dg/template/variadic70.C
===================================================================
--- g++.dg/template/variadic70.C (revision 0)
+++ g++.dg/template/variadic70.C (revision 0)
@@ -0,0 +1,22 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+template <typename T, T... Args> struct bomb;
+
+template <typename T>
+struct bomb<T> {
+ static const T value = 0;
+};
+
+template <typename T, T v, T... Args>
+struct bomb<T, v, Args...> {
+ static const T value = v + bomb<T, Args...>::value;
+};
+
+extern "C" void abort();
+
+int main() {
+ bomb<int, 1, 2, 3, 4> b;
+ if (b.value != 10)
+ abort();
+ return 0;
+}
Index: g++.dg/template/variadic53.C
===================================================================
--- g++.dg/template/variadic53.C (revision 0)
+++ g++.dg/template/variadic53.C (revision 0)
@@ -0,0 +1,17 @@
+// { dg-options "-std=c++0x" }
+template<typename F, typename... BoundArgs>
+class bound_functor
+{
+ public:
+ typedef typename F::result_type result_type;
+
+ template<typename... Args>
+ typename F::result_type operator()(Args&... args);
+};
+
+template<typename F, typename... BoundArgs>
+template<typename... Args>
+typename F::result_type
+bound_functor<F, BoundArgs...>::operator()(Args&... args)
+{
+}
Index: g++.dg/template/variadic36.C
===================================================================
--- g++.dg/template/variadic36.C (revision 0)
+++ g++.dg/template/variadic36.C (revision 0)
@@ -0,0 +1,15 @@
+// { dg-options "-std=c++0x" }
+template<typename T, typename... Args>
+void f(const T&, const Args&... args)
+{
+ f(args); // { dg-error "packs not unpacked" }
+}
+
+template<typename... Values>
+struct tuple_base { };
+
+template<typename... Values>
+struct tuple : tuple_base<Values> { }; // { dg-error "packs not unpacked" }
+
+// { dg-error "args" "" { target *-*-* } 5 }
+// { dg-error "Values" "" { target *-*-* } 12 }
Index: g++.dg/template/variadic19.C
===================================================================
--- g++.dg/template/variadic19.C (revision 0)
+++ g++.dg/template/variadic19.C (revision 0)
@@ -0,0 +1,19 @@
+// { dg-options "-std=c++0x" }
+template<typename... Args>
+struct tuple {
+ static const int value = 0;
+};
+
+template<typename T, template<class T> class... Metafunctions>
+struct tuple<Metafunctions<T>...> {
+ static const int value = 1;
+};
+
+template<typename T> struct add_pointer;
+template<typename T> struct add_reference;
+
+int a0[tuple<int, float>::value == 0? 1 : -1];
+int a1[tuple<add_pointer<int>, add_pointer<float> >::value == 0? 1 : -1];
+int a2[tuple<>::value == 0? 1 : -1];
+int a3[tuple<add_pointer<int> >::value == 1? 1 : -1];
+int a4[tuple<add_pointer<int>, add_reference<int> >::value == 1? 1 : -1];
Index: g++.dg/template/variadic5.C
===================================================================
--- g++.dg/template/variadic5.C (revision 0)
+++ g++.dg/template/variadic5.C (revision 0)
@@ -0,0 +1,38 @@
+// { dg-options "-std=c++0x" }
+template<typename... Args>
+struct tuple {
+ static const int value = 0;
+};
+
+template<>
+struct tuple<> {
+ static const int value = 1;
+};
+
+template<>
+struct tuple<int> {
+ static const int value = 2;
+};
+
+
+template<>
+struct tuple<int, float> {
+ static const int value = 3;
+};
+
+template<typename T>
+struct tuple<T, T> {
+ static const int value = 4;
+};
+
+template<>
+struct tuple<float, float> {
+ static const int value = 5;
+};
+
+int a0[tuple<float>::value == 0? 1 : -1];
+int a1[tuple<>::value == 1? 1 : -1];
+int a2[tuple<int>::value == 2? 1 : -1];
+int a3[tuple<int, float>::value == 3? 1 : -1];
+int a4[tuple<int, int>::value == 4? 1 : -1];
+int a5[tuple<float, float>::value == 5? 1 : -1];
Index: g++.dg/template/variadic-tuple.C
===================================================================
--- g++.dg/template/variadic-tuple.C (revision 0)
+++ g++.dg/template/variadic-tuple.C (revision 0)
@@ -0,0 +1,294 @@
+// { dg-options "-std=c++0x" }
+// { dg-do "run" }
+// An implementation of TR1's <tuple> using variadic teplates
+// Contributed by Douglas Gregor <doug.gregor@gmail.com>
+
+#include <string>
+#include <cassert>
+#include <cstring>
+
+// Trivial reference_wrapper
+template<typename T>
+struct reference_wrapper
+{
+ reference_wrapper(T& x) : ptr(&x) { }
+
+ operator T&() const { return *ptr; }
+
+ T* ptr;
+};
+
+template<typename T> reference_wrapper<T> ref(T& x) { return x; }
+template<typename T> reference_wrapper<const T> cref(const T& x) { return x; }
+
+// Simple type-traits we'll need
+template<typename T>
+struct add_reference
+{
+ typedef T& type;
+};
+
+template<typename T>
+struct add_reference<T&>
+{
+ typedef T& type;
+};
+
+template<typename T, typename U>
+struct is_same
+{
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T>
+{
+ static const bool value = true;
+};
+
+// For creating the constructor parameters of tuple<>
+template<typename T>
+struct add_const_reference
+{
+ typedef const T& type;
+};
+
+template<typename T>
+struct add_const_reference<T&>
+{
+ typedef T& type;
+};
+
+// 6.1.3 Class template tuple
+template<typename... Values>
+class tuple;
+
+template<> class tuple<> { };
+
+template<typename Head, typename... Tail>
+class tuple<Head, Tail...>
+ : private tuple<Tail...>
+{
+ typedef tuple<Tail...> inherited;
+
+ public:
+ tuple() { }
+
+ // implicit copy-constructor is okay
+
+ tuple(typename add_const_reference<Head>::type v,
+ typename add_const_reference<Tail>::type... vtail)
+ : m_head(v), inherited(vtail...) { }
+
+ template<typename... VValues>
+ tuple(const tuple<VValues...>& other)
+ : m_head(other.head()), inherited(other.tail()) { }
+
+ template<typename... VValues>
+ tuple& operator=(const tuple<VValues...>& other)
+ {
+ m_head = other.head();
+ tail() = other.tail();
+ return *this;
+ }
+
+ typename add_reference<Head>::type head() { return m_head; }
+ typename add_reference<const Head>::type head() const { return m_head; }
+ inherited& tail() { return *this; }
+ const inherited& tail() const { return *this; }
+
+ protected:
+ Head m_head;
+};
+
+template<typename T>
+struct make_tuple_result
+{
+ typedef T type;
+};
+
+template<typename T>
+struct make_tuple_result<reference_wrapper<T> >
+{
+ typedef T& type;
+};
+
+// 6.1.3.2 Tuple creation functions
+struct ignore_t {
+ template<typename T> ignore_t& operator=(const T&) { return *this; }
+} ignore;
+
+template<typename... Values>
+tuple<typename make_tuple_result<Values>::type...>
+make_tuple(const Values&... values)
+{
+ return tuple<typename make_tuple_result<Values>::type...>(values...);
+}
+
+template<typename... Values>
+tuple<Values&...> tie(Values&... values)
+{
+ return tuple<Values&...>(values...);
+}
+
+// 6.1.3.3 Tuple helper classes
+template<typename Tuple>
+struct tuple_size;
+
+template<>
+struct tuple_size<tuple<> >
+{
+ static const std::size_t value = 0;
+};
+
+template<typename Head, typename... Tail>
+struct tuple_size<tuple<Head, Tail...> >
+{
+ static const std::size_t value = 1 + tuple_size<tuple<Tail...> >::value;
+};
+
+template<int I, typename Tuple>
+struct tuple_element;
+
+template<int I, typename Head, typename... Tail>
+struct tuple_element<I, tuple<Head, Tail...> >
+{
+ typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
+};
+
+template<typename Head, typename... Tail>
+struct tuple_element<0, tuple<Head, Tail...> >
+{
+ typedef Head type;
+};
+
+// 6.1.3.4 Element access
+template<int I, typename Tuple>
+class get_impl;
+
+template<int I, typename Head, typename... Values>
+class get_impl<I, tuple<Head, Values...> >
+{
+ typedef typename tuple_element<I-1, tuple<Values...> >::type Element;
+ typedef typename add_reference<Element>::type RJ;
+ typedef typename add_const_reference<Element>::type PJ;
+ typedef get_impl<I-1, tuple<Values...> > Next;
+
+ public:
+ static RJ get(tuple<Head, Values...>& t)
+ { return Next::get(t.tail()); }
+
+ static PJ get(const tuple<Head, Values...>& t)
+ { return Next::get(t.tail()); }
+};
+
+template<typename Head, typename... Values>
+class get_impl<0, tuple<Head, Values...> >
+{
+ typedef typename add_reference<Head>::type RJ;
+ typedef typename add_const_reference<Head>::type PJ;
+
+ public:
+ static RJ get(tuple<Head, Values...>& t) { return t.head(); }
+ static PJ get(const tuple<Head, Values...>& t) { return t.head(); }
+};
+
+template<int I, typename... Values>
+typename add_reference<
+ typename tuple_element<I, tuple<Values...> >::type
+ >::type
+get(tuple<Values...>& t)
+{
+ return get_impl<I, tuple<Values...> >::get(t);
+}
+
+template<int I, typename... Values>
+typename add_const_reference<
+ typename tuple_element<I, tuple<Values...> >::type
+ >::type
+get(const tuple<Values...>& t)
+{
+ return get_impl<I, tuple<Values...> >::get(t);
+}
+
+// 6.1.3.5 Relational operators
+inline bool operator==(const tuple<>&, const tuple<>&) { return true; }
+
+template<typename T, typename... TTail, typename U, typename... UTail>
+bool operator==(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u)
+{
+ return t.head() == u.head() && t.tail() == u.tail();
+}
+
+template<typename... TValues, typename... UValues>
+bool operator!=(const tuple<TValues...>& t, const tuple<UValues...>& u)
+{
+ return !(t == u);
+}
+
+inline bool operator<(const tuple<>&, const tuple<>&) { return false; }
+
+template<typename T, typename... TTail, typename U, typename... UTail>
+bool operator<(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u)
+{
+ return (t.head() < u.head() ||
+ (!(t.head() < u.head()) && t.tail() < u.tail()));
+}
+
+template<typename... TValues, typename... UValues>
+bool operator>(const tuple<TValues...>& t, const tuple<UValues...>& u)
+{
+ return u < t;
+}
+
+template<typename... TValues, typename... UValues>
+bool operator<=(const tuple<TValues...>& t, const tuple<UValues...>& u)
+{
+ return !(u < t);
+}
+
+template<typename... TValues, typename... UValues>
+bool operator>=(const tuple<TValues...>& t, const tuple<UValues...>& u)
+{
+ return !(t < u);
+}
+
+int a0[tuple_size<tuple<> >::value == 0? 1 : -1];
+int a1[tuple_size<tuple<int, float, double> >::value == 3? 1 : -1];
+int a2a[is_same<tuple_element<0, tuple<int, float, double> >::type, int>
+ ::value? 1 : -1];
+int a2b[is_same<tuple_element<1, tuple<int, float, double> >::type, float>
+ ::value? 1 : -1];
+int a2c[is_same<tuple_element<2, tuple<int, float, double> >::type, double>
+ ::value? 1 : -1];
+
+int main()
+{
+ tuple<> t0;
+ tuple<int> t1(1);
+ tuple<int, float> t2(1, 3.14159f);
+ tuple<int, float, const char*> t3a(1, 3.14159f, "Hello, world!");
+ tuple<long, double, std::string> t3b(t3a);
+ t3b = t3a;
+ // t3a = t3b; DPG: triggers an error, as it should.
+
+ tuple<int, float, std::string> t3c =
+ make_tuple(17, 2.718281828, std::string("Fun"));
+
+ int seventeen = 17;
+ double pi = 3.14159;
+ tuple<int&, double&> seventeen_pi = make_tuple(ref(seventeen), ref(pi));
+ tuple<int&, const double&> seventeen_pi2 =
+ make_tuple(ref(seventeen), cref(pi));
+ tuple<int&, double&> 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: g++.dg/template/variadic62.C
===================================================================
--- g++.dg/template/variadic62.C (revision 0)
+++ g++.dg/template/variadic62.C (revision 0)
@@ -0,0 +1,2 @@
+// { dg-options "-pedantic-errors" }
+template<typename... Args> class tuple; // { dg-error "variadic templates" }
Index: g++.dg/template/variadic45.C
===================================================================
--- g++.dg/template/variadic45.C (revision 0)
+++ g++.dg/template/variadic45.C (revision 0)
@@ -0,0 +1,10 @@
+// { dg-options "-std=c++0x" }
+template<typename... Args>
+int& f(Args...);
+
+template<typename T1, typename T2>
+float& f(T1, T2);
+
+float& g() {
+ return f(17, 3.14159);
+}
Index: g++.dg/template/variadic28.C
===================================================================
--- g++.dg/template/variadic28.C (revision 0)
+++ g++.dg/template/variadic28.C (revision 0)
@@ -0,0 +1,25 @@
+// { dg-options "-std=c++0x" }
+template<typename Signature>
+struct function_traits;
+
+template<typename R, typename... ArgTypes>
+struct function_traits<R(ArgTypes......)> {
+ typedef R result_type;
+};
+
+template<typename T, typename U>
+struct same_type {
+ static const bool value = false;
+};
+
+template<typename T>
+struct same_type<T, T> {
+ static const bool value = true;
+};
+
+int a0[same_type<function_traits<int(double, char...)>::result_type, int>::value? 1 : -1];
+int a1[same_type<function_traits<int(double, char,...)>::result_type, int>::value? 1 : -1];
+int a2[same_type<function_traits<int(char,...)>::result_type, int>::value? 1 : -1];
+int a3[same_type<function_traits<int(...)>::result_type, int>::value? 1 : -1];
+int a4[same_type<function_traits<int(double x, char...)>::result_type, int>::value? 1 : -1];
+int a5[same_type<function_traits<int(double, char y...)>::result_type, int>::value? 1 : -1];
Index: g++.dg/template/variadic71.C
===================================================================
--- g++.dg/template/variadic71.C (revision 0)
+++ g++.dg/template/variadic71.C (revision 0)
@@ -0,0 +1,12 @@
+// { dg-options "-std=c++0x" }
+template<typename...> struct list {};
+
+template<typename Sequence, typename Head>
+struct push_front;
+
+template<typename... Elements, typename Head>
+struct push_front<list<Elements...>, Head> {
+ typedef list<Head, Elements> type; // { dg-error "parameter packs not unpacked" }
+};
+
+// { dg-error "Elements" "" { target *-*-* } 9 }
Index: g++.dg/template/variadic54.C
===================================================================
--- g++.dg/template/variadic54.C (revision 0)
+++ g++.dg/template/variadic54.C (revision 0)
@@ -0,0 +1,12 @@
+// { dg-options "-std=c++0x" }
+template<typename F, typename... BoundArgs>
+class bound_functor
+{
+ public:
+ bound_functor();
+};
+
+template<typename F, typename... BoundArgs>
+bound_functor<F, BoundArgs...>::bound_functor()
+{
+}
Index: g++.dg/template/variadic37.C
===================================================================
--- g++.dg/template/variadic37.C (revision 0)
+++ g++.dg/template/variadic37.C (revision 0)
@@ -0,0 +1,10 @@
+// { dg-options "-std=c++0x" }
+template<typename... Values>
+struct tuple
+{
+ static const __SIZE_TYPE__ length = sizeof...(Values);
+};
+
+int a0[tuple<>::length == 0? 1 : -1];
+int a1[tuple<int>::length == 1? 1 : -1];
+int a2[tuple<int, float>::length == 2? 1 : -1];
Index: g++.dg/template/variadic6.C
===================================================================
--- g++.dg/template/variadic6.C (revision 0)
+++ g++.dg/template/variadic6.C (revision 0)
@@ -0,0 +1,12 @@
+// { dg-options "-std=c++0x" }
+template<typename ... Args>
+struct tuple_base {};
+
+template<typename ... Args>
+struct tuple : public tuple_base<Args...>
+{
+};
+
+tuple<> zero;
+tuple<int> one;
+tuple<float, int> two;
Index: g++.dg/template/variadic63.C
===================================================================
--- g++.dg/template/variadic63.C (revision 0)
+++ g++.dg/template/variadic63.C (revision 0)
@@ -0,0 +1,2 @@
+// { dg-options "-std=c++0x -pedantic" }
+template<typename... Args> class tuple;
Index: g++.dg/template/variadic46.C
===================================================================
--- g++.dg/template/variadic46.C (revision 0)
+++ g++.dg/template/variadic46.C (revision 0)
@@ -0,0 +1,11 @@
+// { dg-options "-std=c++0x" }
+template<typename... Args>
+int& f(Args&...);
+
+template<typename... Args>
+float& f(const Args&...);
+
+int& g(int x, float y)
+{
+ return f(x, y);
+}
Index: g++.dg/template/variadic29.C
===================================================================
--- g++.dg/template/variadic29.C (revision 0)
+++ g++.dg/template/variadic29.C (revision 0)
@@ -0,0 +1,35 @@
+// { dg-options "-std=c++0x" }
+template<typename Signature>
+struct function_traits;
+
+template<typename R, typename... ArgTypes>
+struct function_traits<R(ArgTypes...)> {
+ typedef R result_type;
+};
+
+template<typename R, typename Class, typename... ArgTypes>
+struct function_traits<R (Class::*)(ArgTypes...)> {
+ typedef R result_type;
+};
+
+template<typename R, typename Class, typename... ArgTypes>
+struct function_traits<R (Class::*)(ArgTypes...) const> {
+ typedef R result_type;
+};
+
+template<typename T, typename U>
+struct same_type {
+ static const bool value = false;
+};
+
+template<typename T>
+struct same_type<T, T> {
+ static const bool value = true;
+};
+
+struct X {};
+
+int a0[same_type<function_traits<int (X::*)()>::result_type, int>::value? 1 : -1];
+int a1[same_type<function_traits<int (X::*)(float)>::result_type, int>::value? 1 : -1];
+int a2[same_type<function_traits<int (X::*)(double, char)>::result_type, int>::value? 1 : -1];
+int a3[same_type<function_traits<int (X::*)(double, char) const>::result_type, int>::value? 1 : -1];
Index: g++.dg/template/variadic72.C
===================================================================
--- g++.dg/template/variadic72.C (revision 0)
+++ g++.dg/template/variadic72.C (revision 0)
@@ -0,0 +1,21 @@
+// { dg-options "-std=c++0x" }
+struct A {};
+struct B {};
+struct C {};
+
+template<typename... Mixins>
+struct mixed_up : public Mixins...
+{
+};
+
+void fA(A);
+void fB(B);
+void fC(C);
+
+void g()
+{
+ mixed_up<A, B, C> m;
+ fA(m);
+ fB(m);
+ fC(m);
+}
Index: g++.dg/template/variadic55.C
===================================================================
--- g++.dg/template/variadic55.C (revision 0)
+++ g++.dg/template/variadic55.C (revision 0)
@@ -0,0 +1,12 @@
+// { dg-options "-std=c++0x" }
+template<typename F, typename... BoundArgs>
+class bound_functor
+{
+ public:
+ bound_functor(const BoundArgs&... bound_args);
+};
+
+template<typename F, typename... BoundArgs>
+bound_functor<F, BoundArgs...>::bound_functor(const BoundArgs&...)
+{
+}
Index: g++.dg/template/variadic38.C
===================================================================
--- g++.dg/template/variadic38.C (revision 0)
+++ g++.dg/template/variadic38.C (revision 0)
@@ -0,0 +1,6 @@
+// { dg-options "-std=c++0x" }
+template<int... Values>
+struct int_vec {};
+
+template<int... Values>
+struct int_vec<0, (Values+1)...> {}; // { dg-error "involves template parameter" }
Index: g++.dg/template/variadic7.C
===================================================================
--- g++.dg/template/variadic7.C (revision 0)
+++ g++.dg/template/variadic7.C (revision 0)
@@ -0,0 +1,33 @@
+// { dg-options "-std=c++0x" }
+template<typename... Args>
+struct tuple_base {
+ static const int value = 0;
+};
+
+template<>
+struct tuple_base<int> {
+ static const int value = 1;
+};
+
+template<>
+struct tuple_base<int, float> {
+ static const int value = 2;
+};
+
+template<>
+struct tuple_base<float, int> {
+ static const int value = 3;
+};
+
+template<typename... Args>
+struct int_tuple : tuple_base<int, Args...> { };
+
+template<typename... Args>
+struct tuple_int : tuple_base<Args..., int> { };
+
+int a0a[int_tuple<int>::value == 0? 1 : -1];
+int a0b[int_tuple<int>::value == 0? 1 : -1];
+int a1a[int_tuple<>::value == 1? 1 : -1];
+int a1b[tuple_int<>::value == 1? 1 : -1];
+int a2[int_tuple<float>::value == 2? 1 : -1];
+int a3[tuple_int<float>::value == 3? 1 : -1];
Index: g++.dg/template/variadic64.C
===================================================================
--- g++.dg/template/variadic64.C (revision 0)
+++ g++.dg/template/variadic64.C (revision 0)
@@ -0,0 +1,19 @@
+// { dg-options "-std=c++0x" }
+template<int... Indexes>
+ struct _Index_tuple { };
+
+template<int _Num, typename _Tuple = _Index_tuple<> >
+struct _Build_index_tuple;
+
+template<int _Num, int... _Indexes>
+struct _Build_index_tuple<_Num, _Index_tuple<_Indexes...> >
+ : _Build_index_tuple<_Num - 1,
+ _Index_tuple<_Indexes..., sizeof...(_Indexes)> >
+{
+};
+
+template<int... _Indexes>
+struct _Build_index_tuple<0, _Index_tuple<_Indexes...> >
+{
+ typedef _Index_tuple<_Indexes...> __type;
+};
Index: g++.dg/template/variadic47.C
===================================================================
--- g++.dg/template/variadic47.C (revision 0)
+++ g++.dg/template/variadic47.C (revision 0)
@@ -0,0 +1,18 @@
+// { dg-options "-std=c++0x" }
+template<typename T> struct wrap { };
+
+template<typename... Args>
+int& f(const Args&...);
+
+template<typename... Args>
+float& f(const wrap<Args>&...);
+
+int& g(int x, float y, double z)
+{
+ return f(x, y, z);
+}
+
+float& h(wrap<int> x, wrap<float> y, wrap<double> z)
+{
+ return f(x, y, z);
+}
Index: g++.dg/template/variadic73.C
===================================================================
--- g++.dg/template/variadic73.C (revision 0)
+++ g++.dg/template/variadic73.C (revision 0)
@@ -0,0 +1,33 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+struct A {};
+struct B {};
+struct C {};
+
+template<typename... Exceptions> 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<A, B, C>(0);
+ abort();
+ } catch (A) {
+ }
+ try {
+ f<A, B, C>(1);
+ abort();
+ } catch (B) {
+ }
+ try {
+ f<A, B, C>(2);
+ abort();
+ } catch (C) {
+ }
+ return 0;
+}
Index: g++.dg/template/variadic56.C
===================================================================
--- g++.dg/template/variadic56.C (revision 0)
+++ g++.dg/template/variadic56.C (revision 0)
@@ -0,0 +1,19 @@
+// { dg-options "-std=c++0x" }
+template<typename... Elements>
+struct tuple { };
+
+template<typename T, typename... Elements>
+struct tuple<T, Elements...> {
+ int foo();
+};
+
+template<typename T, typename... Elements>
+struct tuple<T*, Elements...> {
+ int bar();
+};
+
+template<typename T, typename... Elements>
+int tuple<T, Elements...>::foo() { return 0; }
+
+template<typename T, typename... Elements>
+int tuple<T*, Elements...>::bar() { return 0; }
Index: g++.dg/template/variadic39.C
===================================================================
--- g++.dg/template/variadic39.C (revision 0)
+++ g++.dg/template/variadic39.C (revision 0)
@@ -0,0 +1,13 @@
+// { dg-options "-std=c++0x" }
+template<typename... Args>
+struct tuple {};
+
+template<typename T, typename... Args>
+struct tuple<Args..., T> { }; // { dg-error "end" }
+
+
+template<int... Values>
+struct int_vec { };
+
+template<int I, int... Values>
+struct int_vec<Values..., I> { }; // { dg-error "end" }
Index: g++.dg/template/variadic8.C
===================================================================
--- g++.dg/template/variadic8.C (revision 0)
+++ g++.dg/template/variadic8.C (revision 0)
@@ -0,0 +1,23 @@
+// { dg-options "-std=c++0x" }
+template<typename... Args>
+struct tuple_base {
+ static const int value = 0;
+};
+
+template<>
+struct tuple_base<int*>
+{
+ static const int value = 1;
+};
+
+template<typename T>
+struct tuple_base<T*>
+{
+ static const int value = 2;
+};
+
+template<typename... Args>
+struct tuple_of_pointers : tuple_base<Args*...> { };
+
+int a1[tuple_of_pointers<int>::value == 1? 1 : -1];
+int a2[tuple_of_pointers<float>::value == 2? 1 : -1];
Index: g++.dg/template/variadic65.C
===================================================================
--- g++.dg/template/variadic65.C (revision 0)
+++ g++.dg/template/variadic65.C (revision 0)
@@ -0,0 +1,8 @@
+// { dg-options "-std=c++0x" }
+struct unused;
+template<typename T1 = unused, typename T2 = unused, typename T3 = unused,
+ typename T4 = unused, typename T5 = unused, typename T6 = unused>
+struct tuple {};
+
+template<typename... Args>
+void foo(tuple<Args...>) { } // { dg-error "cannot unpack" }
Index: g++.dg/template/variadic48.C
===================================================================
--- g++.dg/template/variadic48.C (revision 0)
+++ g++.dg/template/variadic48.C (revision 0)
@@ -0,0 +1,10 @@
+// { dg-options "-std=c++0x" }
+template<typename T, typename... Args>
+int& f(const T&, Args...);
+
+template<typename T>
+float& f(const T&);
+
+float& g() {
+ return f(17);
+}
Index: g++.dg/template/variadic-mem_fn.C
===================================================================
--- g++.dg/template/variadic-mem_fn.C (revision 0)
+++ g++.dg/template/variadic-mem_fn.C (revision 0)
@@ -0,0 +1,50 @@
+// { dg-options "-std=c++0x" }
+// { dg-do "run" }
+// A basic implementation of TR1's mem_fn using variadic teplates
+// Contributed by Douglas Gregor <doug.gregor@gmail.com>
+#include <cassert>
+
+template<typename R, typename Class, typename... Args>
+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<typename R, typename Class, typename... Args>
+inline Mem_fn<R, Class, Args...>
+mem_fn(R (Class::* pmf)(Args...))
+{
+ return Mem_fn<R, Class, Args...>(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: g++.dg/template/variadic57.C
===================================================================
--- g++.dg/template/variadic57.C (revision 0)
+++ g++.dg/template/variadic57.C (revision 0)
@@ -0,0 +1,16 @@
+// { dg-options "-std=c++0x" }
+template<typename T, int... Dims>
+struct array {
+ int foo();
+};
+
+template<typename T>
+struct array<T, 0> {
+ int bar();
+};
+
+template<typename T, int... Dims>
+int array<T, Dims...>::foo() { }
+
+template<typename T>
+int array<T, 0>::bar() { }
Index: g++.dg/template/variadic9.C
===================================================================
--- g++.dg/template/variadic9.C (revision 0)
+++ g++.dg/template/variadic9.C (revision 0)
@@ -0,0 +1,38 @@
+// { dg-options "-std=c++0x" }
+template<typename T1, typename T2>
+struct pair {};
+
+template<typename... Args>
+struct tuple {
+ static const int value = 0;
+};
+
+template<>
+struct tuple<pair<int, float> > {
+ static const int value = 1;
+};
+
+template<typename U>
+struct tuple<pair<int, U> > {
+ static const int value = 2;
+};
+
+template<typename T, typename U>
+struct tuple<pair<T, U>, pair<T, U> > {
+ static const int value = 3;
+};
+
+
+template<typename... Outer>
+struct X {
+ template<typename... Inner>
+ struct Y
+ {
+ typedef tuple<pair<Outer, Inner>...> type;
+ };
+};
+
+int a0[X<int, double>::Y<short, char>::type::value == 0? 1 : -1];
+int a1[X<int>::Y<float>::type::value == 1? 1 : -1];
+int a2[X<int>::Y<double>::type::value == 2? 1 : -1];
+int a3[X<int, int>::Y<double, double>::type::value == 3? 1 : -1];
Index: g++.dg/template/variadic66.C
===================================================================
--- g++.dg/template/variadic66.C (revision 0)
+++ g++.dg/template/variadic66.C (revision 0)
@@ -0,0 +1,9 @@
+// { dg-options "-std=c++0x" }
+
+template<typename Result, typename Functor, typename... ArgTypes>
+Result bind(Functor, ArgTypes...) { }
+
+void f()
+{
+ bind<int>(17, 20, 22);
+}
Index: g++.dg/template/variadic49.C
===================================================================
--- g++.dg/template/variadic49.C (revision 0)
+++ g++.dg/template/variadic49.C (revision 0)
@@ -0,0 +1,9 @@
+// { dg-options "-std=c++0x" }
+int& f(...);
+
+template<typename... Args>
+float& f(Args...);
+
+float& g() {
+ return f(17, 3.14159);
+}
Index: g++.dg/template/variadic58.C
===================================================================
--- g++.dg/template/variadic58.C (revision 0)
+++ g++.dg/template/variadic58.C (revision 0)
@@ -0,0 +1,16 @@
+// { dg-options "-std=c++0x" }
+#include <typeinfo>
+
+template<typename... Args>
+void foo(Args...) { }
+
+template<typename... Args>
+void bar(Args... args) {
+ foo(Args()...);
+ foo(args = args...);
+ foo(reinterpret_cast<void*>(&args)...);
+ foo(const_cast<const Args>(args)...);
+ foo(static_cast<void*>(&args)...);
+ foo(dynamic_cast<void*>(&args)...);
+ foo(typeid(Args)...);
+}
Index: g++.dg/template/variadic67.C
===================================================================
--- g++.dg/template/variadic67.C (revision 0)
+++ g++.dg/template/variadic67.C (revision 0)
@@ -0,0 +1,24 @@
+// { dg-options "-std=c++0x" }
+template<typename... Elements> struct tuple {};
+
+template<typename... Args>
+struct nested
+{
+ typedef tuple<tuple<Args, Args...>...> type;
+};
+
+template<typename T, typename U>
+struct is_same
+{
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T>
+{
+ static const bool value = true;
+};
+
+int a0[is_same<nested<int, float>::type,
+ tuple<tuple<int, int, float>,
+ tuple<float, int, float> > >::value? 1 : -1];
Index: g++.dg/template/variadic59.C
===================================================================
--- g++.dg/template/variadic59.C (revision 0)
+++ g++.dg/template/variadic59.C (revision 0)
@@ -0,0 +1,4 @@
+// { dg-options "-std=c++0x" }
+template<class T, typename... VarArgs>
+void print(T t, VarArgs args); // { dg-error "packs not unpacked" }
+// { dg-error "VarArgs" "" { target *-*-* } 3 }
Index: g++.dg/template/variadic68.C
===================================================================
--- g++.dg/template/variadic68.C (revision 0)
+++ g++.dg/template/variadic68.C (revision 0)
@@ -0,0 +1,23 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+extern "C" void abort();
+
+template<typename T, T... Values>
+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<int, 1, 2, 3>(test_arr1, 3);
+
+ return 0;
+}
Index: g++.dg/template/variadic10.C
===================================================================
--- g++.dg/template/variadic10.C (revision 0)
+++ g++.dg/template/variadic10.C (revision 0)
@@ -0,0 +1,22 @@
+// { dg-options "-std=c++0x" }
+template<typename T1, typename T2>
+struct pair {};
+
+template<typename... Args>
+struct tuple {
+ static const int value = 0;
+};
+
+template<>
+struct tuple<pair<int, float> > { };
+
+template<typename... Outer>
+struct X {
+ template<typename... Inner>
+ struct Y
+ {
+ typedef tuple<pair<Outer, Inner>...> type; // { dg-error "mismatched argument pack lengths" }
+ };
+};
+
+X<int, double>::Y<short, char, double>::type honk;