Home | History | Annotate | Download | only in temp.variadic
      1 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
      2 // expected-no-diagnostics
      3 
      4 // Example tuple implementation from the variadic templates proposal,
      5 // ISO C++ committee document number N2080.
      6 
      7 // Helper type traits
      8 template<typename T>
      9 struct add_reference {
     10   typedef T &type;
     11 };
     12 
     13 template<typename T>
     14 struct add_reference<T&> {
     15   typedef T &type;
     16 };
     17 
     18 template<typename T>
     19 struct add_const_reference {
     20   typedef T const &type;
     21 };
     22 
     23 template<typename T>
     24 struct add_const_reference<T&> {
     25   typedef T &type;
     26 };
     27 
     28 template<typename T, typename U>
     29 struct is_same {
     30   static const bool value = false;
     31 };
     32 
     33 template<typename T>
     34 struct is_same<T, T> {
     35   static const bool value = true;
     36 };
     37 
     38 template<typename T>
     39 class reference_wrapper {
     40   T *ptr;
     41 
     42 public:
     43   reference_wrapper(T& t) : ptr(&t) { }
     44   operator T&() const { return *ptr; }
     45 };
     46 
     47 template<typename T> reference_wrapper<T> ref(T& t) {
     48   return reference_wrapper<T>(t);
     49 }
     50 template<typename T> reference_wrapper<const T> cref(const T& t) {
     51   return reference_wrapper<const T>(t);
     52 }
     53 
     54 template<typename... Values> class tuple;
     55 
     56 // Basis case: zero-length tuple
     57 template<> class tuple<> { };
     58 
     59 template<typename Head, typename... Tail>
     60 class tuple<Head, Tail...> : private tuple<Tail...> {
     61   typedef tuple<Tail...> inherited;
     62 
     63 public:
     64   tuple() { }
     65   // implicit copy-constructor is okay
     66 
     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...) { }
     71 
     72   // Construct tuple from another tuple.
     73   template<typename... VValues> tuple(const tuple<VValues...>& other)
     74     : m_head(other.head()), inherited(other.tail()) { }
     75 
     76   template<typename... VValues> tuple&
     77   operator=(const tuple<VValues...>& other) {
     78     m_head = other.head();
     79     tail() = other.tail();
     80     return *this;
     81   }
     82 
     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; }
     87 
     88 protected:
     89   Head m_head;
     90 };
     91 
     92 void test_tuple() {
     93   tuple<> t0a;
     94   tuple<> t0b(t0a);
     95   t0a = t0b;
     96 
     97   tuple<int> t1a;
     98   tuple<int> t1b(17);
     99   tuple<int> t1c(t1b);
    100   t1a = t1b;
    101 
    102   tuple<float> t1d(3.14159);
    103   tuple<float> t1e(t1d);
    104   t1d = t1e;
    105 
    106   int i;
    107   float f;
    108   double d;
    109   tuple<int*, float*, double*> t3a(&i, &f, &d);
    110 }
    111 
    112 // Creation functions
    113 template<typename T>
    114 struct make_tuple_result {
    115   typedef T type;
    116 };
    117 
    118 template<typename T>
    119 struct make_tuple_result<reference_wrapper<T> > {
    120   typedef T& type;
    121 };
    122 
    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...);
    127 }
    128 
    129 template<typename... Values>
    130 tuple<Values&...> tie(Values&... values) {
    131   return tuple<Values&...>(values...);
    132 }
    133 
    134 template<typename T> const T *addr(const T& ref) { return &ref; }
    135 void test_creation_functions() {
    136   int i;
    137   float f;
    138   double d;
    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));
    141 }
    142 
    143 // Helper classes
    144 template<typename Tuple> struct tuple_size;
    145 
    146 template<typename... Values> struct tuple_size<tuple<Values...> > {
    147   static const int value = sizeof...(Values);
    148 };
    149 
    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];
    154 
    155 template<int I, typename Tuple> struct tuple_element;
    156 
    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;
    160 };
    161 
    162 template<typename Head, typename... Tail>
    163 struct tuple_element<0, tuple<Head, Tail...> > {
    164   typedef Head type;
    165 };
    166 
    167 int check_tuple_element_0[is_same<tuple_element<0, tuple<int&, float, double>>::type,
    168                                   int&>::value? 1 : -1];
    169 
    170 int check_tuple_element_1[is_same<tuple_element<1, tuple<int&, float, double>>::type,
    171                                   float>::value? 1 : -1];
    172 
    173 int check_tuple_element_2[is_same<tuple_element<2, tuple<int&, float, double>>::type,
    174                                   double>::value? 1 : -1];
    175 
    176 // Element access
    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;
    184 public:
    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()); }
    187 };
    188 
    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;
    193 public:
    194   static RJ get(tuple<Head, Values...>& t) { return t.head(); }
    195   static PJ get(const tuple<Head, Values...>& t) { return t.head(); }
    196 };
    197 
    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);
    202 }
    203 
    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);
    208 }
    209 
    210 void test_element_access(tuple<int*, float*, double*&> t3) {
    211   int i;
    212   float f;
    213   double d;
    214   get<0>(t3) = &i;
    215   get<1>(t3) = &f;
    216   get<2>(t3) = &d;
    217 }
    218 
    219 // Relational operators
    220 inline bool operator==(const tuple<>&, const tuple<>&) { return true; }
    221 
    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();
    225 }
    226 
    227 template<typename... TValues, typename... UValues>
    228 bool operator!=(const tuple<TValues...>& t, const tuple<UValues...>& u) {
    229   return !(t == u);
    230 }
    231 
    232 inline bool operator<(const tuple<>&, const tuple<>&) { return false; }
    233 
    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()));
    237 }
    238 
    239 template<typename... TValues, typename... UValues>
    240 bool operator>(const tuple<TValues...>& t, const tuple<UValues...>& u) {
    241   return u < t;
    242 }
    243 
    244 template<typename... TValues, typename... UValues>
    245 bool operator<=(const tuple<TValues...>& t, const tuple<UValues...>& u) {
    246   return !(u < t);
    247 }
    248 
    249 template<typename... TValues, typename... UValues>
    250 bool operator>=(const tuple<TValues...>& t, const tuple<UValues...>& u) {
    251   return !(t < u);
    252 }
    253 
    254 void test_relational_operators(tuple<int*, float*, double*> t3) {
    255   (void)(t3 == t3);
    256   (void)(t3 != t3);
    257   (void)(t3 < t3);
    258   (void)(t3 <= t3);
    259   (void)(t3 >= t3);
    260   (void)(t3 > t3);
    261 };
    262