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