+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
--- /dev/null
+// { 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;
+}
--- /dev/null
+// { dg-options "-std=gnu++0x" }
+template<typename ... Elements> class Tuple;
+Tuple<>* t; // OK: Elements is empty
+Tuple* u; // { dg-error "expected" }
--- /dev/null
+// { 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 }
--- /dev/null
+// { 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
+}
--- /dev/null
+// { 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
+ }
--- /dev/null
+// { 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.
+}
--- /dev/null
+// { 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
--- /dev/null
+// { 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" }
--- /dev/null
+// { 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" }
+}
--- /dev/null
+// { 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
+}
--- /dev/null
+// { 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
+}
--- /dev/null
+// { 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
+}
--- /dev/null
+// { 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
+}
--- /dev/null
+// { 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");
--- /dev/null
+// { 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
+}
--- /dev/null
+// { 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;
+}
--- /dev/null
+// { 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;
+}
--- /dev/null
+// { 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);
+}
--- /dev/null
+// { dg-options "-std=gnu++0x" }
+template<typename...>
+class tuple;
+
+template<typename... Args>
+class tuple { };
+
+template<typename T1, class... Args>
+class tuple1p { };
+
--- /dev/null
+// { 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;
--- /dev/null
+// { 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];
--- /dev/null
+// { 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];
--- /dev/null
+// { 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];
--- /dev/null
+// { 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];
--- /dev/null
+// { 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];
--- /dev/null
+// { 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];
--- /dev/null
+// { 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];
--- /dev/null
+// { 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];
+
+
--- /dev/null
+// { 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];
--- /dev/null
+// { 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>" }
+}
--- /dev/null
+// { 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 }
--- /dev/null
+// { 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;
--- /dev/null
+// { 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];
--- /dev/null
+// { 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];
--- /dev/null
+// { 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;
--- /dev/null
+// { 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];
--- /dev/null
+// { 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];
--- /dev/null
+// { 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];
--- /dev/null
+// { 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];
--- /dev/null
+// { 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];
--- /dev/null
+// { dg-options "-std=gnu++0x" }
+template<typename... Args>
+class tuple {};
+
+void f()
+{
+ tuple<> x;
+ tuple<int> y;
+ tuple<int, float> z;
+}
--- /dev/null
+// { 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!");
+}
--- /dev/null
+// { 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!");
+}
--- /dev/null
+// { 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!");
+}
--- /dev/null
+// { 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);
+}
--- /dev/null
+// { 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');
+}
--- /dev/null
+// { 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" }
+}
--- /dev/null
+// { 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 }
--- /dev/null
+// { 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];
--- /dev/null
+// { 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" }
--- /dev/null
+// { 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" }
--- /dev/null
+// { 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" } }
--- /dev/null
+// { dg-options "-std=gnu++0x" }
+template<typename... Values, typename T>
+struct backward_tuple {}; // { dg-error "end" }
--- /dev/null
+// { dg-options "-std=gnu++0x" }
+template<typename... Args>
+void f(const Args&... args, int oops); // { dg-error "end" }
--- /dev/null
+// { 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_" } }
--- /dev/null
+// { dg-options "-std=gnu++0x" }
+template<typename... Args>
+int f(const Args&...);
+
+void g()
+{
+ int (*fp)(const int&, const float&) = &f;
+}
--- /dev/null
+// { 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_"} }
--- /dev/null
+// { 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);
+}
--- /dev/null
+// { 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);
+}
--- /dev/null
+// { 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);
+}
--- /dev/null
+// { 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);
+}
--- /dev/null
+// { dg-options "-std=gnu++0x" }
+int& f(...);
+
+template<typename... Args>
+float& f(Args...);
+
+float& g() {
+ return f(17, 3.14159);
+}
--- /dev/null
+// { 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];
--- /dev/null
+// { dg-options "-std=gnu++0x" }
+int& f(int, double, ...);
+
+template<typename... Args>
+float& f(Args...);
+
+float& g() {
+ return f(17, 3.14159, 3);
+}
--- /dev/null
+// { 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);
+}
--- /dev/null
+// { 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;
--- /dev/null
+// { 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)
+{
+}
--- /dev/null
+// { 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()
+{
+}
--- /dev/null
+// { 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&...)
+{
+}
--- /dev/null
+// { 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; }
--- /dev/null
+// { 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() { }
--- /dev/null
+// { 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)...);
+}
--- /dev/null
+// { 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 }
--- /dev/null
+// { 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;
--- /dev/null
+template<typename... Args> class tuple; // { dg-warning "variadic templates" }
--- /dev/null
+// { dg-options "-pedantic" }
+template<typename... Args> class tuple; // { dg-warning "variadic templates" }
--- /dev/null
+// { dg-options "-pedantic-errors" }
+template<typename... Args> class tuple; // { dg-error "variadic templates" }
--- /dev/null
+// { dg-options "-std=gnu++0x -pedantic" }
+template<typename... Args> class tuple;
--- /dev/null
+// { 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;
+};
--- /dev/null
+// { 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" }
--- /dev/null
+// { dg-options "-std=gnu++0x" }
+
+template<typename Result, typename Functor, typename... ArgTypes>
+Result bind(Functor, ArgTypes...) { }
+
+void f()
+{
+ bind<int>(17, 20, 22);
+}
--- /dev/null
+// { 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];
--- /dev/null
+// { 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;
+}
--- /dev/null
+// { 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);
+}
--- /dev/null
+// { 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];
--- /dev/null
+// { 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;
+}
--- /dev/null
+// { 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 }
--- /dev/null
+// { 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);
+}
--- /dev/null
+// { 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;
+}
--- /dev/null
+// { 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;
--- /dev/null
+// { 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");
--- /dev/null
+// { 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];
--- /dev/null
+// { 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];