// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s // expected-no-diagnostics // Example tuple implementation from the variadic templates proposal, // ISO C++ committee document number N2080. // Helper type traits template struct add_reference { typedef T &type; }; template struct add_reference { typedef T &type; }; template struct add_const_reference { typedef T const &type; }; template struct add_const_reference { typedef T &type; }; template struct is_same { static const bool value = false; }; template struct is_same { static const bool value = true; }; template class reference_wrapper { T *ptr; public: reference_wrapper(T& t) : ptr(&t) { } operator T&() const { return *ptr; } }; template reference_wrapper ref(T& t) { return reference_wrapper(t); } template reference_wrapper cref(const T& t) { return reference_wrapper(t); } template class tuple; // Basis case: zero-length tuple template<> class tuple<> { }; template class tuple : private tuple { typedef tuple inherited; public: tuple() { } // implicit copy-constructor is okay // Construct tuple from separate arguments. tuple(typename add_const_reference::type v, typename add_const_reference::type... vtail) : m_head(v), inherited(vtail...) { } // Construct tuple from another tuple. template tuple(const tuple& other) : m_head(other.head()), inherited(other.tail()) { } template tuple& operator=(const tuple& other) { m_head = other.head(); tail() = other.tail(); return *this; } typename add_reference::type head() { return m_head; } typename add_reference::type head() const { return m_head; } inherited& tail() { return *this; } const inherited& tail() const { return *this; } protected: Head m_head; }; void test_tuple() { tuple<> t0a; tuple<> t0b(t0a); t0a = t0b; tuple t1a; tuple t1b(17); tuple t1c(t1b); t1a = t1b; tuple t1d(3.14159); tuple t1e(t1d); t1d = t1e; int i; float f; double d; tuple t3a(&i, &f, &d); } // Creation functions template struct make_tuple_result { typedef T type; }; template struct make_tuple_result > { typedef T& type; }; template tuple::type...> make_tuple(const Values&... values) { return tuple::type...>(values...); } template tuple tie(Values&... values) { return tuple(values...); } template const T *addr(const T& ref) { return &ref; } void test_creation_functions() { int i; float f; double d; const tuple *t3p = addr(make_tuple(i, ref(f), cref(d))); const tuple *t3q = addr(tie(i, f, d)); } // Helper classes template struct tuple_size; template struct tuple_size > { static const int value = sizeof...(Values); }; int check_tuple_size_0[tuple_size >::value == 0? 1 : -1]; int check_tuple_size_1[tuple_size>::value == 1? 1 : -1]; int check_tuple_size_2[tuple_size>::value == 2? 1 : -1]; int check_tuple_size_3[tuple_size>::value == 3? 1 : -1]; template struct tuple_element; template struct tuple_element > { typedef typename tuple_element >::type type; }; template struct tuple_element<0, tuple > { typedef Head type; }; int check_tuple_element_0[is_same>::type, int&>::value? 1 : -1]; int check_tuple_element_1[is_same>::type, float>::value? 1 : -1]; int check_tuple_element_2[is_same>::type, double>::value? 1 : -1]; // Element access template class get_impl; template class get_impl > { typedef typename tuple_element >::type Element; typedef typename add_reference::type RJ; typedef typename add_const_reference::type PJ; typedef get_impl > Next; public: static RJ get(tuple& t) { return Next::get(t.tail()); } static PJ get(const tuple& t) { return Next::get(t.tail()); } }; template class get_impl<0, tuple > { typedef typename add_reference::type RJ; typedef typename add_const_reference::type PJ; public: static RJ get(tuple& t) { return t.head(); } static PJ get(const tuple& t) { return t.head(); } }; template typename add_reference< typename tuple_element >::type >::type get(tuple& t) { return get_impl >::get(t); } template typename add_const_reference< typename tuple_element >::type >::type get(const tuple& t) { return get_impl >::get(t); } void test_element_access(tuple t3) { int i; float f; double d; get<0>(t3) = &i; get<1>(t3) = &f; get<2>(t3) = &d; } // Relational operators inline bool operator==(const tuple<>&, const tuple<>&) { return true; } template bool operator==(const tuple& t, const tuple& u) { return t.head() == u.head() && t.tail() == u.tail(); } template bool operator!=(const tuple& t, const tuple& u) { return !(t == u); } inline bool operator<(const tuple<>&, const tuple<>&) { return false; } template bool operator<(const tuple& t, const tuple& u) { return (t.head() < u.head() || (!(t.head() < u.head()) && t.tail() < u.tail())); } template bool operator>(const tuple& t, const tuple& u) { return u < t; } template bool operator<=(const tuple& t, const tuple& u) { return !(u < t); } template bool operator>=(const tuple& t, const tuple& u) { return !(t < u); } void test_relational_operators(tuple t3) { (void)(t3 == t3); (void)(t3 != t3); (void)(t3 < t3); (void)(t3 <= t3); (void)(t3 >= t3); (void)(t3 > t3); };