]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/20599 (variadic template support)
authorDouglas Gregor <doug.gregor@gmail.com>
Sat, 10 Mar 2007 02:01:49 +0000 (02:01 +0000)
committerDoug Gregor <dgregor@gcc.gnu.org>
Sat, 10 Mar 2007 02:01:49 +0000 (02:01 +0000)
2007-03-09  Douglas Gregor  <doug.gregor@gmail.com>

PR c++/20599
* g++.dg/cpp0x/variadic-bind.C: New.
* g++.dg/cpp0x/variadic-function.C: New.
* g++.dg/cpp0x/variadic-mem_fn.C: New.
* g++.dg/cpp0x/variadic-tuple.C: New.
* g++.dg/cpp0x/variadic1.C: New.
* g++.dg/cpp0x/variadic2.C: New.
* g++.dg/cpp0x/variadic3.C: New.
* g++.dg/cpp0x/variadic4.C: New.
* g++.dg/cpp0x/variadic5.C: New.
* g++.dg/cpp0x/variadic6.C: New.
* g++.dg/cpp0x/variadic7.C: New.
* g++.dg/cpp0x/variadic8.C: New.
* g++.dg/cpp0x/variadic9.C: New.
* g++.dg/cpp0x/variadic10.C: New.
* g++.dg/cpp0x/variadic11.C: New.
* g++.dg/cpp0x/variadic12.C: New.
* g++.dg/cpp0x/variadic13.C: New.
* g++.dg/cpp0x/variadic14.C: New.
* g++.dg/cpp0x/variadic15.C: New.
* g++.dg/cpp0x/variadic16.C: New.
* g++.dg/cpp0x/variadic17.C: New.
* g++.dg/cpp0x/variadic18.C: New.
* g++.dg/cpp0x/variadic19.C: New.
* g++.dg/cpp0x/variadic20.C: New.
* g++.dg/cpp0x/variadic21.C: New.
* g++.dg/cpp0x/variadic22.C: New.
* g++.dg/cpp0x/variadic23.C: New.
* g++.dg/cpp0x/variadic24.C: New.
* g++.dg/cpp0x/variadic25.C: New.
* g++.dg/cpp0x/variadic26.C: New.
* g++.dg/cpp0x/variadic27.C: New.
* g++.dg/cpp0x/variadic28.C: New.
* g++.dg/cpp0x/variadic29.C: New.
* g++.dg/cpp0x/variadic30.C: New.
* g++.dg/cpp0x/variadic31.C: New.
* g++.dg/cpp0x/variadic32.C: New.
* g++.dg/cpp0x/variadic33.C: New.
* g++.dg/cpp0x/variadic34.C: New.
* g++.dg/cpp0x/variadic35.C: New.
* g++.dg/cpp0x/variadic36.C: New.
* g++.dg/cpp0x/variadic37.C: New.
* g++.dg/cpp0x/variadic38.C: New.
* g++.dg/cpp0x/variadic39.C: New.
* g++.dg/cpp0x/variadic40.C: New.
* g++.dg/cpp0x/variadic41.C: New.
* g++.dg/cpp0x/variadic42.C: New.
* g++.dg/cpp0x/variadic43.C: New.
* g++.dg/cpp0x/variadic44.C: New.
* g++.dg/cpp0x/variadic45.C: New.
* g++.dg/cpp0x/variadic46.C: New.
* g++.dg/cpp0x/variadic47.C: New.
* g++.dg/cpp0x/variadic48.C: New.
* g++.dg/cpp0x/variadic49.C: New.
* g++.dg/cpp0x/variadic50.C: New.
* g++.dg/cpp0x/variadic51.C: New.
* g++.dg/cpp0x/variadic52.C: New.
* g++.dg/cpp0x/variadic53.C: New.
* g++.dg/cpp0x/variadic54.C: New.
* g++.dg/cpp0x/variadic55.C: New.
* g++.dg/cpp0x/variadic56.C: New.
* g++.dg/cpp0x/variadic57.C: New.
* g++.dg/cpp0x/variadic58.C: New.
* g++.dg/cpp0x/variadic59.C: New.
        * g++.dg/cpp0x/variadic60.C : New.
        * g++.dg/cpp0x/variadic61.C : New.
        * g++.dg/cpp0x/variadic62.C : New.
        * g++.dg/cpp0x/variadic63.C : New.
        * g++.dg/cpp0x/variadic64.C : New.
        * g++.dg/cpp0x/variadic65.C : New.
        * g++.dg/cpp0x/variadic66.C : New.
        * g++.dg/cpp0x/variadic67.C : New.
        * g++.dg/cpp0x/variadic68.C : New.
        * g++.dg/cpp0x/variadic69.C : New.
* g++.dg/cpp0x/variadic70.C : New.
* g++.dg/cpp0x/variadic71.C : New.
* g++.dg/cpp0x/variadic72.C : New.
* g++.dg/cpp0x/variadic73.C : New.
* g++.dg/cpp0x/variadic74.C : New.
* g++.dg/cpp0x/variadic75.C : New.
* g++.dg/cpp0x/variadic-ex1.C : New.
* g++.dg/cpp0x/variadic-ex2.C : New.
* g++.dg/cpp0x/variadic-ex3.C : New.
* g++.dg/cpp0x/variadic-ex4.C : New.
* g++.dg/cpp0x/variadic-ex5.C : New.
* g++.dg/cpp0x/variadic-ex6.C : New.
* g++.dg/cpp0x/variadic-ex7.C : New.
* g++.dg/cpp0x/variadic-ex8.C : New.
* g++.dg/cpp0x/variadic-ex9.C : New.
* g++.dg/cpp0x/variadic-ex10.C : New.
* g++.dg/cpp0x/variadic-ex11.C : New.
* g++.dg/cpp0x/variadic-ex12.C : New.
* g++.dg/cpp0x/variadic-ex13.C : New.
* g++.dg/cpp0x/variadic-ex14.C : New.

From-SVN: r122789

94 files changed:
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/variadic-bind.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-ex1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-ex10.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-ex11.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-ex12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-ex13.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-ex5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-ex6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-ex7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-ex8.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-ex9.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-function.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-mem_fn.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic10.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic11.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic13.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic14.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic15.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic16.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic17.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic18.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic19.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic20.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic21.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic22.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic23.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic24.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic25.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic26.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic27.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic28.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic29.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic30.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic31.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic32.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic33.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic34.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic35.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic36.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic37.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic38.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic39.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic40.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic41.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic42.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic43.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic44.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic45.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic46.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic47.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic48.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic49.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic50.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic51.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic52.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic53.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic54.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic55.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic56.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic57.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic58.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic59.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic60.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic61.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic62.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic63.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic64.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic65.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic66.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic67.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic68.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic69.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic70.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic71.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic72.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic73.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic74.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic75.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic8.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic9.C [new file with mode: 0644]

index f9c1c3f72e41425eb19181329fd69dce7e2dd201..d71b94f98101580e71d6a8b457c3c20cbd15330b 100644 (file)
@@ -1,3 +1,100 @@
+2007-03-09  Douglas Gregor  <doug.gregor@gmail.com>
+
+       PR c++/20599
+       * g++.dg/cpp0x/variadic-bind.C: New.
+       * g++.dg/cpp0x/variadic-function.C: New.
+       * g++.dg/cpp0x/variadic-mem_fn.C: New.
+       * g++.dg/cpp0x/variadic-tuple.C: New.
+       * g++.dg/cpp0x/variadic1.C: New.
+       * g++.dg/cpp0x/variadic2.C: New.
+       * g++.dg/cpp0x/variadic3.C: New.
+       * g++.dg/cpp0x/variadic4.C: New.
+       * g++.dg/cpp0x/variadic5.C: New.
+       * g++.dg/cpp0x/variadic6.C: New.
+       * g++.dg/cpp0x/variadic7.C: New.
+       * g++.dg/cpp0x/variadic8.C: New.
+       * g++.dg/cpp0x/variadic9.C: New.
+       * g++.dg/cpp0x/variadic10.C: New.
+       * g++.dg/cpp0x/variadic11.C: New.
+       * g++.dg/cpp0x/variadic12.C: New.
+       * g++.dg/cpp0x/variadic13.C: New.
+       * g++.dg/cpp0x/variadic14.C: New.
+       * g++.dg/cpp0x/variadic15.C: New.
+       * g++.dg/cpp0x/variadic16.C: New.
+       * g++.dg/cpp0x/variadic17.C: New.
+       * g++.dg/cpp0x/variadic18.C: New.
+       * g++.dg/cpp0x/variadic19.C: New.
+       * g++.dg/cpp0x/variadic20.C: New.
+       * g++.dg/cpp0x/variadic21.C: New.
+       * g++.dg/cpp0x/variadic22.C: New.
+       * g++.dg/cpp0x/variadic23.C: New.
+       * g++.dg/cpp0x/variadic24.C: New.
+       * g++.dg/cpp0x/variadic25.C: New.
+       * g++.dg/cpp0x/variadic26.C: New.
+       * g++.dg/cpp0x/variadic27.C: New.
+       * g++.dg/cpp0x/variadic28.C: New.
+       * g++.dg/cpp0x/variadic29.C: New.
+       * g++.dg/cpp0x/variadic30.C: New.
+       * g++.dg/cpp0x/variadic31.C: New.
+       * g++.dg/cpp0x/variadic32.C: New.
+       * g++.dg/cpp0x/variadic33.C: New.
+       * g++.dg/cpp0x/variadic34.C: New.
+       * g++.dg/cpp0x/variadic35.C: New.
+       * g++.dg/cpp0x/variadic36.C: New.
+       * g++.dg/cpp0x/variadic37.C: New.
+       * g++.dg/cpp0x/variadic38.C: New.
+       * g++.dg/cpp0x/variadic39.C: New.
+       * g++.dg/cpp0x/variadic40.C: New.
+       * g++.dg/cpp0x/variadic41.C: New.
+       * g++.dg/cpp0x/variadic42.C: New.
+       * g++.dg/cpp0x/variadic43.C: New.
+       * g++.dg/cpp0x/variadic44.C: New.
+       * g++.dg/cpp0x/variadic45.C: New.
+       * g++.dg/cpp0x/variadic46.C: New.
+       * g++.dg/cpp0x/variadic47.C: New.
+       * g++.dg/cpp0x/variadic48.C: New.
+       * g++.dg/cpp0x/variadic49.C: New.
+       * g++.dg/cpp0x/variadic50.C: New.
+       * g++.dg/cpp0x/variadic51.C: New.
+       * g++.dg/cpp0x/variadic52.C: New.
+       * g++.dg/cpp0x/variadic53.C: New.
+       * g++.dg/cpp0x/variadic54.C: New.
+       * g++.dg/cpp0x/variadic55.C: New.
+       * g++.dg/cpp0x/variadic56.C: New.
+       * g++.dg/cpp0x/variadic57.C: New.
+       * g++.dg/cpp0x/variadic58.C: New.
+       * g++.dg/cpp0x/variadic59.C: New.
+        * g++.dg/cpp0x/variadic60.C : New.
+        * g++.dg/cpp0x/variadic61.C : New.
+        * g++.dg/cpp0x/variadic62.C : New.
+        * g++.dg/cpp0x/variadic63.C : New.
+        * g++.dg/cpp0x/variadic64.C : New.
+        * g++.dg/cpp0x/variadic65.C : New.
+        * g++.dg/cpp0x/variadic66.C : New.
+        * g++.dg/cpp0x/variadic67.C : New.
+        * g++.dg/cpp0x/variadic68.C : New.     
+        * g++.dg/cpp0x/variadic69.C : New.
+       * g++.dg/cpp0x/variadic70.C : New.
+       * g++.dg/cpp0x/variadic71.C : New.
+       * g++.dg/cpp0x/variadic72.C : New.
+       * g++.dg/cpp0x/variadic73.C : New.
+       * g++.dg/cpp0x/variadic74.C : New.
+       * g++.dg/cpp0x/variadic75.C : New.
+       * g++.dg/cpp0x/variadic-ex1.C : New.
+       * g++.dg/cpp0x/variadic-ex2.C : New.
+       * g++.dg/cpp0x/variadic-ex3.C : New.
+       * g++.dg/cpp0x/variadic-ex4.C : New.
+       * g++.dg/cpp0x/variadic-ex5.C : New.
+       * g++.dg/cpp0x/variadic-ex6.C : New.
+       * g++.dg/cpp0x/variadic-ex7.C : New.
+       * g++.dg/cpp0x/variadic-ex8.C : New.
+       * g++.dg/cpp0x/variadic-ex9.C : New.
+       * g++.dg/cpp0x/variadic-ex10.C : New.
+       * g++.dg/cpp0x/variadic-ex11.C : New.
+       * g++.dg/cpp0x/variadic-ex12.C : New.
+       * g++.dg/cpp0x/variadic-ex13.C : New.
+       * g++.dg/cpp0x/variadic-ex14.C : New.
+
 2007-03-09  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
        PR libgfortran/31099
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-bind.C b/gcc/testsuite/g++.dg/cpp0x/variadic-bind.C
new file mode 100644 (file)
index 0000000..b9f9f67
--- /dev/null
@@ -0,0 +1,476 @@
+// { dg-options "-std=gnu++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;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex1.C
new file mode 100644 (file)
index 0000000..d5ebf0d
--- /dev/null
@@ -0,0 +1,4 @@
+// { dg-options "-std=gnu++0x" }
+template<typename ... Elements> class Tuple;
+Tuple<>* t; // OK: Elements is empty
+Tuple* u; // { dg-error "expected" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex10.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex10.C
new file mode 100644 (file)
index 0000000..a392bd7
--- /dev/null
@@ -0,0 +1,9 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... Types> struct Tuple { };
+
+Tuple<> t0; // Types contains no arguments
+Tuple<int> t1; // Types contains one argument: int
+Tuple<int, float> t2; // Types contains two arguments: int and float
+Tuple<0> error; // { dg-error "mismatch" }
+// { dg-error "expected a type" "" { target *-*-* } 7 }
+// { dg-error "in declaration" "" { target *-*-* } 7 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex11.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex11.C
new file mode 100644 (file)
index 0000000..57ef2a3
--- /dev/null
@@ -0,0 +1,9 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... Types> 
+  void f(Types... args);
+
+void g() {
+  f(); // okay: args contains no arguments
+  f(1); // okay: args contains one int argument
+  (2, 1.0); // okay: args contains two arguments, an int and a double
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex12.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex12.C
new file mode 100644 (file)
index 0000000..b97df31
--- /dev/null
@@ -0,0 +1,8 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... Types> 
+  void f(Types... rest);
+
+template<typename... Types> 
+  void g(Types... rest) {
+    f(&rest...); // ``&rest...'' is a pack expansion, ``&rest'' is its pattern
+  }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex13.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex13.C
new file mode 100644 (file)
index 0000000..f1cce3a
--- /dev/null
@@ -0,0 +1,39 @@
+// { dg-options "-std=gnu++0x" }
+
+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...> struct Tuple {};
+template<typename T1, typename T2> struct Pair {};
+
+template<typename... Args1>
+  struct zip {
+    template<typename... Args2>
+    struct with {
+      typedef Tuple<Pair<Args1, Args2>...> type; // { dg-error "mismatched argument pack" }
+    };
+  };
+
+static_assert 
+  (is_same<zip<short, int>::with<unsigned short, unsigned>::type,
+           Tuple<Pair<short, unsigned short>, Pair<int, unsigned> > >::value,
+   "zip");
+
+typedef zip<short>::with<unsigned short, unsigned>::type T2; // error: different number of arguments specified 
+                                                             // for Args1 and Args2
+
+template<typename... Args> void f(Args...);
+
+template<typename... Args> void g(Args... args) 
+{
+   f(const_cast<const Args*>(&args)...); // okay: ``Args'' and ``args'' are expanded
+   f(5 ...); // { dg-error "contains no argument packs" }
+   f(args); // { dg-error "parameter packs not expanded" }
+   // { dg-error "args" "" { target *-*-* } 36 }
+   f(h(args...) + args...); // okay: first ``args'' expanded within h, second ``args'' expanded within f.
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C
new file mode 100644 (file)
index 0000000..7050256
--- /dev/null
@@ -0,0 +1,23 @@
+// { dg-options "-std=gnu++0x" }
+
+template<class T> class A { /* ... */ };
+template<class T, class U = T> class B { /* ... */ };
+template<class... Types> class C { /* ... */ };
+
+template<template<class> class P> class X { /* ... */ };
+template<template<class...> class Q> class Y { /* ... */ };
+
+X<A> xA; // okay
+X<B> xB; // { dg-error "mismatch" }
+// { dg-error "expected a template" "" { target *-*-* } 11 }
+// { dg-error "invalid type" "" { target *-*-* } 11 }
+X<C> xC; // { dg-error "mismatch" }
+// { dg-error "expected a template" "" { target *-*-* } 14 }
+// { dg-error "invalid type" "" { target *-*-* } 14 }
+Y<A> yA; // { dg-error "mismatch" }
+// { dg-error "expected a template" "" { target *-*-* } 17 }
+// { dg-error "invalid type" "" { target *-*-* } 17 }
+Y<B> yB; // { dg-error "mismatch" }
+// { dg-error "expected a template" "" { target *-*-* } 20 }
+// { dg-error "invalid type" "" { target *-*-* } 20 }
+Y<C> yC; // okay
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C
new file mode 100644 (file)
index 0000000..ca5fa27
--- /dev/null
@@ -0,0 +1,8 @@
+// { dg-options "-std=gnu++0x" }
+template<class... Types> struct B { // { dg-error "declaration of" }
+  void f3();
+  void f4();
+};
+
+template<class... Types> void B<Types...>::f3() { } // OK
+template<class... Types> void B<Types>::f4() { } // { dg-error "invalid" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C
new file mode 100644 (file)
index 0000000..8b8ca9e
--- /dev/null
@@ -0,0 +1,9 @@
+// { dg-options "-std=gnu++0x" }
+template<class X, class Y, class... Z> X f(Y); 
+void g() 
+{ 
+  int i = f<int>(5.6);
+  int j = f(5.6);         // { dg-error "no matching" }
+  f<void>(f<int, bool>); 
+  f<void>(f<int>);        // { dg-error "no matching" }
+} 
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C
new file mode 100644 (file)
index 0000000..69866dc
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-options "-std=gnu++0x" }
+template<class X, class Y, class Z> X f(Y,Z); 
+template<class... Args> void f2();
+void g() 
+{ 
+  f<int,const char*,double>("aa",3.0); 
+  f<int,const char*>("aa",3.0); // Z is deduced to be double 
+  f<int>("aa",3.0); // Y is deduced to be char*, and 
+                    // Z is deduced to be double 
+  f("aa",3.0); // { dg-error "no matching" }
+  f2<char, short, int, long>(); // okay
+} 
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex5.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex5.C
new file mode 100644 (file)
index 0000000..2439a51
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... Types> void f(Types... values);
+
+void g()
+{
+  f<int*, float*>(0, 0, 0); // Types is deduced to the sequence int*, float*, int
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex6.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex6.C
new file mode 100644 (file)
index 0000000..87b1bf2
--- /dev/null
@@ -0,0 +1,13 @@
+// { dg-options "-std=gnu++0x" }
+template<class...> struct Tuple { };
+
+template<class... Types> void f(Types&...);
+template<class... Types1, class... Types2> void g(Tuple<Types1...>, Tuple<Types2...>);
+
+void h(int x, float& y) 
+{
+  const int z = x;
+  f(x, y, z); // Types is deduced to int, const int, float
+  g(Tuple<short, int, long>(), Tuple<float, double>()); // Types1 is deduced to short, int long
+                                                        // Types2 is deduced to float, double
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex7.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex7.C
new file mode 100644 (file)
index 0000000..7ca31f9
--- /dev/null
@@ -0,0 +1,13 @@
+// { dg-options "-std=gnu++0x" }
+template<typename...> struct Tuple { };
+template<typename... Types>              char& g(Tuple<Types...>);       // #1
+template<typename T1, typename... Types> short& g(Tuple<T1, Types...>);   // #2
+template<typename T1, typename... Types> int& g(Tuple<T1, Types&...>);  // #3
+
+void f() {
+  //  char& x1 = g(Tuple<>());             // calls #1
+  short& y1 = g(Tuple<int, float>());  // calls #2
+  //  int& z1 = g(Tuple<int, float&>());   // calls #3
+  //  int& z2 = g(Tuple<int>());           // calls #3
+  //  int& z3 = g(Tuple<int>());           // calls #3
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex8.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex8.C
new file mode 100644 (file)
index 0000000..03d28b8
--- /dev/null
@@ -0,0 +1,18 @@
+// { dg-options "-std=gnu++0x" }
+template<class> struct X { static const bool primary = true; };
+template<class R, class... ArgTypes> struct X<R(int, ArgTypes...)> { 
+  static const bool primary = false;
+};
+template<class... Types> struct Y { static const bool primary = true; };
+template<class T, class... Types> struct Y<T, Types&...> { 
+  static const bool primary = false;
+};
+
+static_assert (X<int>::primary, "uses primary template");
+static_assert (!X<int(int, float, double)>::primary, 
+              "uses partial specialization");
+static_assert (X<int(float, int)>::primary, "uses primary template");
+static_assert (Y<>::primary, "uses primary template");
+static_assert (!Y<int&, float&, double&>::primary, 
+              "uses partial specialization");
+static_assert (Y<int, float, double>::primary, "uses primary template");
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex9.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex9.C
new file mode 100644 (file)
index 0000000..ec78a7a
--- /dev/null
@@ -0,0 +1,10 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... Args>              char& f(Args... args);         // #1
+template<typename T1, typename... Args> short& f(T1 a1, Args... args); // #2
+template<typename T1, typename T2>      int& f(T1 a2, T2 a2);          // #3
+
+void g() {
+  char& x = f();                      // calls #1
+  short& y = f(1, 2, 3);              // calls #2
+  int& z = f(1, 2);                   // calls #3
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-function.C b/gcc/testsuite/g++.dg/cpp0x/variadic-function.C
new file mode 100644 (file)
index 0000000..0373efd
--- /dev/null
@@ -0,0 +1,96 @@
+// { dg-options "-std=gnu++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;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-mem_fn.C b/gcc/testsuite/g++.dg/cpp0x/variadic-mem_fn.C
new file mode 100644 (file)
index 0000000..6e29d3b
--- /dev/null
@@ -0,0 +1,50 @@
+// { dg-options "-std=gnu++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;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C b/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C
new file mode 100644 (file)
index 0000000..2c298a1
--- /dev/null
@@ -0,0 +1,294 @@
+// { dg-options "-std=gnu++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);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic1.C b/gcc/testsuite/g++.dg/cpp0x/variadic1.C
new file mode 100644 (file)
index 0000000..f87d53c
--- /dev/null
@@ -0,0 +1,10 @@
+// { dg-options "-std=gnu++0x" }
+template<typename...>
+class tuple;
+
+template<typename... Args>
+class tuple { };
+
+template<typename T1, class... Args>
+class tuple1p { };
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic10.C b/gcc/testsuite/g++.dg/cpp0x/variadic10.C
new file mode 100644 (file)
index 0000000..5f73eba
--- /dev/null
@@ -0,0 +1,22 @@
+// { dg-options "-std=gnu++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; 
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic11.C b/gcc/testsuite/g++.dg/cpp0x/variadic11.C
new file mode 100644 (file)
index 0000000..3c27de0
--- /dev/null
@@ -0,0 +1,18 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic12.C b/gcc/testsuite/g++.dg/cpp0x/variadic12.C
new file mode 100644 (file)
index 0000000..30108c9
--- /dev/null
@@ -0,0 +1,42 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic13.C b/gcc/testsuite/g++.dg/cpp0x/variadic13.C
new file mode 100644 (file)
index 0000000..7794e8a
--- /dev/null
@@ -0,0 +1,19 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic14.C b/gcc/testsuite/g++.dg/cpp0x/variadic14.C
new file mode 100644 (file)
index 0000000..3c1bb0d
--- /dev/null
@@ -0,0 +1,21 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic15.C b/gcc/testsuite/g++.dg/cpp0x/variadic15.C
new file mode 100644 (file)
index 0000000..68786cb
--- /dev/null
@@ -0,0 +1,21 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic16.C b/gcc/testsuite/g++.dg/cpp0x/variadic16.C
new file mode 100644 (file)
index 0000000..001919d
--- /dev/null
@@ -0,0 +1,21 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic17.C b/gcc/testsuite/g++.dg/cpp0x/variadic17.C
new file mode 100644 (file)
index 0000000..986721b
--- /dev/null
@@ -0,0 +1,21 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic18.C b/gcc/testsuite/g++.dg/cpp0x/variadic18.C
new file mode 100644 (file)
index 0000000..147ed8e
--- /dev/null
@@ -0,0 +1,47 @@
+// { dg-options "-std=gnu++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];
+
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic19.C b/gcc/testsuite/g++.dg/cpp0x/variadic19.C
new file mode 100644 (file)
index 0000000..92e7a95
--- /dev/null
@@ -0,0 +1,19 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic2.C b/gcc/testsuite/g++.dg/cpp0x/variadic2.C
new file mode 100644 (file)
index 0000000..d62a542
--- /dev/null
@@ -0,0 +1,17 @@
+// { dg-options "-std=gnu++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>" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic20.C b/gcc/testsuite/g++.dg/cpp0x/variadic20.C
new file mode 100644 (file)
index 0000000..06204c7
--- /dev/null
@@ -0,0 +1,47 @@
+// { dg-options "-std=gnu++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> { // { dg-error "candidates" }
+  static const int value = 2;
+};
+
+template<template<class T> class... Metafunctions>
+struct metatuple<add_pointer, Metafunctions...> { // { dg-error "" }
+  static const int value = 3;
+};
+
+template<template<class T> class First,
+         template<class T> class... Metafunctions>
+struct metatuple<First, Metafunctions...> { // { dg-error "struct" }
+  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...> { // { dg-error "struct" }
+  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]; // { dg-error "ambiguous" }
+int a2b[metatuple<add_reference, add_reference>::value == 2? 1 : -1];
+int a3[metatuple<add_pointer, add_reference>::value == 3? 1 : -1]; // { dg-error "ambiguous" }
+int a4[metatuple<add_reference>::value == 4? 1 : -1];
+int a5[metatuple<add_reference, add_pointer>::value == 5? 1 : -1];
+
+// { dg-error "incomplete" "" { target *-*-* } 40 }
+// { dg-error "incomplete" "" { target *-*-* } 42 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic21.C b/gcc/testsuite/g++.dg/cpp0x/variadic21.C
new file mode 100644 (file)
index 0000000..b65e995
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-options "-std=gnu++0x" }
+template<typename T, int... Dims>
+struct array { };
+
+array<int> a0;
+array<int, 1> a1;
+array<int, 1, 2, 3, 4> a1234;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic22.C b/gcc/testsuite/g++.dg/cpp0x/variadic22.C
new file mode 100644 (file)
index 0000000..1d26e40
--- /dev/null
@@ -0,0 +1,21 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic23.C b/gcc/testsuite/g++.dg/cpp0x/variadic23.C
new file mode 100644 (file)
index 0000000..43309a1
--- /dev/null
@@ -0,0 +1,25 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic24.C b/gcc/testsuite/g++.dg/cpp0x/variadic24.C
new file mode 100644 (file)
index 0000000..6ef8e8a
--- /dev/null
@@ -0,0 +1,6 @@
+// { dg-options "-std=gnu++0x" }
+template<typename T, T... Values>
+struct vector_c { };
+
+vector_c<int, 17, 42> intvec;
+vector_c<char, 'a', 'b', 'c'> charvec;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic25.C b/gcc/testsuite/g++.dg/cpp0x/variadic25.C
new file mode 100644 (file)
index 0000000..6589e7f
--- /dev/null
@@ -0,0 +1,16 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic26.C b/gcc/testsuite/g++.dg/cpp0x/variadic26.C
new file mode 100644 (file)
index 0000000..7f9f6bc
--- /dev/null
@@ -0,0 +1,24 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic27.C b/gcc/testsuite/g++.dg/cpp0x/variadic27.C
new file mode 100644 (file)
index 0000000..45a897c
--- /dev/null
@@ -0,0 +1,22 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic28.C b/gcc/testsuite/g++.dg/cpp0x/variadic28.C
new file mode 100644 (file)
index 0000000..167088b
--- /dev/null
@@ -0,0 +1,25 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic29.C b/gcc/testsuite/g++.dg/cpp0x/variadic29.C
new file mode 100644 (file)
index 0000000..aaed595
--- /dev/null
@@ -0,0 +1,35 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic3.C b/gcc/testsuite/g++.dg/cpp0x/variadic3.C
new file mode 100644 (file)
index 0000000..42ba8ab
--- /dev/null
@@ -0,0 +1,10 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... Args>
+class tuple {};
+
+void f()
+{
+  tuple<> x;
+  tuple<int> y;
+  tuple<int, float> z;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic30.C b/gcc/testsuite/g++.dg/cpp0x/variadic30.C
new file mode 100644 (file)
index 0000000..66cbe9f
--- /dev/null
@@ -0,0 +1,11 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... T>
+void eat(T...);
+
+void f()
+{
+  eat();
+  eat(1);
+  eat(1, 2);
+  eat(17, 3.14159, "Hello, World!");
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic31.C b/gcc/testsuite/g++.dg/cpp0x/variadic31.C
new file mode 100644 (file)
index 0000000..eacf568
--- /dev/null
@@ -0,0 +1,11 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... T>
+void eat(T...) { }
+
+void f()
+{
+  eat();
+  eat(1);
+  eat(1, 2);
+  eat(17, 3.14159, "Hello, World!");
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic32.C b/gcc/testsuite/g++.dg/cpp0x/variadic32.C
new file mode 100644 (file)
index 0000000..c5bee55
--- /dev/null
@@ -0,0 +1,11 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... T>
+void eat(const T&...) { }
+
+void f()
+{
+  eat();
+  eat(1);
+  eat(1, 2);
+  eat(17, 3.14159, "Hello, World!");
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic33.C b/gcc/testsuite/g++.dg/cpp0x/variadic33.C
new file mode 100644 (file)
index 0000000..5784be8
--- /dev/null
@@ -0,0 +1,16 @@
+// { dg-options "-std=gnu++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);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic34.C b/gcc/testsuite/g++.dg/cpp0x/variadic34.C
new file mode 100644 (file)
index 0000000..5eee3f1
--- /dev/null
@@ -0,0 +1,11 @@
+// { dg-options "-std=gnu++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');
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic35.C b/gcc/testsuite/g++.dg/cpp0x/variadic35.C
new file mode 100644 (file)
index 0000000..cd6ba2b
--- /dev/null
@@ -0,0 +1,9 @@
+// { dg-options "-std=gnu++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" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic36.C b/gcc/testsuite/g++.dg/cpp0x/variadic36.C
new file mode 100644 (file)
index 0000000..370d475
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-options "-std=gnu++0x" }
+template<typename T, typename... Args>
+void f(const T&, const Args&... args)
+{
+  f(args); // { dg-error "packs not expanded" }
+}
+
+template<typename... Values>
+struct tuple_base { };
+
+template<typename... Values>
+struct tuple : tuple_base<Values> { }; // { dg-error "packs not expanded" }
+
+// { dg-error "args" "" { target *-*-* } 5 }
+// { dg-error "Values" "" { target *-*-* } 12 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic37.C b/gcc/testsuite/g++.dg/cpp0x/variadic37.C
new file mode 100644 (file)
index 0000000..a6e5f61
--- /dev/null
@@ -0,0 +1,10 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic38.C b/gcc/testsuite/g++.dg/cpp0x/variadic38.C
new file mode 100644 (file)
index 0000000..e4ae4a6
--- /dev/null
@@ -0,0 +1,6 @@
+// { dg-options "-std=gnu++0x" }
+template<int... Values>
+struct int_vec {};
+
+template<int... Values>
+struct int_vec<0, (Values+1)...> {}; // { dg-error "involves template parameter" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic39.C b/gcc/testsuite/g++.dg/cpp0x/variadic39.C
new file mode 100644 (file)
index 0000000..bd656ba
--- /dev/null
@@ -0,0 +1,13 @@
+// { dg-options "-std=gnu++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" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic4.C b/gcc/testsuite/g++.dg/cpp0x/variadic4.C
new file mode 100644 (file)
index 0000000..6c15a6d
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-options "-std=gnu++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" } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic40.C b/gcc/testsuite/g++.dg/cpp0x/variadic40.C
new file mode 100644 (file)
index 0000000..6cc9273
--- /dev/null
@@ -0,0 +1,3 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... Values, typename T>
+struct backward_tuple {}; // { dg-error "end" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic41.C b/gcc/testsuite/g++.dg/cpp0x/variadic41.C
new file mode 100644 (file)
index 0000000..d209766
--- /dev/null
@@ -0,0 +1,3 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... Args>
+void f(const Args&... args, int oops); // { dg-error "end" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic42.C b/gcc/testsuite/g++.dg/cpp0x/variadic42.C
new file mode 100644 (file)
index 0000000..4c6c767
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-options "-std=gnu++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_" } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic43.C b/gcc/testsuite/g++.dg/cpp0x/variadic43.C
new file mode 100644 (file)
index 0000000..fce81ae
--- /dev/null
@@ -0,0 +1,8 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... Args>
+int f(const Args&...);
+
+void g()
+{
+  int (*fp)(const int&, const float&) = &f;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic44.C b/gcc/testsuite/g++.dg/cpp0x/variadic44.C
new file mode 100644 (file)
index 0000000..8452a96
--- /dev/null
@@ -0,0 +1,13 @@
+// { dg-options "-std=gnu++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_"} }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic45.C b/gcc/testsuite/g++.dg/cpp0x/variadic45.C
new file mode 100644 (file)
index 0000000..c5a66ab
--- /dev/null
@@ -0,0 +1,10 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... Args>
+int& f(Args...);
+
+template<typename T1, typename T2>
+float& f(T1, T2);
+
+float& g() { 
+  return f(17, 3.14159); 
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic46.C b/gcc/testsuite/g++.dg/cpp0x/variadic46.C
new file mode 100644 (file)
index 0000000..8b81a36
--- /dev/null
@@ -0,0 +1,11 @@
+// { dg-options "-std=gnu++0x" }
+template<typename... Args>
+int& f(Args&...);
+
+template<typename... Args>
+float& f(const Args&...);
+
+int& g(int x, float y)
+{
+  return f(x, y);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic47.C b/gcc/testsuite/g++.dg/cpp0x/variadic47.C
new file mode 100644 (file)
index 0000000..d80371c
--- /dev/null
@@ -0,0 +1,18 @@
+// { dg-options "-std=gnu++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);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic48.C b/gcc/testsuite/g++.dg/cpp0x/variadic48.C
new file mode 100644 (file)
index 0000000..ab3f777
--- /dev/null
@@ -0,0 +1,10 @@
+// { dg-options "-std=gnu++0x" }
+template<typename T, typename... Args>
+int& f(const T&, Args...);
+
+template<typename T>
+float& f(const T&);
+
+float& g() {
+  return f(17);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic49.C b/gcc/testsuite/g++.dg/cpp0x/variadic49.C
new file mode 100644 (file)
index 0000000..7e2215f
--- /dev/null
@@ -0,0 +1,9 @@
+// { dg-options "-std=gnu++0x" }
+int& f(...);
+
+template<typename... Args>
+float& f(Args...);
+
+float& g() {
+  return f(17, 3.14159);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic5.C b/gcc/testsuite/g++.dg/cpp0x/variadic5.C
new file mode 100644 (file)
index 0000000..d1f3335
--- /dev/null
@@ -0,0 +1,38 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic50.C b/gcc/testsuite/g++.dg/cpp0x/variadic50.C
new file mode 100644 (file)
index 0000000..a2c3b7c
--- /dev/null
@@ -0,0 +1,9 @@
+// { dg-options "-std=gnu++0x" }
+int& f(int, double, ...);
+
+template<typename... Args>
+float& f(Args...);
+
+float& g() {
+  return f(17, 3.14159, 3);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic51.C b/gcc/testsuite/g++.dg/cpp0x/variadic51.C
new file mode 100644 (file)
index 0000000..e2e2d63
--- /dev/null
@@ -0,0 +1,10 @@
+// { dg-options "-std=gnu++0x" }
+template<typename T1, typename T2>
+float& f(T1, T2);
+
+template<typename... Args>
+int& f(Args...);
+
+float& g() { 
+  return f(17, 3.14159); 
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic52.C b/gcc/testsuite/g++.dg/cpp0x/variadic52.C
new file mode 100644 (file)
index 0000000..12b121f
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-options "-std=gnu++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;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic53.C b/gcc/testsuite/g++.dg/cpp0x/variadic53.C
new file mode 100644 (file)
index 0000000..09a3879
--- /dev/null
@@ -0,0 +1,17 @@
+// { dg-options "-std=gnu++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)
+{
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic54.C b/gcc/testsuite/g++.dg/cpp0x/variadic54.C
new file mode 100644 (file)
index 0000000..db750d7
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-options "-std=gnu++0x" }
+template<typename F, typename... BoundArgs>
+class bound_functor
+{
+ public:
+  bound_functor();
+};
+
+template<typename F, typename... BoundArgs>
+bound_functor<F, BoundArgs...>::bound_functor()
+{
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic55.C b/gcc/testsuite/g++.dg/cpp0x/variadic55.C
new file mode 100644 (file)
index 0000000..b9c8cff
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-options "-std=gnu++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&...)
+{
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic56.C b/gcc/testsuite/g++.dg/cpp0x/variadic56.C
new file mode 100644 (file)
index 0000000..77846e5
--- /dev/null
@@ -0,0 +1,19 @@
+// { dg-options "-std=gnu++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; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic57.C b/gcc/testsuite/g++.dg/cpp0x/variadic57.C
new file mode 100644 (file)
index 0000000..9833b1b
--- /dev/null
@@ -0,0 +1,16 @@
+// { dg-options "-std=gnu++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() { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic58.C b/gcc/testsuite/g++.dg/cpp0x/variadic58.C
new file mode 100644 (file)
index 0000000..5da0730
--- /dev/null
@@ -0,0 +1,16 @@
+// { dg-options "-std=gnu++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)...);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic59.C b/gcc/testsuite/g++.dg/cpp0x/variadic59.C
new file mode 100644 (file)
index 0000000..f0730d3
--- /dev/null
@@ -0,0 +1,4 @@
+// { dg-options "-std=gnu++0x" }
+template<class T, typename... VarArgs>
+void print(T t, VarArgs args); // { dg-error "packs not expanded" }
+// { dg-error "VarArgs" "" { target *-*-* } 3 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic6.C b/gcc/testsuite/g++.dg/cpp0x/variadic6.C
new file mode 100644 (file)
index 0000000..105550b
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-options "-std=gnu++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;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic60.C b/gcc/testsuite/g++.dg/cpp0x/variadic60.C
new file mode 100644 (file)
index 0000000..29c4e29
--- /dev/null
@@ -0,0 +1 @@
+template<typename... Args> class tuple; // { dg-warning "variadic templates" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic61.C b/gcc/testsuite/g++.dg/cpp0x/variadic61.C
new file mode 100644 (file)
index 0000000..487f78b
--- /dev/null
@@ -0,0 +1,2 @@
+// { dg-options "-pedantic" }
+template<typename... Args> class tuple; // { dg-warning "variadic templates" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic62.C b/gcc/testsuite/g++.dg/cpp0x/variadic62.C
new file mode 100644 (file)
index 0000000..dfa41f7
--- /dev/null
@@ -0,0 +1,2 @@
+// { dg-options "-pedantic-errors" }
+template<typename... Args> class tuple; // { dg-error "variadic templates" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic63.C b/gcc/testsuite/g++.dg/cpp0x/variadic63.C
new file mode 100644 (file)
index 0000000..359def1
--- /dev/null
@@ -0,0 +1,2 @@
+// { dg-options "-std=gnu++0x -pedantic" }
+template<typename... Args> class tuple;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic64.C b/gcc/testsuite/g++.dg/cpp0x/variadic64.C
new file mode 100644 (file)
index 0000000..c9212e2
--- /dev/null
@@ -0,0 +1,19 @@
+// { dg-options "-std=gnu++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;
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic65.C b/gcc/testsuite/g++.dg/cpp0x/variadic65.C
new file mode 100644 (file)
index 0000000..6379da8
--- /dev/null
@@ -0,0 +1,8 @@
+// { dg-options "-std=gnu++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 expand" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic66.C b/gcc/testsuite/g++.dg/cpp0x/variadic66.C
new file mode 100644 (file)
index 0000000..5c31ae0
--- /dev/null
@@ -0,0 +1,9 @@
+// { dg-options "-std=gnu++0x" }
+
+template<typename Result, typename Functor, typename... ArgTypes>
+Result bind(Functor, ArgTypes...) { }
+
+void f()
+{
+  bind<int>(17, 20, 22);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic67.C b/gcc/testsuite/g++.dg/cpp0x/variadic67.C
new file mode 100644 (file)
index 0000000..e496bfc
--- /dev/null
@@ -0,0 +1,24 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic68.C b/gcc/testsuite/g++.dg/cpp0x/variadic68.C
new file mode 100644 (file)
index 0000000..53d8f2d
--- /dev/null
@@ -0,0 +1,23 @@
+// { dg-do "run" }
+// { dg-options "-std=gnu++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;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic69.C b/gcc/testsuite/g++.dg/cpp0x/variadic69.C
new file mode 100644 (file)
index 0000000..5fe9a19
--- /dev/null
@@ -0,0 +1,34 @@
+// { dg-options "-std=gnu++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);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic7.C b/gcc/testsuite/g++.dg/cpp0x/variadic7.C
new file mode 100644 (file)
index 0000000..3ba37bf
--- /dev/null
@@ -0,0 +1,33 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic70.C b/gcc/testsuite/g++.dg/cpp0x/variadic70.C
new file mode 100644 (file)
index 0000000..0bc8e82
--- /dev/null
@@ -0,0 +1,22 @@
+// { dg-do "run" }
+// { dg-options "-std=gnu++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;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic71.C b/gcc/testsuite/g++.dg/cpp0x/variadic71.C
new file mode 100644 (file)
index 0000000..d4219da
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-options "-std=gnu++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 expanded" }
+};
+
+// { dg-error "Elements" "" { target *-*-* } 9 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic72.C b/gcc/testsuite/g++.dg/cpp0x/variadic72.C
new file mode 100644 (file)
index 0000000..b1a620d
--- /dev/null
@@ -0,0 +1,21 @@
+// { dg-options "-std=gnu++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);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic73.C b/gcc/testsuite/g++.dg/cpp0x/variadic73.C
new file mode 100644 (file)
index 0000000..7bff85b
--- /dev/null
@@ -0,0 +1,33 @@
+// { dg-do "run" }
+// { dg-options "-std=gnu++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;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic74.C b/gcc/testsuite/g++.dg/cpp0x/variadic74.C
new file mode 100644 (file)
index 0000000..19b6b11
--- /dev/null
@@ -0,0 +1,26 @@
+// { dg-options "-std=gnu++0x" }
+template <class... Types> class A
+{
+public:
+  template <Types... Values> class X { /* ... */ }; // { dg-error "not a valid type for a template constant parameter" }
+};
+
+template<class... Types> class B
+{
+public:
+  template <Types*... Values> class X { 
+    typename A<Types*...>::template X<Values...> foo;
+  };
+};
+
+int i;
+float f;
+
+A<int*, float*>::X<&i, &f> apple1;
+B<int, float>::X<&i, &f> banana1;
+
+A<int*, float*>::X<&i> apple2; // { dg-error "wrong number of template arguments" }
+// { dg-error "invalid type" "" { target *-*-* } 22 }
+A<int*, float*>::X<&i, &f, &f> apple3; // { dg-error "wrong number of template arguments" }
+// { dg-error "invalid type" "" { target *-*-* } 24 }
+A<int, float> apple4;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic75.C b/gcc/testsuite/g++.dg/cpp0x/variadic75.C
new file mode 100644 (file)
index 0000000..f57f8b3
--- /dev/null
@@ -0,0 +1,33 @@
+// { dg-options "-std=gnu++0x" }
+
+template<typename...> struct tuple { };
+
+template<template<typename T> class Meta, typename... Values>
+struct apply_all
+{
+  typedef tuple<typename Meta<Values>::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_reference {
+  typedef T& type;
+};
+
+template<typename T>
+struct add_reference<T&> {
+  typedef T& type;
+};
+
+static_assert(is_same<apply_all<add_reference, int, int&, float>::type,
+                               tuple<int&, int&, float&> >::value, 
+             "check apply");
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic8.C b/gcc/testsuite/g++.dg/cpp0x/variadic8.C
new file mode 100644 (file)
index 0000000..c3a1340
--- /dev/null
@@ -0,0 +1,23 @@
+// { dg-options "-std=gnu++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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic9.C b/gcc/testsuite/g++.dg/cpp0x/variadic9.C
new file mode 100644 (file)
index 0000000..c5db6af
--- /dev/null
@@ -0,0 +1,38 @@
+// { dg-options "-std=gnu++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];