📄 tuple_basic.hpp
字号:
// tuple_basic.hpp -----------------------------------------------------// Copyright (C) 1999, 2000 Jaakko J鋜vi (jaakko.jarvi@cs.utu.fi)//// Distributed under the Boost Software License, Version 1.0. (See// accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)// For more information, see http://www.boost.org// Outside help:// This and that, Gary Powell.// Fixed return types for get_head/get_tail// ( and other bugs ) per suggestion of Jens Maurer// simplified element type accessors + bug fix (Jeremy Siek)// Several changes/additions according to suggestions by Douglas Gregor,// William Kempf, Vesa Karvonen, John Max Skaller, Ed Brey, Beman Dawes,// David Abrahams.// Revision history:// 2002 05 01 Hugo Duncan: Fix for Borland after Jaakko's previous changes// 2002 04 18 Jaakko: tuple element types can be void or plain function// types, as long as no object is created.// Tuple objects can no hold even noncopyable types// such as arrays.// 2001 10 22 John Maddock// Fixes for Borland C++// 2001 08 30 David Abrahams// Added default constructor for cons<>.// -----------------------------------------------------------------#ifndef BOOST_TUPLE_BASIC_HPP#define BOOST_TUPLE_BASIC_HPP#include <utility> // needed for the assignment from pair to tuple#include "boost/type_traits/cv_traits.hpp"#include "boost/type_traits/function_traits.hpp"#include "boost/detail/workaround.hpp" // needed for BOOST_WORKAROUNDnamespace boost {namespace tuples {// -- null_type --------------------------------------------------------struct null_type {};// a helper function to provide a const null_type type temporarynamespace detail { inline const null_type cnull() { return null_type(); }// -- if construct ------------------------------------------------// Proposed by Krzysztof Czarnecki and Ulrich Eiseneckertemplate <bool If, class Then, class Else> struct IF { typedef Then RET; };template <class Then, class Else> struct IF<false, Then, Else> { typedef Else RET;};} // end detail// - cons forward declaration -----------------------------------------------template <class HT, class TT> struct cons;// - tuple forward declaration -----------------------------------------------template < class T0 = null_type, class T1 = null_type, class T2 = null_type, class T3 = null_type, class T4 = null_type, class T5 = null_type, class T6 = null_type, class T7 = null_type, class T8 = null_type, class T9 = null_type>class tuple;// tuple_length forward declarationtemplate<class T> struct length;namespace detail {// -- generate error template, referencing to non-existing members of this// template is used to produce compilation errors intentionallytemplate<class T>class generate_error;// - cons getters --------------------------------------------------------// called: get_class<N>::get<RETURN_TYPE>(aTuple)template< int N >struct get_class { template<class RET, class HT, class TT > inline static RET get(const cons<HT, TT>& t) {#if BOOST_WORKAROUND(__IBMCPP__,==600) // vacpp 6.0 is not very consistent regarding the member template keyword // Here it generates an error when the template keyword is used. return get_class<N-1>::get<RET>(t.tail);#else return get_class<N-1>::BOOST_NESTED_TEMPLATE get<RET>(t.tail);#endif } template<class RET, class HT, class TT > inline static RET get(cons<HT, TT>& t) {#if BOOST_WORKAROUND(__IBMCPP__,==600) return get_class<N-1>::get<RET>(t.tail);#else return get_class<N-1>::BOOST_NESTED_TEMPLATE get<RET>(t.tail);#endif }};template<>struct get_class<0> { template<class RET, class HT, class TT> inline static RET get(const cons<HT, TT>& t) { return t.head; } template<class RET, class HT, class TT> inline static RET get(cons<HT, TT>& t) { return t.head; }};} // end of namespace detail// -cons type accessors ----------------------------------------// typename tuples::element<N,T>::type gets the type of the// Nth element ot T, first element is at index 0// -------------------------------------------------------#ifndef BOOST_NO_CV_SPECIALIZATIONStemplate<int N, class T>struct element{private: typedef typename T::tail_type Next;public: typedef typename element<N-1, Next>::type type;};template<class T>struct element<0,T>{ typedef typename T::head_type type;};template<int N, class T>struct element<N, const T>{private: typedef typename T::tail_type Next; typedef typename element<N-1, Next>::type unqualified_type;public:#if BOOST_WORKAROUND(__BORLANDC__,<0x600) typedef const unqualified_type type;#else typedef typename boost::add_const<unqualified_type>::type type;#endif};template<class T>struct element<0,const T>{#if BOOST_WORKAROUND(__BORLANDC__,<0x600) typedef const typename T::head_type type;#else typedef typename boost::add_const<typename T::head_type>::type type;#endif};#else // def BOOST_NO_CV_SPECIALIZATIONSnamespace detail {template<int N, class T, bool IsConst>struct element_impl{private: typedef typename T::tail_type Next;public: typedef typename element_impl<N-1, Next, IsConst>::type type;};template<int N, class T>struct element_impl<N, T, true /* IsConst */>{private: typedef typename T::tail_type Next;public: typedef const typename element_impl<N-1, Next, true>::type type;};template<class T>struct element_impl<0, T, false /* IsConst */>{ typedef typename T::head_type type;};template<class T>struct element_impl<0, T, true /* IsConst */>{ typedef const typename T::head_type type;};} // end of namespace detailtemplate<int N, class T>struct element: public detail::element_impl<N, T, ::boost::is_const<T>::value>{};#endif// -get function templates -----------------------------------------------// Usage: get<N>(aTuple)// -- some traits classes for get functions// access traits lifted from detail namespace to be part of the interface,// (Joel de Guzman's suggestion). Rationale: get functions are part of the// interface, so should the way to express their return types be.template <class T> struct access_traits { typedef const T& const_type; typedef T& non_const_type; typedef const typename boost::remove_cv<T>::type& parameter_type;// used as the tuple constructors parameter types// Rationale: non-reference tuple element types can be cv-qualified.// It should be possible to initialize such types with temporaries,// and when binding temporaries to references, the reference must// be non-volatile and const. 8.5.3. (5)};template <class T> struct access_traits<T&> { typedef T& const_type; typedef T& non_const_type; typedef T& parameter_type;};// get function for non-const cons-lists, returns a reference to the elementtemplate<int N, class HT, class TT>inline typename access_traits< typename element<N, cons<HT, TT> >::type >::non_const_typeget(cons<HT, TT>& c BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int, N)) {#if BOOST_WORKAROUND(__IBMCPP__,==600 ) return detail::get_class<N>::#else return detail::get_class<N>::BOOST_NESTED_TEMPLATE#endif get< typename access_traits< typename element<N, cons<HT, TT> >::type >::non_const_type, HT,TT >(c);}// get function for const cons-lists, returns a const reference to// the element. If the element is a reference, returns the reference// as such (that is, can return a non-const reference)template<int N, class HT, class TT>inline typename access_traits< typename element<N, cons<HT, TT> >::type >::const_typeget(const cons<HT, TT>& c BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(int, N)) {#if BOOST_WORKAROUND(__IBMCPP__,==600) return detail::get_class<N>::#else return detail::get_class<N>::BOOST_NESTED_TEMPLATE#endif get< typename access_traits< typename element<N, cons<HT, TT> >::type >::const_type, HT,TT >(c);}// -- the cons template --------------------------------------------------namespace detail {// These helper templates wrap void types and plain function types.// The reationale is to allow one to write tuple types with those types// as elements, even though it is not possible to instantiate such object.// E.g: typedef tuple<void> some_type; // ok// but: some_type x; // failstemplate <class T> class non_storeable_type { non_storeable_type();};template <class T> struct wrap_non_storeable_type { typedef typename IF< ::boost::is_function<T>::value, non_storeable_type<T>, T >::RET type;};template <> struct wrap_non_storeable_type<void> { typedef non_storeable_type<void> type;};} // detailtemplate <class HT, class TT>struct cons { typedef HT head_type; typedef TT tail_type; typedef typename detail::wrap_non_storeable_type<head_type>::type stored_head_type; stored_head_type head; tail_type tail; typename access_traits<stored_head_type>::non_const_type get_head() { return head; } typename access_traits<tail_type>::non_const_type get_tail() { return tail; } typename access_traits<stored_head_type>::const_type get_head() const { return head; } typename access_traits<tail_type>::const_type get_tail() const { return tail; } cons() : head(), tail() {} // cons() : head(detail::default_arg<HT>::f()), tail() {} // the argument for head is not strictly needed, but it prevents // array type elements. This is good, since array type elements // cannot be supported properly in any case (no assignment, // copy works only if the tails are exactly the same type, ...) cons(typename access_traits<stored_head_type>::parameter_type h, const tail_type& t) : head (h), tail(t) {} template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10> cons( T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8, T9& t9, T10& t10 ) : head (t1), tail (t2, t3, t4, t5, t6, t7, t8, t9, t10, detail::cnull()) {} template <class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10> cons( const null_type& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8, T9& t9, T10& t10 ) : head (), tail (t2, t3, t4, t5, t6, t7, t8, t9, t10, detail::cnull()) {} template <class HT2, class TT2> cons( const cons<HT2, TT2>& u ) : head(u.head), tail(u.tail) {} template <class HT2, class TT2> cons& operator=( const cons<HT2, TT2>& u ) { head=u.head; tail=u.tail; return *this; } // must define assignment operator explicitly, implicit version is // illformed if HT is a reference (12.8. (12)) cons& operator=(const cons& u) { head = u.head; tail = u.tail; return *this; } template <class T1, class T2> cons& operator=( const std::pair<T1, T2>& u ) { BOOST_STATIC_ASSERT(length<cons>::value == 2); // check length = 2 head = u.first; tail.head = u.second; return *this; } // get member functions (non-const and const) template <int N> typename access_traits< typename element<N, cons<HT, TT> >::type >::non_const_type get() { return boost::tuples::get<N>(*this); // delegate to non-member get } template <int N> typename access_traits< typename element<N, cons<HT, TT> >::type >::const_type get() const { return boost::tuples::get<N>(*this); // delegate to non-member get }};template <class HT>struct cons<HT, null_type> { typedef HT head_type; typedef null_type tail_type; typedef cons<HT, null_type> self_type; typedef typename detail::wrap_non_storeable_type<head_type>::type stored_head_type; stored_head_type head; typename access_traits<stored_head_type>::non_const_type get_head() { return head; } null_type get_tail() { return null_type(); } typename access_traits<stored_head_type>::const_type get_head() const { return head; } const null_type get_tail() const { return null_type(); } // cons() : head(detail::default_arg<HT>::f()) {} cons() : head() {} cons(typename access_traits<stored_head_type>::parameter_type h, const null_type& = null_type()) : head (h) {} template<class T1> cons(T1& t1, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&) : head (t1) {} cons(const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&) : head () {} template <class HT2> cons( const cons<HT2, null_type>& u ) : head(u.head) {} template <class HT2> cons& operator=(const cons<HT2, null_type>& u ) { head = u.head; return *this; } // must define assignment operator explicitely, implicit version // is illformed if HT is a reference cons& operator=(const cons& u) { head = u.head; return *this; } template <int N> typename access_traits< typename element<N, self_type>::type >::non_const_type get(BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int, N)) { return boost::tuples::get<N>(*this); } template <int N> typename access_traits< typename element<N, self_type>::type >::const_type get(BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int, N)) const {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -