diff options
author | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
---|---|---|
committer | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
commit | 222e2a7620e6520ffaf4fc4e69d79c18da31542e (patch) | |
tree | 7bfbc05bfa3b41c8f9d2e56d53a0bc3e310df239 /clang/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp | |
parent | 3d206f03985b50beacae843d880bccdc91a9f424 (diff) |
Add the clang library to the repo (with some of my changes, too).
Diffstat (limited to 'clang/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp')
-rw-r--r-- | clang/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp new file mode 100644 index 0000000..9de5fa8 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp @@ -0,0 +1,260 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Example tuple implementation from the variadic templates proposal, +// ISO C++ committee document number N2080. + +// Helper type traits +template<typename T> +struct add_reference { + typedef T &type; +}; + +template<typename T> +struct add_reference<T&> { + typedef T &type; +}; + +template<typename T> +struct add_const_reference { + typedef T const &type; +}; + +template<typename T> +struct add_const_reference<T&> { + typedef T &type; +}; + +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +template<typename T> +class reference_wrapper { + T *ptr; + +public: + reference_wrapper(T& t) : ptr(&t) { } + operator T&() const { return *ptr; } +}; + +template<typename T> reference_wrapper<T> ref(T& t) { + return reference_wrapper<T>(t); +} +template<typename T> reference_wrapper<const T> cref(const T& t) { + return reference_wrapper<const T>(t); +} + +template<typename... Values> class tuple; + +// Basis case: zero-length tuple +template<> class tuple<> { }; + +template<typename Head, typename... Tail> +class tuple<Head, Tail...> : private tuple<Tail...> { + typedef tuple<Tail...> inherited; + +public: + tuple() { } + // implicit copy-constructor is okay + + // Construct tuple from separate arguments. + tuple(typename add_const_reference<Head>::type v, + typename add_const_reference<Tail>::type... vtail) + : m_head(v), inherited(vtail...) { } + + // Construct tuple from another tuple. + template<typename... VValues> tuple(const tuple<VValues...>& other) + : m_head(other.head()), inherited(other.tail()) { } + + template<typename... VValues> tuple& + operator=(const tuple<VValues...>& other) { + m_head = other.head(); + tail() = other.tail(); + return *this; + } + + typename add_reference<Head>::type head() { return m_head; } + typename add_reference<const Head>::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<int> t1a; + tuple<int> t1b(17); + tuple<int> t1c(t1b); + t1a = t1b; + + tuple<float> t1d(3.14159); + tuple<float> t1e(t1d); + t1d = t1e; + + int i; + float f; + double d; + tuple<int*, float*, double*> t3a(&i, &f, &d); +} + +// Creation functions +template<typename T> +struct make_tuple_result { + typedef T type; +}; + +template<typename T> +struct make_tuple_result<reference_wrapper<T> > { + typedef T& type; +}; + +template<typename... Values> +tuple<typename make_tuple_result<Values>::type...> +make_tuple(const Values&... values) { + return tuple<typename make_tuple_result<Values>::type...>(values...); +} + +template<typename... Values> +tuple<Values&...> tie(Values&... values) { + return tuple<Values&...>(values...); +} + +template<typename T> const T *addr(const T& ref) { return &ref; } +void test_creation_functions() { + int i; + float f; + double d; + const tuple<int, float&, const double&> *t3p = addr(make_tuple(i, ref(f), cref(d))); + const tuple<int&, float&, double&> *t3q = addr(tie(i, f, d)); +} + +// Helper classes +template<typename Tuple> struct tuple_size; + +template<typename... Values> struct tuple_size<tuple<Values...> > { + static const int value = sizeof...(Values); +}; + +int check_tuple_size_0[tuple_size<tuple<> >::value == 0? 1 : -1]; +int check_tuple_size_1[tuple_size<tuple<int>>::value == 1? 1 : -1]; +int check_tuple_size_2[tuple_size<tuple<float, double>>::value == 2? 1 : -1]; +int check_tuple_size_3[tuple_size<tuple<char, unsigned char, signed char>>::value == 3? 1 : -1]; + +template<int I, typename Tuple> struct tuple_element; + +template<int I, typename Head, typename... Tail> +struct tuple_element<I, tuple<Head, Tail...> > { + typedef typename tuple_element<I-1, tuple<Tail...> >::type type; +}; + +template<typename Head, typename... Tail> +struct tuple_element<0, tuple<Head, Tail...> > { + typedef Head type; +}; + +int check_tuple_element_0[is_same<tuple_element<0, tuple<int&, float, double>>::type, + int&>::value? 1 : -1]; + +int check_tuple_element_1[is_same<tuple_element<1, tuple<int&, float, double>>::type, + float>::value? 1 : -1]; + +int check_tuple_element_2[is_same<tuple_element<2, tuple<int&, float, double>>::type, + double>::value? 1 : -1]; + +// Element access +template<int I, typename Tuple> class get_impl; +template<int I, typename Head, typename... Values> +class get_impl<I, tuple<Head, Values...> > { + typedef typename tuple_element<I-1, tuple<Values...> >::type Element; + typedef typename add_reference<Element>::type RJ; + typedef typename add_const_reference<Element>::type PJ; + typedef get_impl<I-1, tuple<Values...> > Next; +public: + static RJ get(tuple<Head, Values...>& t) { return Next::get(t.tail()); } + static PJ get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); } +}; + +template<typename Head, typename... Values> +class get_impl<0, tuple<Head, Values...> > { + typedef typename add_reference<Head>::type RJ; + typedef typename add_const_reference<Head>::type PJ; +public: + static RJ get(tuple<Head, Values...>& t) { return t.head(); } + static PJ get(const tuple<Head, Values...>& t) { return t.head(); } +}; + +template<int I, typename... Values> typename add_reference< +typename tuple_element<I, tuple<Values...> >::type >::type +get(tuple<Values...>& t) { + return get_impl<I, tuple<Values...> >::get(t); +} + +template<int I, typename... Values> typename add_const_reference< +typename tuple_element<I, tuple<Values...> >::type >::type +get(const tuple<Values...>& t) { + return get_impl<I, tuple<Values...> >::get(t); +} + +void test_element_access(tuple<int*, float*, double*&> 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<typename T, typename... TTail, typename U, typename... UTail> +bool operator==(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) { + return t.head() == u.head() && t.tail() == u.tail(); +} + +template<typename... TValues, typename... UValues> +bool operator!=(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return !(t == u); +} + +inline bool operator<(const tuple<>&, const tuple<>&) { return false; } + +template<typename T, typename... TTail, typename U, typename... UTail> +bool operator<(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) { + return (t.head() < u.head() || (!(t.head() < u.head()) && t.tail() < u.tail())); +} + +template<typename... TValues, typename... UValues> +bool operator>(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return u < t; +} + +template<typename... TValues, typename... UValues> +bool operator<=(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return !(u < t); +} + +template<typename... TValues, typename... UValues> +bool operator>=(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return !(t < u); +} + +void test_relational_operators(tuple<int*, float*, double*> t3) { + (void)(t3 == t3); + (void)(t3 != t3); + (void)(t3 < t3); + (void)(t3 <= t3); + (void)(t3 >= t3); + (void)(t3 > t3); +}; |