williamr@2: // tuple_basic.hpp ----------------------------------------------------- williamr@2: williamr@2: // Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi) williamr@2: // williamr@2: // Distributed under the Boost Software License, Version 1.0. (See williamr@2: // accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: williamr@2: // For more information, see http://www.boost.org williamr@2: williamr@2: // Outside help: williamr@2: // This and that, Gary Powell. williamr@2: // Fixed return types for get_head/get_tail williamr@2: // ( and other bugs ) per suggestion of Jens Maurer williamr@2: // simplified element type accessors + bug fix (Jeremy Siek) williamr@2: // Several changes/additions according to suggestions by Douglas Gregor, williamr@2: // William Kempf, Vesa Karvonen, John Max Skaller, Ed Brey, Beman Dawes, williamr@2: // David Abrahams. williamr@2: williamr@2: // Revision history: williamr@2: // 2002 05 01 Hugo Duncan: Fix for Borland after Jaakko's previous changes williamr@2: // 2002 04 18 Jaakko: tuple element types can be void or plain function williamr@2: // types, as long as no object is created. williamr@2: // Tuple objects can no hold even noncopyable types williamr@2: // such as arrays. williamr@2: // 2001 10 22 John Maddock williamr@2: // Fixes for Borland C++ williamr@2: // 2001 08 30 David Abrahams williamr@2: // Added default constructor for cons<>. williamr@2: // ----------------------------------------------------------------- williamr@2: williamr@2: #ifndef BOOST_TUPLE_BASIC_HPP williamr@2: #define BOOST_TUPLE_BASIC_HPP williamr@2: williamr@2: williamr@2: #include // needed for the assignment from pair to tuple williamr@2: williamr@2: #include "boost/type_traits/cv_traits.hpp" williamr@2: #include "boost/type_traits/function_traits.hpp" williamr@2: williamr@2: #include "boost/detail/workaround.hpp" // needed for BOOST_WORKAROUND williamr@2: williamr@2: namespace boost { williamr@2: namespace tuples { williamr@2: williamr@2: // -- null_type -------------------------------------------------------- williamr@2: struct null_type {}; williamr@2: williamr@2: // a helper function to provide a const null_type type temporary williamr@2: namespace detail { williamr@2: inline const null_type cnull() { return null_type(); } williamr@2: williamr@2: williamr@2: // -- if construct ------------------------------------------------ williamr@2: // Proposed by Krzysztof Czarnecki and Ulrich Eisenecker williamr@2: williamr@2: template struct IF { typedef Then RET; }; williamr@2: williamr@2: template struct IF { williamr@2: typedef Else RET; williamr@2: }; williamr@2: williamr@2: } // end detail williamr@2: williamr@2: // - cons forward declaration ----------------------------------------------- williamr@2: template struct cons; williamr@2: williamr@2: williamr@2: // - tuple forward declaration ----------------------------------------------- williamr@2: template < williamr@2: class T0 = null_type, class T1 = null_type, class T2 = null_type, williamr@2: class T3 = null_type, class T4 = null_type, class T5 = null_type, williamr@2: class T6 = null_type, class T7 = null_type, class T8 = null_type, williamr@2: class T9 = null_type> williamr@2: class tuple; williamr@2: williamr@2: // tuple_length forward declaration williamr@2: template struct length; williamr@2: williamr@2: williamr@2: williamr@2: namespace detail { williamr@2: williamr@2: // -- generate error template, referencing to non-existing members of this williamr@2: // template is used to produce compilation errors intentionally williamr@2: template williamr@2: class generate_error; williamr@2: williamr@2: // - cons getters -------------------------------------------------------- williamr@2: // called: get_class::get(aTuple) williamr@2: williamr@2: template< int N > williamr@2: struct get_class { williamr@2: template williamr@2: inline static RET get(const cons& t) williamr@2: { williamr@2: #if BOOST_WORKAROUND(__IBMCPP__,==600) williamr@2: // vacpp 6.0 is not very consistent regarding the member template keyword williamr@2: // Here it generates an error when the template keyword is used. williamr@2: return get_class::get(t.tail); williamr@2: #else williamr@2: return get_class::BOOST_NESTED_TEMPLATE get(t.tail); williamr@2: #endif williamr@2: } williamr@2: template williamr@2: inline static RET get(cons& t) williamr@2: { williamr@2: #if BOOST_WORKAROUND(__IBMCPP__,==600) williamr@2: return get_class::get(t.tail); williamr@2: #else williamr@2: return get_class::BOOST_NESTED_TEMPLATE get(t.tail); williamr@2: #endif williamr@2: } williamr@2: }; williamr@2: williamr@2: template<> williamr@2: struct get_class<0> { williamr@2: template williamr@2: inline static RET get(const cons& t) williamr@2: { williamr@2: return t.head; williamr@2: } williamr@2: template williamr@2: inline static RET get(cons& t) williamr@2: { williamr@2: return t.head; williamr@2: } williamr@2: }; williamr@2: williamr@2: } // end of namespace detail williamr@2: williamr@2: williamr@2: // -cons type accessors ---------------------------------------- williamr@2: // typename tuples::element::type gets the type of the williamr@2: // Nth element ot T, first element is at index 0 williamr@2: // ------------------------------------------------------- williamr@2: williamr@2: #ifndef BOOST_NO_CV_SPECIALIZATIONS williamr@2: williamr@2: template williamr@2: struct element williamr@2: { williamr@2: private: williamr@2: typedef typename T::tail_type Next; williamr@2: public: williamr@2: typedef typename element::type type; williamr@2: }; williamr@2: template williamr@2: struct element<0,T> williamr@2: { williamr@2: typedef typename T::head_type type; williamr@2: }; williamr@2: williamr@2: template williamr@2: struct element williamr@2: { williamr@2: private: williamr@2: typedef typename T::tail_type Next; williamr@2: typedef typename element::type unqualified_type; williamr@2: public: williamr@2: #if BOOST_WORKAROUND(__BORLANDC__,<0x600) williamr@2: typedef const unqualified_type type; williamr@2: #else williamr@2: typedef typename boost::add_const::type type; williamr@2: #endif williamr@2: williamr@2: }; williamr@2: template williamr@2: struct element<0,const T> williamr@2: { williamr@2: #if BOOST_WORKAROUND(__BORLANDC__,<0x600) williamr@2: typedef const typename T::head_type type; williamr@2: #else williamr@2: typedef typename boost::add_const::type type; williamr@2: #endif williamr@2: }; williamr@2: williamr@2: #else // def BOOST_NO_CV_SPECIALIZATIONS williamr@2: williamr@2: namespace detail { williamr@2: williamr@2: template williamr@2: struct element_impl williamr@2: { williamr@2: private: williamr@2: typedef typename T::tail_type Next; williamr@2: public: williamr@2: typedef typename element_impl::type type; williamr@2: }; williamr@2: williamr@2: template williamr@2: struct element_impl williamr@2: { williamr@2: private: williamr@2: typedef typename T::tail_type Next; williamr@2: public: williamr@2: typedef const typename element_impl::type type; williamr@2: }; williamr@2: williamr@2: template williamr@2: struct element_impl<0, T, false /* IsConst */> williamr@2: { williamr@2: typedef typename T::head_type type; williamr@2: }; williamr@2: williamr@2: template williamr@2: struct element_impl<0, T, true /* IsConst */> williamr@2: { williamr@2: typedef const typename T::head_type type; williamr@2: }; williamr@2: williamr@2: } // end of namespace detail williamr@2: williamr@2: williamr@2: template williamr@2: struct element: williamr@2: public detail::element_impl::value> williamr@2: { williamr@2: }; williamr@2: williamr@2: #endif williamr@2: williamr@2: williamr@2: // -get function templates ----------------------------------------------- williamr@2: // Usage: get(aTuple) williamr@2: williamr@2: // -- some traits classes for get functions williamr@2: williamr@2: // access traits lifted from detail namespace to be part of the interface, williamr@2: // (Joel de Guzman's suggestion). Rationale: get functions are part of the williamr@2: // interface, so should the way to express their return types be. williamr@2: williamr@2: template struct access_traits { williamr@2: typedef const T& const_type; williamr@2: typedef T& non_const_type; williamr@2: williamr@2: typedef const typename boost::remove_cv::type& parameter_type; williamr@2: williamr@2: // used as the tuple constructors parameter types williamr@2: // Rationale: non-reference tuple element types can be cv-qualified. williamr@2: // It should be possible to initialize such types with temporaries, williamr@2: // and when binding temporaries to references, the reference must williamr@2: // be non-volatile and const. 8.5.3. (5) williamr@2: }; williamr@2: williamr@2: template struct access_traits { williamr@2: williamr@2: typedef T& const_type; williamr@2: typedef T& non_const_type; williamr@2: williamr@2: typedef T& parameter_type; williamr@2: }; williamr@2: williamr@2: // get function for non-const cons-lists, returns a reference to the element williamr@2: williamr@2: template williamr@2: inline typename access_traits< williamr@2: typename element >::type williamr@2: >::non_const_type williamr@2: get(cons& c BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int, N)) { williamr@2: #if BOOST_WORKAROUND(__IBMCPP__,==600 ) williamr@2: return detail::get_class:: williamr@2: #else williamr@2: return detail::get_class::BOOST_NESTED_TEMPLATE williamr@2: #endif williamr@2: get< williamr@2: typename access_traits< williamr@2: typename element >::type williamr@2: >::non_const_type, williamr@2: HT,TT williamr@2: >(c); williamr@2: } williamr@2: williamr@2: // get function for const cons-lists, returns a const reference to williamr@2: // the element. If the element is a reference, returns the reference williamr@2: // as such (that is, can return a non-const reference) williamr@2: template williamr@2: inline typename access_traits< williamr@2: typename element >::type williamr@2: >::const_type williamr@2: get(const cons& c BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int, N)) { williamr@2: #if BOOST_WORKAROUND(__IBMCPP__,==600) williamr@2: return detail::get_class:: williamr@2: #else williamr@2: return detail::get_class::BOOST_NESTED_TEMPLATE williamr@2: #endif williamr@2: get< williamr@2: typename access_traits< williamr@2: typename element >::type williamr@2: >::const_type, williamr@2: HT,TT williamr@2: >(c); williamr@2: } williamr@2: williamr@2: // -- the cons template -------------------------------------------------- williamr@2: namespace detail { williamr@2: williamr@2: // These helper templates wrap void types and plain function types. williamr@2: // The reationale is to allow one to write tuple types with those types williamr@2: // as elements, even though it is not possible to instantiate such object. williamr@2: // E.g: typedef tuple some_type; // ok williamr@2: // but: some_type x; // fails williamr@2: williamr@2: template class non_storeable_type { williamr@2: non_storeable_type(); williamr@2: }; williamr@2: williamr@2: template struct wrap_non_storeable_type { williamr@2: typedef typename IF< williamr@2: ::boost::is_function::value, non_storeable_type, T williamr@2: >::RET type; williamr@2: }; williamr@2: template <> struct wrap_non_storeable_type { williamr@2: typedef non_storeable_type type; williamr@2: }; williamr@2: williamr@2: } // detail williamr@2: williamr@2: template williamr@2: struct cons { williamr@2: williamr@2: typedef HT head_type; williamr@2: typedef TT tail_type; williamr@2: williamr@2: typedef typename williamr@2: detail::wrap_non_storeable_type::type stored_head_type; williamr@2: williamr@2: stored_head_type head; williamr@2: tail_type tail; williamr@2: williamr@2: typename access_traits::non_const_type williamr@2: get_head() { return head; } williamr@2: williamr@2: typename access_traits::non_const_type williamr@2: get_tail() { return tail; } williamr@2: williamr@2: typename access_traits::const_type williamr@2: get_head() const { return head; } williamr@2: williamr@2: typename access_traits::const_type williamr@2: get_tail() const { return tail; } williamr@2: williamr@2: cons() : head(), tail() {} williamr@2: // cons() : head(detail::default_arg::f()), tail() {} williamr@2: williamr@2: // the argument for head is not strictly needed, but it prevents williamr@2: // array type elements. This is good, since array type elements williamr@2: // cannot be supported properly in any case (no assignment, williamr@2: // copy works only if the tails are exactly the same type, ...) williamr@2: williamr@2: cons(typename access_traits::parameter_type h, williamr@2: const tail_type& t) williamr@2: : head (h), tail(t) {} williamr@2: williamr@2: template williamr@2: cons( T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, williamr@2: T6& t6, T7& t7, T8& t8, T9& t9, T10& t10 ) williamr@2: : head (t1), williamr@2: tail (t2, t3, t4, t5, t6, t7, t8, t9, t10, detail::cnull()) williamr@2: {} williamr@2: williamr@2: template williamr@2: cons( const null_type& /*t1*/, T2& t2, T3& t3, T4& t4, T5& t5, williamr@2: T6& t6, T7& t7, T8& t8, T9& t9, T10& t10 ) williamr@2: : head (), williamr@2: tail (t2, t3, t4, t5, t6, t7, t8, t9, t10, detail::cnull()) williamr@2: {} williamr@2: williamr@2: williamr@2: template williamr@2: cons( const cons& u ) : head(u.head), tail(u.tail) {} williamr@2: williamr@2: template williamr@2: cons& operator=( const cons& u ) { williamr@2: head=u.head; tail=u.tail; return *this; williamr@2: } williamr@2: williamr@2: // must define assignment operator explicitly, implicit version is williamr@2: // illformed if HT is a reference (12.8. (12)) williamr@2: cons& operator=(const cons& u) { williamr@2: head = u.head; tail = u.tail; return *this; williamr@2: } williamr@2: williamr@2: template williamr@2: cons& operator=( const std::pair& u ) { williamr@2: BOOST_STATIC_ASSERT(length::value == 2); // check length = 2 williamr@2: head = u.first; tail.head = u.second; return *this; williamr@2: } williamr@2: williamr@2: // get member functions (non-const and const) williamr@2: template williamr@2: typename access_traits< williamr@2: typename element >::type williamr@2: >::non_const_type williamr@2: get() { williamr@2: return boost::tuples::get(*this); // delegate to non-member get williamr@2: } williamr@2: williamr@2: template williamr@2: typename access_traits< williamr@2: typename element >::type williamr@2: >::const_type williamr@2: get() const { williamr@2: return boost::tuples::get(*this); // delegate to non-member get williamr@2: } williamr@2: }; williamr@2: williamr@2: template williamr@2: struct cons { williamr@2: williamr@2: typedef HT head_type; williamr@2: typedef null_type tail_type; williamr@2: typedef cons self_type; williamr@2: williamr@2: typedef typename williamr@2: detail::wrap_non_storeable_type::type stored_head_type; williamr@2: stored_head_type head; williamr@2: williamr@2: typename access_traits::non_const_type williamr@2: get_head() { return head; } williamr@2: williamr@2: null_type get_tail() { return null_type(); } williamr@2: williamr@2: typename access_traits::const_type williamr@2: get_head() const { return head; } williamr@2: williamr@2: const null_type get_tail() const { return null_type(); } williamr@2: williamr@2: // cons() : head(detail::default_arg::f()) {} williamr@2: cons() : head() {} williamr@2: williamr@2: cons(typename access_traits::parameter_type h, williamr@2: const null_type& = null_type()) williamr@2: : head (h) {} williamr@2: williamr@2: template williamr@2: cons(T1& t1, const null_type&, const null_type&, const null_type&, williamr@2: const null_type&, const null_type&, const null_type&, williamr@2: const null_type&, const null_type&, const null_type&) williamr@2: : head (t1) {} williamr@2: williamr@2: cons(const null_type&, williamr@2: const null_type&, const null_type&, const null_type&, williamr@2: const null_type&, const null_type&, const null_type&, williamr@2: const null_type&, const null_type&, const null_type&) williamr@2: : head () {} williamr@2: williamr@2: template williamr@2: cons( const cons& u ) : head(u.head) {} williamr@2: williamr@2: template williamr@2: cons& operator=(const cons& u ) williamr@2: { head = u.head; return *this; } williamr@2: williamr@2: // must define assignment operator explicitely, implicit version williamr@2: // is illformed if HT is a reference williamr@2: cons& operator=(const cons& u) { head = u.head; return *this; } williamr@2: williamr@2: template williamr@2: typename access_traits< williamr@2: typename element::type williamr@2: >::non_const_type williamr@2: get(BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int, N)) { williamr@2: return boost::tuples::get(*this); williamr@2: } williamr@2: williamr@2: template williamr@2: typename access_traits< williamr@2: typename element::type williamr@2: >::const_type williamr@2: get(BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int, N)) const { williamr@2: return boost::tuples::get(*this); williamr@2: } williamr@2: williamr@2: }; williamr@2: williamr@2: // templates for finding out the length of the tuple ------------------- williamr@2: williamr@2: template williamr@2: struct length { williamr@2: BOOST_STATIC_CONSTANT(int, value = 1 + length::value); williamr@2: }; williamr@2: williamr@2: template<> williamr@2: struct length > { williamr@2: BOOST_STATIC_CONSTANT(int, value = 0); williamr@2: }; williamr@2: williamr@2: template<> williamr@2: struct length { williamr@2: BOOST_STATIC_CONSTANT(int, value = 0); williamr@2: }; williamr@2: williamr@2: williamr@2: namespace detail { williamr@2: williamr@2: // Tuple to cons mapper -------------------------------------------------- williamr@2: template williamr@2: struct map_tuple_to_cons williamr@2: { williamr@2: typedef cons::type williamr@2: > type; williamr@2: }; williamr@2: williamr@2: // The empty tuple is a null_type williamr@2: template <> williamr@2: struct map_tuple_to_cons williamr@2: { williamr@2: typedef null_type type; williamr@2: }; williamr@2: williamr@2: } // end detail williamr@2: williamr@2: // ------------------------------------------------------------------- williamr@2: // -- tuple ------------------------------------------------------ williamr@2: template williamr@2: williamr@2: class tuple : williamr@2: public detail::map_tuple_to_cons::type williamr@2: { williamr@2: public: williamr@2: typedef typename williamr@2: detail::map_tuple_to_cons::type inherited; williamr@2: typedef typename inherited::head_type head_type; williamr@2: typedef typename inherited::tail_type tail_type; williamr@2: williamr@2: williamr@2: // access_traits::parameter_type takes non-reference types as const T& williamr@2: tuple() {} williamr@2: williamr@2: tuple(typename access_traits::parameter_type t0) williamr@2: : inherited(t0, detail::cnull(), detail::cnull(), detail::cnull(), williamr@2: detail::cnull(), detail::cnull(), detail::cnull(), williamr@2: detail::cnull(), detail::cnull(), detail::cnull()) {} williamr@2: williamr@2: tuple(typename access_traits::parameter_type t0, williamr@2: typename access_traits::parameter_type t1) williamr@2: : inherited(t0, t1, detail::cnull(), detail::cnull(), williamr@2: detail::cnull(), detail::cnull(), detail::cnull(), williamr@2: detail::cnull(), detail::cnull(), detail::cnull()) {} williamr@2: williamr@2: tuple(typename access_traits::parameter_type t0, williamr@2: typename access_traits::parameter_type t1, williamr@2: typename access_traits::parameter_type t2) williamr@2: : inherited(t0, t1, t2, detail::cnull(), detail::cnull(), williamr@2: detail::cnull(), detail::cnull(), detail::cnull(), williamr@2: detail::cnull(), detail::cnull()) {} williamr@2: williamr@2: tuple(typename access_traits::parameter_type t0, williamr@2: typename access_traits::parameter_type t1, williamr@2: typename access_traits::parameter_type t2, williamr@2: typename access_traits::parameter_type t3) williamr@2: : inherited(t0, t1, t2, t3, detail::cnull(), detail::cnull(), williamr@2: detail::cnull(), detail::cnull(), detail::cnull(), williamr@2: detail::cnull()) {} williamr@2: williamr@2: tuple(typename access_traits::parameter_type t0, williamr@2: typename access_traits::parameter_type t1, williamr@2: typename access_traits::parameter_type t2, williamr@2: typename access_traits::parameter_type t3, williamr@2: typename access_traits::parameter_type t4) williamr@2: : inherited(t0, t1, t2, t3, t4, detail::cnull(), detail::cnull(), williamr@2: detail::cnull(), detail::cnull(), detail::cnull()) {} williamr@2: williamr@2: tuple(typename access_traits::parameter_type t0, williamr@2: typename access_traits::parameter_type t1, williamr@2: typename access_traits::parameter_type t2, williamr@2: typename access_traits::parameter_type t3, williamr@2: typename access_traits::parameter_type t4, williamr@2: typename access_traits::parameter_type t5) williamr@2: : inherited(t0, t1, t2, t3, t4, t5, detail::cnull(), detail::cnull(), williamr@2: detail::cnull(), detail::cnull()) {} williamr@2: williamr@2: tuple(typename access_traits::parameter_type t0, williamr@2: typename access_traits::parameter_type t1, williamr@2: typename access_traits::parameter_type t2, williamr@2: typename access_traits::parameter_type t3, williamr@2: typename access_traits::parameter_type t4, williamr@2: typename access_traits::parameter_type t5, williamr@2: typename access_traits::parameter_type t6) williamr@2: : inherited(t0, t1, t2, t3, t4, t5, t6, detail::cnull(), williamr@2: detail::cnull(), detail::cnull()) {} williamr@2: williamr@2: tuple(typename access_traits::parameter_type t0, williamr@2: typename access_traits::parameter_type t1, williamr@2: typename access_traits::parameter_type t2, williamr@2: typename access_traits::parameter_type t3, williamr@2: typename access_traits::parameter_type t4, williamr@2: typename access_traits::parameter_type t5, williamr@2: typename access_traits::parameter_type t6, williamr@2: typename access_traits::parameter_type t7) williamr@2: : inherited(t0, t1, t2, t3, t4, t5, t6, t7, detail::cnull(), williamr@2: detail::cnull()) {} williamr@2: williamr@2: tuple(typename access_traits::parameter_type t0, williamr@2: typename access_traits::parameter_type t1, williamr@2: typename access_traits::parameter_type t2, williamr@2: typename access_traits::parameter_type t3, williamr@2: typename access_traits::parameter_type t4, williamr@2: typename access_traits::parameter_type t5, williamr@2: typename access_traits::parameter_type t6, williamr@2: typename access_traits::parameter_type t7, williamr@2: typename access_traits::parameter_type t8) williamr@2: : inherited(t0, t1, t2, t3, t4, t5, t6, t7, t8, detail::cnull()) {} williamr@2: williamr@2: tuple(typename access_traits::parameter_type t0, williamr@2: typename access_traits::parameter_type t1, williamr@2: typename access_traits::parameter_type t2, williamr@2: typename access_traits::parameter_type t3, williamr@2: typename access_traits::parameter_type t4, williamr@2: typename access_traits::parameter_type t5, williamr@2: typename access_traits::parameter_type t6, williamr@2: typename access_traits::parameter_type t7, williamr@2: typename access_traits::parameter_type t8, williamr@2: typename access_traits::parameter_type t9) williamr@2: : inherited(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) {} williamr@2: williamr@2: williamr@2: template williamr@2: tuple(const cons& p) : inherited(p) {} williamr@2: williamr@2: template williamr@2: tuple& operator=(const cons& k) { williamr@2: inherited::operator=(k); williamr@2: return *this; williamr@2: } williamr@2: williamr@2: template williamr@2: tuple& operator=(const std::pair& k) { williamr@2: BOOST_STATIC_ASSERT(length::value == 2);// check_length = 2 williamr@2: this->head = k.first; williamr@2: this->tail.head = k.second; williamr@2: return *this; williamr@2: } williamr@2: williamr@2: }; williamr@2: williamr@2: // The empty tuple williamr@2: template <> williamr@2: class tuple : williamr@2: public null_type williamr@2: { williamr@2: public: williamr@2: typedef null_type inherited; williamr@2: }; williamr@2: williamr@2: williamr@2: // Swallows any assignment (by Doug Gregor) williamr@2: namespace detail { williamr@2: williamr@2: struct swallow_assign { williamr@2: williamr@2: template williamr@2: swallow_assign const& operator=(const T&) const { williamr@2: return *this; williamr@2: } williamr@2: }; williamr@2: williamr@2: } // namespace detail williamr@2: williamr@2: // "ignore" allows tuple positions to be ignored when using "tie". williamr@2: detail::swallow_assign const ignore = detail::swallow_assign(); williamr@2: williamr@2: // --------------------------------------------------------------------------- williamr@2: // The call_traits for make_tuple williamr@2: // Honours the reference_wrapper class. williamr@2: williamr@2: // Must be instantiated with plain or const plain types (not with references) williamr@2: williamr@2: // from template foo(const T& t) : make_tuple_traits::type williamr@2: // from template foo(T& t) : make_tuple_traits::type williamr@2: williamr@2: // Conversions: williamr@2: // T -> T, williamr@2: // references -> compile_time_error williamr@2: // reference_wrapper -> T& williamr@2: // const reference_wrapper -> T& williamr@2: // array -> const ref array williamr@2: williamr@2: williamr@2: template williamr@2: struct make_tuple_traits { williamr@2: typedef T type; williamr@2: williamr@2: // commented away, see below (JJ) williamr@2: // typedef typename IF< williamr@2: // boost::is_function::value, williamr@2: // T&, williamr@2: // T>::RET type; williamr@2: williamr@2: }; williamr@2: williamr@2: // The is_function test was there originally for plain function types, williamr@2: // which can't be stored as such (we must either store them as references or williamr@2: // pointers). Such a type could be formed if make_tuple was called with a williamr@2: // reference to a function. williamr@2: // But this would mean that a const qualified function type was formed in williamr@2: // the make_tuple function and hence make_tuple can't take a function williamr@2: // reference as a parameter, and thus T can't be a function type. williamr@2: // So is_function test was removed. williamr@2: // (14.8.3. says that type deduction fails if a cv-qualified function type williamr@2: // is created. (It only applies for the case of explicitly specifying template williamr@2: // args, though?)) (JJ) williamr@2: williamr@2: template williamr@2: struct make_tuple_traits { williamr@2: typedef typename williamr@2: detail::generate_error:: williamr@2: do_not_use_with_reference_type error; williamr@2: }; williamr@2: williamr@2: // Arrays can't be stored as plain types; convert them to references. williamr@2: // All arrays are converted to const. This is because make_tuple takes its williamr@2: // parameters as const T& and thus the knowledge of the potential williamr@2: // non-constness of actual argument is lost. williamr@2: template struct make_tuple_traits { williamr@2: typedef const T (&type)[n]; williamr@2: }; williamr@2: williamr@2: template williamr@2: struct make_tuple_traits { williamr@2: typedef const T (&type)[n]; williamr@2: }; williamr@2: williamr@2: template struct make_tuple_traits { williamr@2: typedef const volatile T (&type)[n]; williamr@2: }; williamr@2: williamr@2: template williamr@2: struct make_tuple_traits { williamr@2: typedef const volatile T (&type)[n]; williamr@2: }; williamr@2: williamr@2: template williamr@2: struct make_tuple_traits >{ williamr@2: typedef T& type; williamr@2: }; williamr@2: williamr@2: template williamr@2: struct make_tuple_traits >{ williamr@2: typedef T& type; williamr@2: }; williamr@2: williamr@2: williamr@2: williamr@2: williamr@2: namespace detail { williamr@2: williamr@2: // a helper traits to make the make_tuple functions shorter (Vesa Karvonen's williamr@2: // suggestion) williamr@2: template < williamr@2: class T0 = null_type, class T1 = null_type, class T2 = null_type, williamr@2: class T3 = null_type, class T4 = null_type, class T5 = null_type, williamr@2: class T6 = null_type, class T7 = null_type, class T8 = null_type, williamr@2: class T9 = null_type williamr@2: > williamr@2: struct make_tuple_mapper { williamr@2: typedef williamr@2: tuple::type, williamr@2: typename make_tuple_traits::type, williamr@2: typename make_tuple_traits::type, williamr@2: typename make_tuple_traits::type, williamr@2: typename make_tuple_traits::type, williamr@2: typename make_tuple_traits::type, williamr@2: typename make_tuple_traits::type, williamr@2: typename make_tuple_traits::type, williamr@2: typename make_tuple_traits::type, williamr@2: typename make_tuple_traits::type> type; williamr@2: }; williamr@2: williamr@2: } // end detail williamr@2: williamr@2: // -make_tuple function templates ----------------------------------- williamr@2: inline tuple<> make_tuple() { williamr@2: return tuple<>(); williamr@2: } williamr@2: williamr@2: template williamr@2: inline typename detail::make_tuple_mapper::type williamr@2: make_tuple(const T0& t0) { williamr@2: typedef typename detail::make_tuple_mapper::type t; williamr@2: return t(t0); williamr@2: } williamr@2: williamr@2: template williamr@2: inline typename detail::make_tuple_mapper::type williamr@2: make_tuple(const T0& t0, const T1& t1) { williamr@2: typedef typename detail::make_tuple_mapper::type t; williamr@2: return t(t0, t1); williamr@2: } williamr@2: williamr@2: template williamr@2: inline typename detail::make_tuple_mapper::type williamr@2: make_tuple(const T0& t0, const T1& t1, const T2& t2) { williamr@2: typedef typename detail::make_tuple_mapper::type t; williamr@2: return t(t0, t1, t2); williamr@2: } williamr@2: williamr@2: template williamr@2: inline typename detail::make_tuple_mapper::type williamr@2: make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3) { williamr@2: typedef typename detail::make_tuple_mapper::type t; williamr@2: return t(t0, t1, t2, t3); williamr@2: } williamr@2: williamr@2: template williamr@2: inline typename detail::make_tuple_mapper::type williamr@2: make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, williamr@2: const T4& t4) { williamr@2: typedef typename detail::make_tuple_mapper::type t; williamr@2: return t(t0, t1, t2, t3, t4); williamr@2: } williamr@2: williamr@2: template williamr@2: inline typename detail::make_tuple_mapper::type williamr@2: make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, williamr@2: const T4& t4, const T5& t5) { williamr@2: typedef typename detail::make_tuple_mapper::type t; williamr@2: return t(t0, t1, t2, t3, t4, t5); williamr@2: } williamr@2: williamr@2: template williamr@2: inline typename detail::make_tuple_mapper::type williamr@2: make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, williamr@2: const T4& t4, const T5& t5, const T6& t6) { williamr@2: typedef typename detail::make_tuple_mapper williamr@2: ::type t; williamr@2: return t(t0, t1, t2, t3, t4, t5, t6); williamr@2: } williamr@2: williamr@2: template williamr@2: inline typename detail::make_tuple_mapper::type williamr@2: make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, williamr@2: const T4& t4, const T5& t5, const T6& t6, const T7& t7) { williamr@2: typedef typename detail::make_tuple_mapper williamr@2: ::type t; williamr@2: return t(t0, t1, t2, t3, t4, t5, t6, t7); williamr@2: } williamr@2: williamr@2: template williamr@2: inline typename detail::make_tuple_mapper williamr@2: ::type williamr@2: make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, williamr@2: const T4& t4, const T5& t5, const T6& t6, const T7& t7, williamr@2: const T8& t8) { williamr@2: typedef typename detail::make_tuple_mapper williamr@2: ::type t; williamr@2: return t(t0, t1, t2, t3, t4, t5, t6, t7, t8); williamr@2: } williamr@2: williamr@2: template williamr@2: inline typename detail::make_tuple_mapper williamr@2: ::type williamr@2: make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, williamr@2: const T4& t4, const T5& t5, const T6& t6, const T7& t7, williamr@2: const T8& t8, const T9& t9) { williamr@2: typedef typename detail::make_tuple_mapper williamr@2: ::type t; williamr@2: return t(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9); williamr@2: } williamr@2: williamr@2: williamr@2: williamr@2: // Tie function templates ------------------------------------------------- williamr@2: template williamr@2: inline tuple tie(T1& t1) { williamr@2: return tuple (t1); williamr@2: } williamr@2: williamr@2: template williamr@2: inline tuple tie(T1& t1, T2& t2) { williamr@2: return tuple (t1, t2); williamr@2: } williamr@2: williamr@2: template williamr@2: inline tuple tie(T1& t1, T2& t2, T3& t3) { williamr@2: return tuple (t1, t2, t3); williamr@2: } williamr@2: williamr@2: template williamr@2: inline tuple tie(T1& t1, T2& t2, T3& t3, T4& t4) { williamr@2: return tuple (t1, t2, t3, t4); williamr@2: } williamr@2: williamr@2: template williamr@2: inline tuple williamr@2: tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) { williamr@2: return tuple (t1, t2, t3, t4, t5); williamr@2: } williamr@2: williamr@2: template williamr@2: inline tuple williamr@2: tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6) { williamr@2: return tuple (t1, t2, t3, t4, t5, t6); williamr@2: } williamr@2: williamr@2: template williamr@2: inline tuple williamr@2: tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7) { williamr@2: return tuple (t1, t2, t3, t4, t5, t6, t7); williamr@2: } williamr@2: williamr@2: template williamr@2: inline tuple williamr@2: tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8) { williamr@2: return tuple williamr@2: (t1, t2, t3, t4, t5, t6, t7, t8); williamr@2: } williamr@2: williamr@2: template williamr@2: inline tuple williamr@2: tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8, williamr@2: T9& t9) { williamr@2: return tuple williamr@2: (t1, t2, t3, t4, t5, t6, t7, t8, t9); williamr@2: } williamr@2: williamr@2: template williamr@2: inline tuple williamr@2: tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8, williamr@2: T9& t9, T10& t10) { williamr@2: return tuple williamr@2: (t1, t2, t3, t4, t5, t6, t7, t8, t9, t10); williamr@2: } williamr@2: williamr@2: } // end of namespace tuples williamr@2: } // end of namespace boost williamr@2: williamr@2: williamr@2: #endif // BOOST_TUPLE_BASIC_HPP williamr@2: williamr@2: