re PR c++/20599 (variadic template support)

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
This commit is contained in:
Douglas Gregor 2007-03-10 02:01:49 +00:00 committed by Doug Gregor
parent 5d80a30674
commit d6a85c8dd4
94 changed files with 2473 additions and 0 deletions

View 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

View File

@ -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;
}

View File

@ -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" }

View File

@ -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 }

View File

@ -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
}

View File

@ -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
}

View File

@ -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.
}

View File

@ -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

View File

@ -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" }

View File

@ -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" }
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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");

View File

@ -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
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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 { };

View File

@ -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;

View File

@ -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];

View File

@ -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];

View File

@ -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];

View File

@ -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];

View File

@ -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];

View File

@ -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];

View File

@ -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];

View File

@ -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];

View File

@ -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];

View File

@ -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>" }
}

View File

@ -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 }

View File

@ -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;

View File

@ -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];

View File

@ -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];

View File

@ -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;

View File

@ -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];

View File

@ -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];

View File

@ -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];

View File

@ -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];

View File

@ -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];

View File

@ -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;
}

View File

@ -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!");
}

View File

@ -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!");
}

View File

@ -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!");
}

View File

@ -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);
}

View File

@ -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');
}

View File

@ -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" }
}

View File

@ -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 }

View File

@ -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];

View File

@ -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" }

View File

@ -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" }

View File

@ -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" } }

View File

@ -0,0 +1,3 @@
// { dg-options "-std=gnu++0x" }
template<typename... Values, typename T>
struct backward_tuple {}; // { dg-error "end" }

View File

@ -0,0 +1,3 @@
// { dg-options "-std=gnu++0x" }
template<typename... Args>
void f(const Args&... args, int oops); // { dg-error "end" }

View File

@ -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_" } }

View File

@ -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;
}

View File

@ -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_"} }

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -0,0 +1,9 @@
// { dg-options "-std=gnu++0x" }
int& f(...);
template<typename... Args>
float& f(Args...);
float& g() {
return f(17, 3.14159);
}

View File

@ -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];

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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)
{
}

View File

@ -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()
{
}

View File

@ -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&...)
{
}

View File

@ -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; }

View File

@ -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() { }

View File

@ -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)...);
}

View File

@ -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 }

View File

@ -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;

View File

@ -0,0 +1 @@
template<typename... Args> class tuple; // { dg-warning "variadic templates" }

View File

@ -0,0 +1,2 @@
// { dg-options "-pedantic" }
template<typename... Args> class tuple; // { dg-warning "variadic templates" }

View File

@ -0,0 +1,2 @@
// { dg-options "-pedantic-errors" }
template<typename... Args> class tuple; // { dg-error "variadic templates" }

View File

@ -0,0 +1,2 @@
// { dg-options "-std=gnu++0x -pedantic" }
template<typename... Args> class tuple;

View File

@ -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;
};

View File

@ -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" }

View File

@ -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);
}

View File

@ -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];

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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];

View File

@ -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;
}

View File

@ -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 }

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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");

View File

@ -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];

View File

@ -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];