From 222e2a7620e6520ffaf4fc4e69d79c18da31542e Mon Sep 17 00:00:00 2001 From: "Zancanaro; Carlo" Date: Mon, 24 Sep 2012 09:58:17 +1000 Subject: Add the clang library to the repo (with some of my changes, too). --- .../temp/temp.decls/temp.variadic/example-bind.cpp | 352 +++++++++++++++++++++ 1 file changed, 352 insertions(+) create mode 100644 clang/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp (limited to 'clang/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp') diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp new file mode 100644 index 0000000..db28eea --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp @@ -0,0 +1,352 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Example bind 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; +}; + +// 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...); +} + +// Helper classes +template struct tuple_size; + +template struct tuple_size > { + static const int value = sizeof...(Values); +}; + +template struct tuple_element; + +template +struct tuple_element > { + typedef typename tuple_element >::type type; +}; + +template +struct tuple_element<0, tuple > { + typedef Head type; +}; + +// 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); +} + +// 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); +} + +// make_indices helper +template struct int_tuple {}; +// make_indexes impl is a helper for make_indexes +template struct make_indexes_impl; + +template +struct make_indexes_impl, T, Types...> { + typedef typename make_indexes_impl, Types...>::type type; +}; + +template +struct make_indexes_impl > { + typedef int_tuple type; +}; + +template +struct make_indexes : make_indexes_impl<0, int_tuple<>, Types...> { +}; + +// Bind +template struct is_bind_expression { + static const bool value = false; +}; + +template struct is_placeholder { + static const int value = 0; +}; + + +template class bound_functor { + typedef typename make_indexes::type indexes; +public: + typedef typename F::result_type result_type; + explicit bound_functor(const F& f, const BoundArgs&... bound_args) + : f(f), bound_args(bound_args...) { } template + typename F::result_type operator()(Args&... args); +private: F f; + tuple bound_args; +}; + +template +inline bound_functor bind(const F& f, const BoundArgs&... bound_args) { + return bound_functor(f, bound_args...); +} + +template +struct is_bind_expression > { + static const bool value = true; +}; + +// enable_if helper +template +struct enable_if; + +template +struct enable_if { + typedef T type; +}; + +template +struct enable_if { }; + +// safe_tuple_element helper +template +struct safe_tuple_element { }; + +template +struct safe_tuple_element, + typename enable_if<(I >= 0 && I < tuple_size >::value)>::type> { + typedef typename tuple_element >::type type; +}; + +// mu +template +inline typename safe_tuple_element::value -1, + tuple >::type +mu(Bound& bound_arg, const tuple& args) { + return get::value-1>(args); +} + +template +inline T& mu(reference_wrapper& bound_arg, const tuple&) { + return bound_arg.get(); +} + +template +inline typename F::result_type +unwrap_and_forward(F& f, int_tuple, const tuple& args) { + return f(get(args)...); +} + +template +inline typename enable_if::value, + typename Bound::result_type>::type +mu(Bound& bound_arg, const tuple& args) { + typedef typename make_indexes::type Indexes; + return unwrap_and_forward(bound_arg, Indexes(), args); +} + +template +struct is_reference_wrapper { + static const bool value = false; +}; + +template +struct is_reference_wrapper> { + static const bool value = true; +}; + +template +inline typename enable_if<(!is_bind_expression::value + && !is_placeholder::value + && !is_reference_wrapper::value), + Bound&>::type +mu(Bound& bound_arg, const tuple&) { + return bound_arg; +} + +template +typename F::result_type apply_functor(F& f, tuple& bound_args, + int_tuple, + const tuple& args) { + return f(mu(get(bound_args), args)...); +} + +template +template +typename F::result_type bound_functor::operator()(Args&... args) { + return apply_functor(f, bound_args, indexes(), tie(args...)); +} + +template struct placeholder { }; +template +struct is_placeholder> { + static const int value = N; +}; + +template +struct plus { + typedef T result_type; + + T operator()(T x, T y) { return x + y; } +}; + +placeholder<1> _1; + +// Test bind +void test_bind() { + int x = 17; + int y = 25; + bind(plus(), x, _1)(y); +} -- cgit v1.2.3