1 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
2 // expected-no-diagnostics
4 // Example tuple implementation from the variadic templates proposal,
5 // ISO C++ committee document number N2080.
14 struct add_reference
<T
&> {
19 struct add_const_reference
{
20 typedef T
const &type
;
24 struct add_const_reference
<T
&> {
28 template<typename T
, typename U
>
30 static const bool value
= false;
34 struct is_same
<T
, T
> {
35 static const bool value
= true;
39 class reference_wrapper
{
43 reference_wrapper(T
& t
) : ptr(&t
) { }
44 operator T
&() const { return *ptr
; }
47 template<typename T
> reference_wrapper
<T
> ref(T
& t
) {
48 return reference_wrapper
<T
>(t
);
50 template<typename T
> reference_wrapper
<const T
> cref(const T
& t
) {
51 return reference_wrapper
<const T
>(t
);
54 template<typename
... Values
> class tuple
;
56 // Basis case: zero-length tuple
57 template<> class tuple
<> { };
59 template<typename Head
, typename
... Tail
>
60 class tuple
<Head
, Tail
...> : private tuple
<Tail
...> {
61 typedef tuple
<Tail
...> inherited
;
65 // implicit copy-constructor is okay
67 // Construct tuple from separate arguments.
68 tuple(typename add_const_reference
<Head
>::type v
,
69 typename add_const_reference
<Tail
>::type
... vtail
)
70 : m_head(v
), inherited(vtail
...) { }
72 // Construct tuple from another tuple.
73 template<typename
... VValues
> tuple(const tuple
<VValues
...>& other
)
74 : m_head(other
.head()), inherited(other
.tail()) { }
76 template<typename
... VValues
> tuple
&
77 operator=(const tuple
<VValues
...>& other
) {
78 m_head
= other
.head();
79 tail() = other
.tail();
83 typename add_reference
<Head
>::type
head() { return m_head
; }
84 typename add_reference
<const Head
>::type
head() const { return m_head
; }
85 inherited
& tail() { return *this; }
86 const inherited
& tail() const { return *this; }
102 tuple
<float> t1d(3.14159);
103 tuple
<float> t1e(t1d
);
109 tuple
<int*, float*, double*> t3a(&i
, &f
, &d
);
112 // Creation functions
114 struct make_tuple_result
{
119 struct make_tuple_result
<reference_wrapper
<T
> > {
123 template<typename
... Values
>
124 tuple
<typename make_tuple_result
<Values
>::type
...>
125 make_tuple(const Values
&... values
) {
126 return tuple
<typename make_tuple_result
<Values
>::type
...>(values
...);
129 template<typename
... Values
>
130 tuple
<Values
&...> tie(Values
&... values
) {
131 return tuple
<Values
&...>(values
...);
134 template<typename T
> const T
*addr(const T
& ref
) { return &ref
; }
135 void test_creation_functions() {
139 const tuple
<int, float&, const double&> *t3p
= addr(make_tuple(i
, ref(f
), cref(d
)));
140 const tuple
<int&, float&, double&> *t3q
= addr(tie(i
, f
, d
));
144 template<typename Tuple
> struct tuple_size
;
146 template<typename
... Values
> struct tuple_size
<tuple
<Values
...> > {
147 static const int value
= sizeof...(Values
);
150 int check_tuple_size_0
[tuple_size
<tuple
<> >::value
== 0? 1 : -1];
151 int check_tuple_size_1
[tuple_size
<tuple
<int>>::value
== 1? 1 : -1];
152 int check_tuple_size_2
[tuple_size
<tuple
<float, double>>::value
== 2? 1 : -1];
153 int check_tuple_size_3
[tuple_size
<tuple
<char, unsigned char, signed char>>::value
== 3? 1 : -1];
155 template<int I
, typename Tuple
> struct tuple_element
;
157 template<int I
, typename Head
, typename
... Tail
>
158 struct tuple_element
<I
, tuple
<Head
, Tail
...> > {
159 typedef typename tuple_element
<I
-1, tuple
<Tail
...> >::type type
;
162 template<typename Head
, typename
... Tail
>
163 struct tuple_element
<0, tuple
<Head
, Tail
...> > {
167 int check_tuple_element_0
[is_same
<tuple_element
<0, tuple
<int&, float, double>>::type
,
168 int&>::value
? 1 : -1];
170 int check_tuple_element_1
[is_same
<tuple_element
<1, tuple
<int&, float, double>>::type
,
171 float>::value
? 1 : -1];
173 int check_tuple_element_2
[is_same
<tuple_element
<2, tuple
<int&, float, double>>::type
,
174 double>::value
? 1 : -1];
177 template<int I
, typename Tuple
> class get_impl
;
178 template<int I
, typename Head
, typename
... Values
>
179 class get_impl
<I
, tuple
<Head
, Values
...> > {
180 typedef typename tuple_element
<I
-1, tuple
<Values
...> >::type Element
;
181 typedef typename add_reference
<Element
>::type RJ
;
182 typedef typename add_const_reference
<Element
>::type PJ
;
183 typedef get_impl
<I
-1, tuple
<Values
...> > Next
;
185 static RJ
get(tuple
<Head
, Values
...>& t
) { return Next::get(t
.tail()); }
186 static PJ
get(const tuple
<Head
, Values
...>& t
) { return Next::get(t
.tail()); }
189 template<typename Head
, typename
... Values
>
190 class get_impl
<0, tuple
<Head
, Values
...> > {
191 typedef typename add_reference
<Head
>::type RJ
;
192 typedef typename add_const_reference
<Head
>::type PJ
;
194 static RJ
get(tuple
<Head
, Values
...>& t
) { return t
.head(); }
195 static PJ
get(const tuple
<Head
, Values
...>& t
) { return t
.head(); }
198 template<int I
, typename
... Values
> typename add_reference
<
199 typename tuple_element
<I
, tuple
<Values
...> >::type
>::type
200 get(tuple
<Values
...>& t
) {
201 return get_impl
<I
, tuple
<Values
...> >::get(t
);
204 template<int I
, typename
... Values
> typename add_const_reference
<
205 typename tuple_element
<I
, tuple
<Values
...> >::type
>::type
206 get(const tuple
<Values
...>& t
) {
207 return get_impl
<I
, tuple
<Values
...> >::get(t
);
210 void test_element_access(tuple
<int*, float*, double*&> t3
) {
219 // Relational operators
220 inline bool operator==(const tuple
<>&, const tuple
<>&) { return true; }
222 template<typename T
, typename
... TTail
, typename U
, typename
... UTail
>
223 bool operator==(const tuple
<T
, TTail
...>& t
, const tuple
<U
, UTail
...>& u
) {
224 return t
.head() == u
.head() && t
.tail() == u
.tail();
227 template<typename
... TValues
, typename
... UValues
>
228 bool operator!=(const tuple
<TValues
...>& t
, const tuple
<UValues
...>& u
) {
232 inline bool operator<(const tuple
<>&, const tuple
<>&) { return false; }
234 template<typename T
, typename
... TTail
, typename U
, typename
... UTail
>
235 bool operator<(const tuple
<T
, TTail
...>& t
, const tuple
<U
, UTail
...>& u
) {
236 return (t
.head() < u
.head() || (!(t
.head() < u
.head()) && t
.tail() < u
.tail()));
239 template<typename
... TValues
, typename
... UValues
>
240 bool operator>(const tuple
<TValues
...>& t
, const tuple
<UValues
...>& u
) {
244 template<typename
... TValues
, typename
... UValues
>
245 bool operator<=(const tuple
<TValues
...>& t
, const tuple
<UValues
...>& u
) {
249 template<typename
... TValues
, typename
... UValues
>
250 bool operator>=(const tuple
<TValues
...>& t
, const tuple
<UValues
...>& u
) {
254 void test_relational_operators(tuple
<int*, float*, double*> t3
) {