Home | History | Annotate | Download | only in temp.variadic
      1 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
      2 
      3 // Example tuple 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 void test_tuple() {
     92   tuple<> t0a;
     93   tuple<> t0b(t0a);
     94   t0a = t0b;
     95 
     96   tuple<int> t1a;
     97   tuple<int> t1b(17);
     98   tuple<int> t1c(t1b);
     99   t1a = t1b;
    100 
    101   tuple<float> t1d(3.14159);
    102   tuple<float> t1e(t1d);
    103   t1d = t1e;
    104 
    105   int i;
    106   float f;
    107   double d;
    108   tuple<int*, float*, double*> t3a(&i, &f, &d);
    109 }
    110 
    111 // Creation functions
    112 template<typename T>
    113 struct make_tuple_result {
    114   typedef T type;
    115 };
    116 
    117 template<typename T>
    118 struct make_tuple_result<reference_wrapper<T> > {
    119   typedef T& type;
    120 };
    121 
    122 template<typename... Values>
    123 tuple<typename make_tuple_result<Values>::type...>
    124 make_tuple(const Values&... values) {
    125   return tuple<typename make_tuple_result<Values>::type...>(values...);
    126 }
    127 
    128 template<typename... Values>
    129 tuple<Values&...> tie(Values&... values) {
    130   return tuple<Values&...>(values...);
    131 }
    132 
    133 template<typename T> const T *addr(const T& ref) { return &ref; }
    134 void test_creation_functions() {
    135   int i;
    136   float f;
    137   double d;
    138   const tuple<int, float&, const double&> *t3p = addr(make_tuple(i, ref(f), cref(d)));
    139   const tuple<int&, float&, double&> *t3q = addr(tie(i, f, d));
    140 }
    141 
    142 // Helper classes
    143 template<typename Tuple> struct tuple_size;
    144 
    145 template<typename... Values> struct tuple_size<tuple<Values...> > {
    146   static const int value = sizeof...(Values);
    147 };
    148 
    149 int check_tuple_size_0[tuple_size<tuple<> >::value == 0? 1 : -1];
    150 int check_tuple_size_1[tuple_size<tuple<int>>::value == 1? 1 : -1];
    151 int check_tuple_size_2[tuple_size<tuple<float, double>>::value == 2? 1 : -1];
    152 int check_tuple_size_3[tuple_size<tuple<char, unsigned char, signed char>>::value == 3? 1 : -1];
    153 
    154 template<int I, typename Tuple> struct tuple_element;
    155 
    156 template<int I, typename Head, typename... Tail>
    157 struct tuple_element<I, tuple<Head, Tail...> > {
    158   typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
    159 };
    160 
    161 template<typename Head, typename... Tail>
    162 struct tuple_element<0, tuple<Head, Tail...> > {
    163   typedef Head type;
    164 };
    165 
    166 int check_tuple_element_0[is_same<tuple_element<0, tuple<int&, float, double>>::type,
    167                                   int&>::value? 1 : -1];
    168 
    169 int check_tuple_element_1[is_same<tuple_element<1, tuple<int&, float, double>>::type,
    170                                   float>::value? 1 : -1];
    171 
    172 int check_tuple_element_2[is_same<tuple_element<2, tuple<int&, float, double>>::type,
    173                                   double>::value? 1 : -1];
    174 
    175 // Element access
    176 template<int I, typename Tuple> class get_impl;
    177 template<int I, typename Head, typename... Values>
    178 class get_impl<I, tuple<Head, Values...> > {
    179   typedef typename tuple_element<I-1, tuple<Values...> >::type Element;
    180   typedef typename add_reference<Element>::type RJ;
    181   typedef typename add_const_reference<Element>::type PJ;
    182   typedef get_impl<I-1, tuple<Values...> > Next;
    183 public:
    184   static RJ get(tuple<Head, Values...>& t) { return Next::get(t.tail()); }
    185   static PJ get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); }
    186 };
    187 
    188 template<typename Head, typename... Values>
    189 class get_impl<0, tuple<Head, Values...> > {
    190   typedef typename add_reference<Head>::type RJ;
    191   typedef typename add_const_reference<Head>::type PJ;
    192 public:
    193   static RJ get(tuple<Head, Values...>& t) { return t.head(); }
    194   static PJ get(const tuple<Head, Values...>& t) { return t.head(); }
    195 };
    196 
    197 template<int I, typename... Values> typename add_reference<
    198 typename tuple_element<I, tuple<Values...> >::type >::type
    199 get(tuple<Values...>& t) {
    200   return get_impl<I, tuple<Values...> >::get(t);
    201 }
    202 
    203 template<int I, typename... Values> typename add_const_reference<
    204 typename tuple_element<I, tuple<Values...> >::type >::type
    205 get(const tuple<Values...>& t) {
    206   return get_impl<I, tuple<Values...> >::get(t);
    207 }
    208 
    209 void test_element_access(tuple<int*, float*, double*&> t3) {
    210   int i;
    211   float f;
    212   double d;
    213   get<0>(t3) = &i;
    214   get<1>(t3) = &f;
    215   get<2>(t3) = &d;
    216 }
    217 
    218 // Relational operators
    219 inline bool operator==(const tuple<>&, const tuple<>&) { return true; }
    220 
    221 template<typename T, typename... TTail, typename U, typename... UTail>
    222 bool operator==(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) {
    223   return t.head() == u.head() && t.tail() == u.tail();
    224 }
    225 
    226 template<typename... TValues, typename... UValues>
    227 bool operator!=(const tuple<TValues...>& t, const tuple<UValues...>& u) {
    228   return !(t == u);
    229 }
    230 
    231 inline bool operator<(const tuple<>&, const tuple<>&) { return false; }
    232 
    233 template<typename T, typename... TTail, typename U, typename... UTail>
    234 bool operator<(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) {
    235   return (t.head() < u.head() || (!(t.head() < u.head()) && t.tail() < u.tail()));
    236 }
    237 
    238 template<typename... TValues, typename... UValues>
    239 bool operator>(const tuple<TValues...>& t, const tuple<UValues...>& u) {
    240   return u < t;
    241 }
    242 
    243 template<typename... TValues, typename... UValues>
    244 bool operator<=(const tuple<TValues...>& t, const tuple<UValues...>& u) {
    245   return !(u < t);
    246 }
    247 
    248 template<typename... TValues, typename... UValues>
    249 bool operator>=(const tuple<TValues...>& t, const tuple<UValues...>& u) {
    250   return !(t < u);
    251 }
    252 
    253 void test_relational_operators(tuple<int*, float*, double*> t3) {
    254   (void)(t3 == t3);
    255   (void)(t3 != t3);
    256   (void)(t3 < t3);
    257   (void)(t3 <= t3);
    258   (void)(t3 >= t3);
    259   (void)(t3 > t3);
    260 };
    261