1762bb9d0ad20320b9f97a841dce57ba5e8e48b07Richard Smith// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
28e8fb3be5bd78f0564444eca02b404566a5f3b5dAndy Gibbs// expected-no-diagnostics
3d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
4d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor// Example bind implementation from the variadic templates proposal,
5d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor// ISO C++ committee document number N2080.
6d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
7d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor// Helper type traits
8d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T>
9d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct add_reference {
10d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef T &type;
11d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
12d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
13d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T>
14d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct add_reference<T&> {
15d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef T &type;
16d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
17d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
18d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T>
19d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct add_const_reference {
20d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef T const &type;
21d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
22d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
23d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T>
24d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct add_const_reference<T&> {
25d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef T &type;
26d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
27d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
28d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T, typename U>
29d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct is_same {
30d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  static const bool value = false;
31d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
32d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
33d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T>
34d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct is_same<T, T> {
35d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  static const bool value = true;
36d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
37d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
38d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T>
39d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorclass reference_wrapper {
40d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  T *ptr;
41d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
42d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorpublic:
43d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  reference_wrapper(T& t) : ptr(&t) { }
44d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  operator T&() const { return *ptr; }
45d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
46d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
47d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T> reference_wrapper<T> ref(T& t) {
48d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return reference_wrapper<T>(t);
49d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
50d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T> reference_wrapper<const T> cref(const T& t) {
51d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return reference_wrapper<const T>(t);
52d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
53d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
54d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename... Values> class tuple;
55d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
56d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor// Basis case: zero-length tuple
57d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<> class tuple<> { };
58d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
59d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename Head, typename... Tail>
60d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorclass tuple<Head, Tail...> : private tuple<Tail...> {
61d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef tuple<Tail...> inherited;
62d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
63d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorpublic:
64d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  tuple() { }
65d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  // implicit copy-constructor is okay
66d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
67d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  // Construct tuple from separate arguments.
68d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  tuple(typename add_const_reference<Head>::type v,
69d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor        typename add_const_reference<Tail>::type... vtail)
70d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor    : m_head(v), inherited(vtail...) { }
71d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
72d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  // Construct tuple from another tuple.
73d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  template<typename... VValues> tuple(const tuple<VValues...>& other)
74d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor    : m_head(other.head()), inherited(other.tail()) { }
75d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
76d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  template<typename... VValues> tuple&
77d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  operator=(const tuple<VValues...>& other) {
78d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor    m_head = other.head();
79d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor    tail() = other.tail();
80d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor    return *this;
81d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  }
82d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
83d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typename add_reference<Head>::type head() { return m_head; }
84d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typename add_reference<const Head>::type head() const { return m_head; }
85d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  inherited& tail() { return *this; }
86d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  const inherited& tail() const { return *this; }
87d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
88d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorprotected:
89d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  Head m_head;
90d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
91d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
92d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor// Creation functions
93d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T>
94d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct make_tuple_result {
95d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef T type;
96d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
97d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
98d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T>
99d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct make_tuple_result<reference_wrapper<T> > {
100d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef T& type;
101d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
102d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
103d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename... Values>
104d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortuple<typename make_tuple_result<Values>::type...>
105d3731198193eee92796ddeb493973b7a598b003eDouglas Gregormake_tuple(const Values&... values) {
106d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return tuple<typename make_tuple_result<Values>::type...>(values...);
107d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
108d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
109d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename... Values>
110d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortuple<Values&...> tie(Values&... values) {
111d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return tuple<Values&...>(values...);
112d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
113d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
114d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor// Helper classes
115d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename Tuple> struct tuple_size;
116d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
117d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename... Values> struct tuple_size<tuple<Values...> > {
118d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  static const int value = sizeof...(Values);
119d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
120d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
121d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<int I, typename Tuple> struct tuple_element;
122d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
123d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<int I, typename Head, typename... Tail>
124d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct tuple_element<I, tuple<Head, Tail...> > {
125d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
126d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
127d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
128d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename Head, typename... Tail>
129d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct tuple_element<0, tuple<Head, Tail...> > {
130d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef Head type;
131d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
132d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
133d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor// Element access
134d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<int I, typename Tuple> class get_impl;
135d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<int I, typename Head, typename... Values>
136d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorclass get_impl<I, tuple<Head, Values...> > {
137d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef typename tuple_element<I-1, tuple<Values...> >::type Element;
138d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef typename add_reference<Element>::type RJ;
139d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef typename add_const_reference<Element>::type PJ;
140d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef get_impl<I-1, tuple<Values...> > Next;
141d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorpublic:
142d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  static RJ get(tuple<Head, Values...>& t) { return Next::get(t.tail()); }
143d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  static PJ get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); }
144d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
145d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
146d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename Head, typename... Values>
147d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorclass get_impl<0, tuple<Head, Values...> > {
148d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef typename add_reference<Head>::type RJ;
149d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef typename add_const_reference<Head>::type PJ;
150d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorpublic:
151d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  static RJ get(tuple<Head, Values...>& t) { return t.head(); }
152d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  static PJ get(const tuple<Head, Values...>& t) { return t.head(); }
153d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
154d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
155d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<int I, typename... Values> typename add_reference<
156d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortypename tuple_element<I, tuple<Values...> >::type >::type
157d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorget(tuple<Values...>& t) {
158d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return get_impl<I, tuple<Values...> >::get(t);
159d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
160d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
161d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<int I, typename... Values> typename add_const_reference<
162d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortypename tuple_element<I, tuple<Values...> >::type >::type
163d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorget(const tuple<Values...>& t) {
164d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return get_impl<I, tuple<Values...> >::get(t);
165d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
166d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
167d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor// Relational operators
168d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorinline bool operator==(const tuple<>&, const tuple<>&) { return true; }
169d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
170d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T, typename... TTail, typename U, typename... UTail>
171d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorbool operator==(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) {
172d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return t.head() == u.head() && t.tail() == u.tail();
173d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
174d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
175d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename... TValues, typename... UValues>
176d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorbool operator!=(const tuple<TValues...>& t, const tuple<UValues...>& u) {
177d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return !(t == u);
178d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
179d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
180d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorinline bool operator<(const tuple<>&, const tuple<>&) { return false; }
181d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
182d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T, typename... TTail, typename U, typename... UTail>
183d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorbool operator<(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) {
184d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return (t.head() < u.head() || (!(t.head() < u.head()) && t.tail() < u.tail()));
185d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
186d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
187d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename... TValues, typename... UValues>
188d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorbool operator>(const tuple<TValues...>& t, const tuple<UValues...>& u) {
189d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return u < t;
190d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
191d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
192d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename... TValues, typename... UValues>
193d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorbool operator<=(const tuple<TValues...>& t, const tuple<UValues...>& u) {
194d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return !(u < t);
195d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
196d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
197d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename... TValues, typename... UValues>
198d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorbool operator>=(const tuple<TValues...>& t, const tuple<UValues...>& u) {
199d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return !(t < u);
200d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
201d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
202d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor// make_indices helper
203d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<int...> struct int_tuple {};
204d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor// make_indexes impl is a helper for make_indexes
205d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<int I, typename IntTuple, typename... Types> struct make_indexes_impl;
206d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
207d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<int I, int... Indexes, typename T, typename... Types>
208d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct make_indexes_impl<I, int_tuple<Indexes...>, T, Types...> {
209d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef typename make_indexes_impl<I+1, int_tuple<Indexes..., I>, Types...>::type type;
210d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
211d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
212d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<int I, int... Indexes>
213d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct make_indexes_impl<I, int_tuple<Indexes...> > {
214d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef int_tuple<Indexes...> type;
215d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
216d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
217d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename... Types>
218d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct make_indexes : make_indexes_impl<0, int_tuple<>, Types...> {
219d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
220d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
221d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor// Bind
222d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T> struct is_bind_expression {
223d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  static const bool value = false;
224d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
225d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
226d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T> struct is_placeholder {
227d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  static const int value = 0;
228d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
229d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
230d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
231d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename F, typename... BoundArgs> class bound_functor {
232d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef typename make_indexes<BoundArgs...>::type indexes;
233d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorpublic:
234d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef typename F::result_type result_type;
235d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  explicit bound_functor(const F& f, const BoundArgs&... bound_args)
236d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor    : f(f), bound_args(bound_args...) { } template<typename... Args>
237d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typename F::result_type operator()(Args&... args);
238d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorprivate: F f;
239d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  tuple<BoundArgs...> bound_args;
240d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
241d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
242d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename F, typename... BoundArgs>
243d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorinline bound_functor<F, BoundArgs...> bind(const F& f, const BoundArgs&... bound_args) {
244d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return bound_functor<F, BoundArgs...>(f, bound_args...);
245d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
246d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
247d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename F, typename ...BoundArgs>
248d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct is_bind_expression<bound_functor<F, BoundArgs...> > {
249d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  static const bool value = true;
250d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
251d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
252d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor// enable_if helper
253d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<bool Cond, typename T = void>
254d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct enable_if;
255d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
256d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T>
257d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct enable_if<true, T> {
258d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef T type;
259d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
260d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
261d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T>
262d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct enable_if<false, T> { };
263d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
264d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor// safe_tuple_element helper
265d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<int I, typename Tuple, typename = void>
266d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct safe_tuple_element { };
267d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
268d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<int I, typename... Values>
269d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct safe_tuple_element<I, tuple<Values...>,
270d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor                          typename enable_if<(I >= 0 && I < tuple_size<tuple<Values...> >::value)>::type> {
271d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor   typedef typename tuple_element<I, tuple<Values...> >::type type;
272d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
273d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
274d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor// mu
275d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename Bound, typename... Args>
276d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorinline typename safe_tuple_element<is_placeholder<Bound>::value -1,
277d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor                                   tuple<Args...> >::type
278d3731198193eee92796ddeb493973b7a598b003eDouglas Gregormu(Bound& bound_arg, const tuple<Args&...>& args) {
279d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return get<is_placeholder<Bound>::value-1>(args);
280d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
281d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
282d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T, typename... Args>
283d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorinline T& mu(reference_wrapper<T>& bound_arg, const tuple<Args&...>&) {
284d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return bound_arg.get();
285d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
286d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
287d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename F, int... Indexes, typename... Args>
288d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorinline typename F::result_type
289d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorunwrap_and_forward(F& f, int_tuple<Indexes...>, const tuple<Args&...>& args) {
290d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return f(get<Indexes>(args)...);
291d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
292d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
293d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename Bound, typename... Args>
294d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorinline typename enable_if<is_bind_expression<Bound>::value,
295d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor                          typename Bound::result_type>::type
296d3731198193eee92796ddeb493973b7a598b003eDouglas Gregormu(Bound& bound_arg, const tuple<Args&...>& args) {
297d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef typename make_indexes<Args...>::type Indexes;
298d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return unwrap_and_forward(bound_arg, Indexes(), args);
299d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
300d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
301d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T>
302d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct is_reference_wrapper {
303d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  static const bool value = false;
304d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
305d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
306d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T>
307d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct is_reference_wrapper<reference_wrapper<T>> {
308d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  static const bool value = true;
309d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
310d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
311d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename Bound, typename... Args>
312d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorinline typename enable_if<(!is_bind_expression<Bound>::value
313d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor                           && !is_placeholder<Bound>::value
314d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor                           && !is_reference_wrapper<Bound>::value),
315d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor                           Bound&>::type
316d3731198193eee92796ddeb493973b7a598b003eDouglas Gregormu(Bound& bound_arg, const tuple<Args&...>&) {
317d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return bound_arg;
318d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
319d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
320d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename F, typename... BoundArgs, int... Indexes, typename... Args>
321d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortypename F::result_type apply_functor(F& f, tuple<BoundArgs...>& bound_args,
322d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor                                      int_tuple<Indexes...>,
323d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor                                      const tuple<Args&...>& args) {
324d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return f(mu(get<Indexes>(bound_args), args)...);
325d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
326d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
327d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename F, typename... BoundArgs>
328d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename... Args>
329d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortypename F::result_type bound_functor<F, BoundArgs...>::operator()(Args&... args) {
330d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  return apply_functor(f, bound_args, indexes(), tie(args...));
331d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
332d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
333d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<int N> struct placeholder { };
334d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<int N>
335d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct is_placeholder<placeholder<N>> {
336d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  static const int value = N;
337d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
338d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
339d3731198193eee92796ddeb493973b7a598b003eDouglas Gregortemplate<typename T>
340d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorstruct plus {
341d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  typedef T result_type;
342d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
343d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  T operator()(T x, T y) { return x + y; }
344d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor};
345d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
346d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorplaceholder<1> _1;
347d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor
348d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor// Test bind
349d3731198193eee92796ddeb493973b7a598b003eDouglas Gregorvoid test_bind() {
350d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  int x = 17;
351d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  int y = 25;
352d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor  bind(plus<int>(), x, _1)(y);
353d3731198193eee92796ddeb493973b7a598b003eDouglas Gregor}
354