commit adeeed1f6d54a2660303ff9b58a22254d8464cf9 Author: Jaakko Järvi Date: Fri Aug 10 11:45:43 2001 +0000 Adding the Tuple library files [SVN r10828] diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3e84d7c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,96 @@ +* text=auto !eol svneol=native#text/plain +*.gitattributes text svneol=native#text/plain + +# Scriptish formats +*.bat text svneol=native#text/plain +*.bsh text svneol=native#text/x-beanshell +*.cgi text svneol=native#text/plain +*.cmd text svneol=native#text/plain +*.js text svneol=native#text/javascript +*.php text svneol=native#text/x-php +*.pl text svneol=native#text/x-perl +*.pm text svneol=native#text/x-perl +*.py text svneol=native#text/x-python +*.sh eol=lf svneol=LF#text/x-sh +configure eol=lf svneol=LF#text/x-sh + +# Image formats +*.bmp binary svneol=unset#image/bmp +*.gif binary svneol=unset#image/gif +*.ico binary svneol=unset#image/ico +*.jpeg binary svneol=unset#image/jpeg +*.jpg binary svneol=unset#image/jpeg +*.png binary svneol=unset#image/png +*.tif binary svneol=unset#image/tiff +*.tiff binary svneol=unset#image/tiff +*.svg text svneol=native#image/svg%2Bxml + +# Data formats +*.pdf binary svneol=unset#application/pdf +*.avi binary svneol=unset#video/avi +*.doc binary svneol=unset#application/msword +*.dsp text svneol=crlf#text/plain +*.dsw text svneol=crlf#text/plain +*.eps binary svneol=unset#application/postscript +*.gz binary svneol=unset#application/gzip +*.mov binary svneol=unset#video/quicktime +*.mp3 binary svneol=unset#audio/mpeg +*.ppt binary svneol=unset#application/vnd.ms-powerpoint +*.ps binary svneol=unset#application/postscript +*.psd binary svneol=unset#application/photoshop +*.rdf binary svneol=unset#text/rdf +*.rss text svneol=unset#text/xml +*.rtf binary svneol=unset#text/rtf +*.sln text svneol=native#text/plain +*.swf binary svneol=unset#application/x-shockwave-flash +*.tgz binary svneol=unset#application/gzip +*.vcproj text svneol=native#text/xml +*.vcxproj text svneol=native#text/xml +*.vsprops text svneol=native#text/xml +*.wav binary svneol=unset#audio/wav +*.xls binary svneol=unset#application/vnd.ms-excel +*.zip binary svneol=unset#application/zip + +# Text formats +.htaccess text svneol=native#text/plain +*.bbk text svneol=native#text/xml +*.cmake text svneol=native#text/plain +*.css text svneol=native#text/css +*.dtd text svneol=native#text/xml +*.htm text svneol=native#text/html +*.html text svneol=native#text/html +*.ini text svneol=native#text/plain +*.log text svneol=native#text/plain +*.mak text svneol=native#text/plain +*.qbk text svneol=native#text/plain +*.rst text svneol=native#text/plain +*.sql text svneol=native#text/x-sql +*.txt text svneol=native#text/plain +*.xhtml text svneol=native#text/xhtml%2Bxml +*.xml text svneol=native#text/xml +*.xsd text svneol=native#text/xml +*.xsl text svneol=native#text/xml +*.xslt text svneol=native#text/xml +*.xul text svneol=native#text/xul +*.yml text svneol=native#text/plain +boost-no-inspect text svneol=native#text/plain +CHANGES text svneol=native#text/plain +COPYING text svneol=native#text/plain +INSTALL text svneol=native#text/plain +Jamfile text svneol=native#text/plain +Jamroot text svneol=native#text/plain +Jamfile.v2 text svneol=native#text/plain +Jamrules text svneol=native#text/plain +Makefile* text svneol=native#text/plain +README text svneol=native#text/plain +TODO text svneol=native#text/plain + +# Code formats +*.c text svneol=native#text/plain +*.cpp text svneol=native#text/plain +*.h text svneol=native#text/plain +*.hpp text svneol=native#text/plain +*.ipp text svneol=native#text/plain +*.tpp text svneol=native#text/plain +*.jam text svneol=native#text/plain +*.java text svneol=native#text/plain diff --git a/include/boost/tuple/detail/tuple_basic.hpp b/include/boost/tuple/detail/tuple_basic.hpp new file mode 100644 index 0000000..499ec8f --- /dev/null +++ b/include/boost/tuple/detail/tuple_basic.hpp @@ -0,0 +1,707 @@ +// tuple_basic.hpp ----------------------------------------------------- + +// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi) +// +// Permission to copy, use, sell and distribute this software is granted +// provided this copyright notice appears in all copies. +// Permission to modify the code and to distribute modified code is granted +// provided this copyright notice appears in all copies, and a notice +// that the code was modified is included with the copyright notice. +// +// This software is provided "as is" without express or implied warranty, +// and with no claim as to its suitability for any purpose. + +// 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 Doug Gregor, +// William Kempf, Vesa Karvonen, John Max Skaller, Ed Brey, Beman Davis, +// David Abrahams. + +// ----------------------------------------------------------------- + +#ifndef BOOST_TUPLE_BASIC_HPP +#define BOOST_TUPLE_BASIC_HPP + + +#include // needed for the assignment from pair to tuple + +#include "boost/type_traits/cv_traits.hpp" + +namespace boost { + +// -- null_type -------------------------------------------------------- +struct null_type {}; + +// a helper function to provide a const null_type type temporary +namespace detail { +namespace tuples { + inline const null_type cnull_type() { return null_type(); } +} // end tuples +} // end detail + +// - cons forward declaration ----------------------------------------------- +template +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 declaration +template struct tuple_length; + + + +namespace detail { +namespace tuples { + +// -- generate error template, referencing to non-existing members of this +// template is used to produce compilation errors intentionally +template +class generate_error; + +// tuple default argument wrappers --------------------------------------- +// Work for non-reference types, intentionally not for references +template +struct default_arg { + +// Non-class temporaries cannot have qualifiers. +// To prevent f to return for example const int, we remove cv-qualifiers +// from all temporaries. + static typename boost::remove_cv::type f() { return T(); } +}; + +template +struct default_arg { + static T& f() { + return generate_error::no_default_values_for_reference_types; + } +}; + +// - cons getters -------------------------------------------------------- +// called: element::get(aTuple) + +template< int N > +struct element { + template + inline static RET get(const cons& t) + { + return element::template get(t.tail); + } + template + inline static RET get(cons& t) + { + return element::template get(t.tail); + } +}; + +template<> +struct element<0> { + template + inline static RET get(const cons& t) + { + return t.head; + } + template + inline static RET get(cons& t) + { + return t.head; + } +}; + +} // end of namespace tuples +} // end of namespace detail + + +// -cons type accessors ---------------------------------------- +// typename tuple_element::type gets the type of the +// Nth element ot T, first element is at index 0 +// ------------------------------------------------------- + +template +struct tuple_element +{ +private: + typedef typename T::tail_type Next; +public: + typedef typename tuple_element::type type; +}; +template +struct tuple_element<0,T> +{ + typedef typename T::head_type type; +}; + +// -get function templates ----------------------------------------------- +// Usage: get(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 struct tuple_access_traits { + typedef const T& const_type; + typedef T& non_const_type; + + typedef const typename boost::remove_cv::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 struct tuple_access_traits { + + 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 element + +template +inline typename tuple_access_traits< + typename tuple_element >::type + >::non_const_type +get(cons& c) { + return detail::tuples::element::template + get< + typename tuple_access_traits< + typename tuple_element >::type + >::non_const_type>(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 +inline typename tuple_access_traits< + typename tuple_element >::type + >::const_type +get(const cons& c) { + return detail::tuples::element::template + get< + typename tuple_access_traits< + typename tuple_element >::type + >::const_type>(c); +} + + + + +// -- the cons template -------------------------------------------------- + +template +struct cons { + + typedef HT head_type; + typedef TT tail_type; + + head_type head; + tail_type tail; + + typename tuple_access_traits::non_const_type get_head() { return head; } + typename tuple_access_traits::non_const_type get_tail() { return tail; } + + typename tuple_access_traits::const_type get_head() const { return head; } + typename tuple_access_traits::const_type get_tail() const { return tail; } + + template + 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::tuples::cnull_type()) {} + + template + cons( const cons& u ) : head(u.head), tail(u.tail) {} + + template + cons& operator=( const cons& 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 + cons& operator=( const std::pair& u ) { + BOOST_STATIC_ASSERT(tuple_length::value == 2); // check length = 2 + head = u.first; tail.head = u.second; return *this; + } + + // get member functions (non-const and const) + template + typename tuple_access_traits< + typename tuple_element >::type + >::non_const_type + get() { + return boost::get(*this); // delegate to non-member get + } + + template + typename tuple_access_traits< + typename tuple_element >::type + >::const_type + get() const { + return boost::get(*this); // delegate to non-member get + } +}; + +template +struct cons { + + typedef HT head_type; + typedef null_type tail_type; + + head_type head; + + typename tuple_access_traits::non_const_type get_head() { return head; } + null_type get_tail() { return null_type(); } + + typename tuple_access_traits::const_type get_head() const { return head; } + const null_type get_tail() const { return null_type(); } + + template + 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) {} + + template + cons( const cons& u ) : head(u.head) {} + + template + cons& operator=(const cons& 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 + typename tuple_access_traits< + typename tuple_element::type + >::non_const_type + get() { + return boost::get(*this); + } + + template + typename tuple_access_traits< + typename tuple_element::type + >::const_type + get() const { + return boost::get(*this); + } + +}; + +// templates for finding out the length of the tuple ------------------- + +template +struct tuple_length { + BOOST_STATIC_CONSTANT(int, value = 1 + tuple_length::value); +}; + +template<> +struct tuple_length { + BOOST_STATIC_CONSTANT(int, value = 0); +}; + + +namespace detail { +namespace tuples { + +// Tuple to cons mapper -------------------------------------------------- +template +struct map_tuple_to_cons +{ + typedef cons::type + > type; +}; + +template +struct map_tuple_to_cons +{ + typedef cons type; +}; + +// The empty tuple is a null_type +template <> +struct map_tuple_to_cons +{ + typedef null_type type; +}; + +} // end tuples +} // end detail + +// ------------------------------------------------------------------- +// -- tuple ------------------------------------------------------ +template + +class tuple : + public detail::tuples::map_tuple_to_cons::type +{ +public: + typedef typename + detail::tuples::map_tuple_to_cons::type inherited; + typedef typename inherited::head_type head_type; + typedef typename inherited::tail_type tail_type; + + +// tuple_access_traits::parameter_type takes non-reference types as const T& + explicit tuple( + typename tuple_access_traits::parameter_type t0 + = detail::tuples::default_arg::f(), + typename tuple_access_traits::parameter_type t1 + = detail::tuples::default_arg::f(), + typename tuple_access_traits::parameter_type t2 + = detail::tuples::default_arg::f(), + typename tuple_access_traits::parameter_type t3 + = detail::tuples::default_arg::f(), + typename tuple_access_traits::parameter_type t4 + = detail::tuples::default_arg::f(), + typename tuple_access_traits::parameter_type t5 + = detail::tuples::default_arg::f(), + typename tuple_access_traits::parameter_type t6 + = detail::tuples::default_arg::f(), + typename tuple_access_traits::parameter_type t7 + = detail::tuples::default_arg::f(), + typename tuple_access_traits::parameter_type t8 + = detail::tuples::default_arg::f(), + typename tuple_access_traits::parameter_type t9 + = detail::tuples::default_arg::f()) + + : inherited(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) {} + + template + tuple(const cons& p) : inherited(p) {} + + template + tuple& operator=(const cons& k) { + inherited::operator=(k); + return *this; + } + + template + tuple& operator=(const std::pair& k) { + BOOST_STATIC_ASSERT(tuple_length::value == 2);// check_length = 2 + this->head = k.first; + this->tail.head = k.second; + return *this; + } + +}; + +// Swallows any assignment (by Doug Gregor) +namespace detail { +namespace tuples { + +struct swallow_assign { + + template + swallow_assign& operator=(const T&) { + return *this; + } +}; +} // namespace tuples +} // namespace detail + +// "ignore" allows tuple positions to be ignored when using "tie". +namespace { + detail::tuples::swallow_assign ignore; +} + +// --------------------------------------------------------------------------- +// The call_traits for make_tuple +// Honours the reference_wrapper class. + +// Must be instantiated with plain or const plain types (not with references) + +// from template foo(const T& t) : make_tuple_traits::type +// from template foo(T& t) : make_tuple_traits::type + +// Conversions: +// T -> T, +// references -> compile_time_error +// reference_wrapper -> T& +// const reference_wrapper -> T& +// array -> const ref array + + +template +struct make_tuple_traits { + typedef T type; + + // commented away, see below (JJ) + // typedef typename IF< + // boost::is_function::value, + // T&, + // T>::RET type; + +}; + +// The is_function test was there originally for plain function types, +// which can't be stored as such (we must either store them as references or +// pointers). Such a type could be formed if make_tuple was called with a +// reference to a function. +// But this would mean that a const qualified function type was formed in +// the make_tuple function and hence make_tuple can't take a function +// reference as a parameter, and thus T can't be a function type. +// So is_function test was removed. +// (14.8.3. says that type deduction fails if a cv-qualified function type +// is created. (It only applies for the case of explicitly specifying template +// args, though?)) (JJ) + +template +struct make_tuple_traits { + typedef typename + detail::tuples::generate_error:: + do_not_use_with_reference_type error; +}; + +// Arrays can't be stored as plain types; convert them to references. +// All arrays are converted to const. This is because make_tuple takes its +// parameters as const T& and thus the knowledge of the potential +// non-constness of actual argument is lost. +template struct make_tuple_traits { + typedef const T (&type)[n]; +}; + +template +struct make_tuple_traits { + typedef const T (&type)[n]; +}; + +template struct make_tuple_traits { + typedef const volatile T (&type)[n]; +}; + +template +struct make_tuple_traits { + typedef const volatile T (&type)[n]; +}; + +template +struct make_tuple_traits >{ + typedef T& type; +}; + +template +struct make_tuple_traits >{ + typedef T& type; +}; + + + + +namespace detail { +namespace tuples { + +// a helper traits to make the make_tuple functions shorter (Vesa Karvonen's +// suggestion) +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 +> +struct make_tuple_mapper { + typedef + tuple::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type> type; +}; + +} // end tuples +} // end detail + +// -make_tuple function templates ----------------------------------- +//tuple<> inline make_tuple() { +// return tuple<>(); +//} + +template +boost::detail::tuples::make_tuple_mapper::type +inline make_tuple(const T0& t0) { + return boost::detail::tuples::make_tuple_mapper::type(t0); +} + +template +boost::detail::tuples::make_tuple_mapper::type +inline make_tuple(const T0& t0, const T1& t1) { + return boost::detail::tuples::make_tuple_mapper::type(t0, t1); +} + +template +boost::detail::tuples::make_tuple_mapper::type +inline make_tuple(const T0& t0, const T1& t1, const T2& t2) { + return boost::detail::tuples::make_tuple_mapper::type(t0, t1, t2); +} + +template +boost::detail::tuples::make_tuple_mapper::type +inline make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3) { + return boost::detail::tuples::make_tuple_mapper::type + (t0, t1, t2, t3); +} + +template +boost::detail::tuples::make_tuple_mapper::type +inline make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4) { + return boost::detail::tuples::make_tuple_mapper::type + (t0, t1, t2, t3, t4); +} + +template +boost::detail::tuples::make_tuple_mapper::type +inline make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5) { + return boost::detail::tuples::make_tuple_mapper::type + (t0, t1, t2, t3, t4, t5); +} + +template +boost::detail::tuples::make_tuple_mapper::type +inline make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6) { + return boost::detail::tuples::make_tuple_mapper + ::type + (t0, t1, t2, t3, t4, t5, t6); +} + +template +boost::detail::tuples::make_tuple_mapper::type +inline make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6, const T7& t7) { + return boost::detail::tuples::make_tuple_mapper + ::type + (t0, t1, t2, t3, t4, t5, t6, t7); +} + +template +boost::detail::tuples::make_tuple_mapper + ::type +inline make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6, const T7& t7, + const T8& t8) { + return boost::detail::tuples::make_tuple_mapper + ::type + (t0, t1, t2, t3, t4, t5, t6, t7, t8); +} + +template +boost::detail::tuples::make_tuple_mapper + ::type +inline make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6, const T7& t7, + const T8& t8, const T9& t9) { + return boost::detail::tuples::make_tuple_mapper + ::type + (t0, t1, t2, t3, t4, t5, t6, t7, t8, t9); +} + + + +// Tie function templates ------------------------------------------------- +template +tuple inline tie(T1& t1) { + return tuple (t1); +} + +template +tuple inline tie(T1& t1, T2& t2) { + return tuple (t1, t2); +} + +template +tuple inline tie(T1& t1, T2& t2, T3& t3) { + return tuple (t1, t2, t3); +} + +template +tuple inline tie(T1& t1, T2& t2, T3& t3, T4& t4) { + return tuple (t1, t2, t3, t4); +} + +template +tuple +inline tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) { + return tuple (t1, t2, t3, t4, t5); +} + +template +tuple +inline tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6) { + return tuple (t1, t2, t3, t4, t5, t6); +} + +template +tuple +inline tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7) { + return tuple (t1, t2, t3, t4, t5, t6, t7); +} + +template +tuple +inline tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8) { + return tuple + (t1, t2, t3, t4, t5, t6, t7, t8); +} + +template +tuple +inline tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8, + T9& t9) { + return tuple + (t1, t2, t3, t4, t5, t6, t7, t8, t9); +} + +template +tuple +inline tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8, + T9& t9, T10& t10) { + return tuple + (t1, t2, t3, t4, t5, t6, t7, t8, t9, t10); +} + +} // end of namespace boost + + +#endif // BOOST_TUPLE_BASIC_HPP + + diff --git a/include/boost/tuple/detail/tuple_basic_no_partial_spec.hpp b/include/boost/tuple/detail/tuple_basic_no_partial_spec.hpp new file mode 100644 index 0000000..fa197b1 --- /dev/null +++ b/include/boost/tuple/detail/tuple_basic_no_partial_spec.hpp @@ -0,0 +1,654 @@ +// - tuple_basic_no_partial_spec.hpp ----------------------------------------- + +// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi) +// Copyright (C) 2001 Doug Gregor (gregod@rpi.edu) +// Copyright (C) 2001 Gary Powell (gary.powell@sierra.com) +// +// Permission to copy, use, sell and distribute this software is granted +// provided this copyright notice appears in all copies. +// Permission to modify the code and to distribute modified code is granted +// provided this copyright notice appears in all copies, and a notice +// that the code was modified is included with the copyright notice. +// +// This software is provided "as is" without express or implied warranty, +// and with no claim as to its suitability for any purpose. + +// For more information, see http://www.boost.org or http://lambda.cs.utu.fi + +// Revision History +// 14 02 01 Remove extra ';'. Also, fixed 10-parameter to make_tuple. (DG) +// 10 02 01 Fixed "null_type" constructors. +// Implemented comparison operators globally. +// Hide element_type_ref and element_type_const_ref. +// (DG). +// 09 02 01 Extended to tuples of length 10. Changed comparison for +// operator<() +// to the same used by std::pair<>, added cnull_type() (GP) +// 03 02 01 Initial Version from original tuple.hpp code by JJ. (DG) + +// ----------------------------------------------------------------- + +#ifndef BOOST_TUPLE_BASIC_NO_PARTIAL_SPEC_HPP +#define BOOST_TUPLE_BASIC_NO_PARTIAL_SPEC_HPP + +#include "boost/type_traits.hpp" + +#if defined BOOST_MSVC +#pragma warning(disable:4518) // storage-class or type specifier(s) unexpected here; ignored +#pragma warning(disable:4181) // qualifier applied to reference type ignored +#pragma warning(disable:4227) // qualifier applied to reference type ignored +#endif + +namespace boost { + + // null_type denotes the end of a list built with "cons" + struct null_type + { + null_type() {} + null_type(const null_type&, const null_type&) {} + }; + + // a helper function to provide a const null_type type temporary + inline const null_type cnull_type() { return null_type(); } + + namespace detail { + namespace tuples { + // Takes a pointer and routes all assignments to whatever it points to + template + struct assign_to_pointee + { + public: + explicit assign_to_pointee(T* p) : ptr(p) {} + + template + assign_to_pointee& operator=(const Other& other) + { + *ptr = other; + return *this; + } + + private: + T* ptr; + }; + + // Swallows any assignment + struct swallow_assign + { + template + swallow_assign& operator=(const T&) + { + return *this; + } + }; + + } // end of namespace tuples + } // end of namespace detail + + // cons builds a heterogenous list of types + template + struct cons + { + typedef cons self_type; + typedef Head head_type; + typedef Tail tail_type; + + head_type head; + tail_type tail; + + typename boost::add_reference::type get_head() { return head; } + typename boost::add_reference::type get_tail() { return tail; } + + typename boost::add_reference::type get_head() const { return head; } + typename boost::add_reference::type get_tail() const { return tail; } + + template + explicit cons(const Other& other) : head(other.head), tail(other.tail) + { + } + +#if defined BOOST_MSVC + explicit cons(const head_type& h /* = head_type() */, // causes MSVC 6.5 to barf. + const tail_type& t = tail_type()) : + head(h), tail(t) + { + } +#else + explicit cons(const head_type& h = head_type(), + const tail_type& t = tail_type()) : + head(h), tail(t) + { + } +#endif + + + template + cons& operator=(const Other& other) + { + head = other.head; + tail = other.tail; + return *this; + } + }; + + namespace detail { + namespace tuples { + // Determines if the parameter is null_type + template struct is_null_type { enum { RET = 0 }; }; + template<> struct is_null_type { enum { RET = 1 }; }; + + /* Build a cons structure from the given Head and Tail. If both are null_type, + return null_type. */ + template + struct build_cons + { + private: + enum { tail_is_null_type = is_null_type::RET }; + public: + typedef cons RET; + }; + + template<> + struct build_cons + { + typedef null_type RET; + }; + + // Map the N elements of a tuple into a cons list + template< + typename T1, + typename T2 = null_type, + typename T3 = null_type, + typename T4 = null_type, + typename T5 = null_type, + typename T6 = null_type, + typename T7 = null_type, + typename T8 = null_type, + typename T9 = null_type, + typename T10 = null_type + > + struct map_tuple_to_cons + { + typedef typename detail::tuples::build_cons::RET cons10; + typedef typename detail::tuples::build_cons::RET cons9; + typedef typename detail::tuples::build_cons::RET cons8; + typedef typename detail::tuples::build_cons::RET cons7; + typedef typename detail::tuples::build_cons::RET cons6; + typedef typename detail::tuples::build_cons::RET cons5; + typedef typename detail::tuples::build_cons::RET cons4; + typedef typename detail::tuples::build_cons::RET cons3; + typedef typename detail::tuples::build_cons::RET cons2; + typedef typename detail::tuples::build_cons::RET cons1; + }; + + // Workaround the lack of partial specialization in some compilers + template + struct _element_type + { + template + struct inner + { + private: + typedef typename Tuple::tail_type tail_type; + typedef _element_type next_elt_type; + + public: + typedef typename _element_type::template inner::RET RET; + }; + }; + + template<> + struct _element_type<0> + { + template + struct inner + { + typedef typename Tuple::head_type RET; + }; + }; + } // detail + } // tuples + + // Return the Nth type of the given Tuple + template + struct tuple_element + { + private: + typedef detail::tuples::_element_type nth_type; + + public: + typedef typename nth_type::template inner::RET RET; + typedef RET type; + }; + + namespace detail { + namespace tuples { + // Return a reference to the Nth type of the given Tuple + template + struct tuple_element_ref + { + private: + typedef typename tuple_element::RET elt_type; + + public: + typedef typename add_reference::type RET; + typedef RET type; + }; + + // Return a const reference to the Nth type of the given Tuple + template + struct tuple_element_const_ref + { + private: + typedef typename tuple_element::RET elt_type; + + public: + typedef typename add_reference::type RET; + typedef RET type; + }; + } + } + // Get length of this tuple + template + struct tuple_length + { + enum { value = 1 + tuple_length::value }; + }; + + template<> + struct tuple_length + { + enum { value = 0 }; + }; + + // Reference the Nth element in a tuple and retrieve it with "get" + template + struct element + { + template + static inline + typename detail::tuples::tuple_element_ref::RET + get(Tuple& t) + { + return element::get(t.tail); + } + + template + static inline + typename detail::tuples::tuple_element_const_ref::RET + get(const Tuple& t) + { + return element::get(t.tail); + } + }; + + template<> + struct element<0> + { + template + static inline + typename add_reference::type + get(Tuple& t) + { + return t.head; + } + + template + static inline + typename add_reference::type + get(const Tuple& t) + { + return t.head; + } + }; + + // tuple class + template< + typename T1, + typename T2 = null_type, + typename T3 = null_type, + typename T4 = null_type, + typename T5 = null_type, + typename T6 = null_type, + typename T7 = null_type, + typename T8 = null_type, + typename T9 = null_type, + typename T10 = null_type + > + class tuple : + public detail::tuples::map_tuple_to_cons::cons1 + { + private: + typedef detail::tuples::map_tuple_to_cons mapped_tuple; + typedef typename mapped_tuple::cons10 cons10; + typedef typename mapped_tuple::cons9 cons9; + typedef typename mapped_tuple::cons8 cons8; + typedef typename mapped_tuple::cons7 cons7; + typedef typename mapped_tuple::cons6 cons6; + typedef typename mapped_tuple::cons5 cons5; + typedef typename mapped_tuple::cons4 cons4; + typedef typename mapped_tuple::cons3 cons3; + typedef typename mapped_tuple::cons2 cons2; + typedef typename mapped_tuple::cons1 cons1; + + public: + typedef tuple self_type; + + explicit tuple(const T1& t1 = T1(), + const T2& t2 = T2(), + const T3& t3 = T3(), + const T4& t4 = T4(), + const T5& t5 = T5(), + const T6& t6 = T6(), + const T7& t7 = T7(), + const T8& t8 = T8(), + const T9& t9 = T9(), + const T10& t10 = T10()) : + cons1(t1, cons2(t2, cons3(t3, cons4(t4, cons5(t5, cons6(t6,cons7(t7,cons8(t8,cons9(t9,cons10(t10)))))))))) + { + } + + template + explicit tuple(const Other& other) : cons1(other) + { + } + + template + self_type& operator=(const Other& other) + { + this->head = other.head; + this->tail = other.tail; + return *this; + } + }; + + // Retrieve the Nth element in the typle + template + typename detail::tuples::tuple_element_ref::RET + get(Tuple& t) + { + return element::get(t); + } + + // Retrieve the Nth element in the typle + template + typename detail::tuples::tuple_element_const_ref::RET + get(const Tuple& t) + { + return element::get(t); + } + + // Make a tuple + template + inline + tuple + make_tuple(const T1& t1) + { + return tuple(t1); + } + + // Make a tuple + template + inline + tuple + make_tuple(const T1& t1, const T2& t2) + { + return tuple(t1, t2); + } + + // Make a tuple + template + inline + tuple + make_tuple(const T1& t1, const T2& t2, const T3& t3) + { + return tuple(t1, t2, t3); + } + + // Make a tuple + template + inline + tuple + make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4) + { + return tuple(t1, t2, t3, t4); + } + + // Make a tuple + template + inline + tuple + make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) + { + return tuple(t1, t2, t3, t4, t5); + } + + // Make a tuple + template + inline + tuple + make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6) + { + return tuple(t1, t2, t3, t4, t5, t6); + } + + // Make a tuple + template + inline + tuple + make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7) + { + return tuple(t1, t2, t3, t4, t5, t6, t7); + } + + // Make a tuple + template + inline + tuple + make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8) + { + return tuple(t1, t2, t3, t4, t5, t6, t7, t8); + } + + // Make a tuple + template + inline + tuple + make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8, const T9& t9) + { + return tuple(t1, t2, t3, t4, t5, t6, t7, t8, t9); + } + + // Make a tuple + template + inline + tuple + make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8, const T9& t9, const T10& t10) + { + return tuple(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10); + } + + // Tie variables into a tuple + template + inline + tuple > + tie(T1& t1) + { + return make_tuple(detail::tuples::assign_to_pointee(&t1)); + } + + // Tie variables into a tuple + template + inline + tuple, + detail::tuples::assign_to_pointee > + tie(T1& t1, T2& t2) + { + return make_tuple(detail::tuples::assign_to_pointee(&t1), + detail::tuples::assign_to_pointee(&t2)); + } + + // Tie variables into a tuple + template + inline + tuple, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee > + tie(T1& t1, T2& t2, T3& t3) + { + return make_tuple(detail::tuples::assign_to_pointee(&t1), + detail::tuples::assign_to_pointee(&t2), + detail::tuples::assign_to_pointee(&t3)); + } + + // Tie variables into a tuple + template + inline + tuple, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee > + tie(T1& t1, T2& t2, T3& t3, T4& t4) + { + return make_tuple(detail::tuples::assign_to_pointee(&t1), + detail::tuples::assign_to_pointee(&t2), + detail::tuples::assign_to_pointee(&t3), + detail::tuples::assign_to_pointee(&t4)); + } + + // Tie variables into a tuple + template + inline + tuple, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee > + tie(T1& t1, T2& t2, T3& t3, T4& t4, T5 &t5) + { + return make_tuple(detail::tuples::assign_to_pointee(&t1), + detail::tuples::assign_to_pointee(&t2), + detail::tuples::assign_to_pointee(&t3), + detail::tuples::assign_to_pointee(&t4), + detail::tuples::assign_to_pointee(&t5)); + } + + // Tie variables into a tuple + template + inline + tuple, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee > + tie(T1& t1, T2& t2, T3& t3, T4& t4, T5 &t5, T6 &t6) + { + return make_tuple(detail::tuples::assign_to_pointee(&t1), + detail::tuples::assign_to_pointee(&t2), + detail::tuples::assign_to_pointee(&t3), + detail::tuples::assign_to_pointee(&t4), + detail::tuples::assign_to_pointee(&t5), + detail::tuples::assign_to_pointee(&t6)); + } + + // Tie variables into a tuple + template + inline + tuple, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee > + tie(T1& t1, T2& t2, T3& t3, T4& t4, T5 &t5, T6 &t6, T7 &t7) + { + return make_tuple(detail::tuples::assign_to_pointee(&t1), + detail::tuples::assign_to_pointee(&t2), + detail::tuples::assign_to_pointee(&t3), + detail::tuples::assign_to_pointee(&t4), + detail::tuples::assign_to_pointee(&t5), + detail::tuples::assign_to_pointee(&t6), + detail::tuples::assign_to_pointee(&t7)); + } + + // Tie variables into a tuple + template + inline + tuple, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee > + tie(T1& t1, T2& t2, T3& t3, T4& t4, T5 &t5, T6 &t6, T7 &t7, T8 &t8) + { + return make_tuple(detail::tuples::assign_to_pointee(&t1), + detail::tuples::assign_to_pointee(&t2), + detail::tuples::assign_to_pointee(&t3), + detail::tuples::assign_to_pointee(&t4), + detail::tuples::assign_to_pointee(&t5), + detail::tuples::assign_to_pointee(&t6), + detail::tuples::assign_to_pointee(&t7), + detail::tuples::assign_to_pointee(&t8)); + } + + // Tie variables into a tuple + template + inline + tuple, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee > + tie(T1& t1, T2& t2, T3& t3, T4& t4, T5 &t5, T6 &t6, T7 &t7, T8 &t8, T9 &t9) + { + return make_tuple(detail::tuples::assign_to_pointee(&t1), + detail::tuples::assign_to_pointee(&t2), + detail::tuples::assign_to_pointee(&t3), + detail::tuples::assign_to_pointee(&t4), + detail::tuples::assign_to_pointee(&t5), + detail::tuples::assign_to_pointee(&t6), + detail::tuples::assign_to_pointee(&t7), + detail::tuples::assign_to_pointee(&t8), + detail::tuples::assign_to_pointee(&t9)); + } + // Tie variables into a tuple + template + inline + tuple, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee, + detail::tuples::assign_to_pointee > + tie(T1& t1, T2& t2, T3& t3, T4& t4, T5 &t5, T6 &t6, T7 &t7, T8 &t8, T9 &t9, T10 &t10) + { + return make_tuple(detail::tuples::assign_to_pointee(&t1), + detail::tuples::assign_to_pointee(&t2), + detail::tuples::assign_to_pointee(&t3), + detail::tuples::assign_to_pointee(&t4), + detail::tuples::assign_to_pointee(&t5), + detail::tuples::assign_to_pointee(&t6), + detail::tuples::assign_to_pointee(&t7), + detail::tuples::assign_to_pointee(&t8), + detail::tuples::assign_to_pointee(&t9), + detail::tuples::assign_to_pointee(&t10)); + } + // "ignore" allows tuple positions to be ignored when using "tie". + namespace { + detail::tuples::swallow_assign ignore; + } + +} // namespace boost +#endif // BOOST_TUPLE_BASIC_NO_PARTIAL_SPEC_HPP diff --git a/include/boost/tuple/reference_wrappers.hpp b/include/boost/tuple/reference_wrappers.hpp new file mode 100644 index 0000000..52df59f --- /dev/null +++ b/include/boost/tuple/reference_wrappers.hpp @@ -0,0 +1,57 @@ +// -- reference_wrappers - Boost Tuple Library ----------------------------- + +// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi) +// +// Permission to copy, use, sell and distribute this software is granted +// provided this copyright notice appears in all copies. +// Permission to modify the code and to distribute modified code is granted +// provided this copyright notice appears in all copies, and a notice +// that the code was modified is included with the copyright notice. +// +// This software is provided "as is" without express or implied warranty, +// and with no claim as to its suitability for any purpose. +// +// For more information, see http://www.boost.org + +// ----------------------------------------------------------------- + +#ifndef BOOST_TUPLE_REFERENCE_WRAPPERS_HPP +#define BOOST_TUPLE_REFERENCE_WRAPPERS_HPP + +namespace boost { + + +// reference wrappers ------------------------------------------------------- + +// These wrappers are handle classes that hold references to objects. + +// reference_wrapper is used to specify that a tuple element should be +// a reference to the wrapped object - rather than a copy of it. +// The wrapper acts as a disguise for passing non-const reference +// parameters via a reference to const parameter. + +template +class reference_wrapper { + T& x; +public: + explicit + reference_wrapper(T& t) : x(t) {} + operator T&() const { return x; } +}; + +// store as a reference to T +template +inline const reference_wrapper ref(T& t) { + return reference_wrapper(t); +} + +// store as a reference to const T +template +inline const reference_wrapper cref(const T& t) { + return reference_wrapper(t); +} + +} // end of namespace boost + + +#endif // BOOST_TUPLE_REFERENCE_WRAPPERS_HPP diff --git a/include/boost/tuple/tuple.hpp b/include/boost/tuple/tuple.hpp new file mode 100644 index 0000000..bd39730 --- /dev/null +++ b/include/boost/tuple/tuple.hpp @@ -0,0 +1,36 @@ +// tuple.hpp - Boost Tuple Library -------------------------------------- + +// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi) +// +// Permission to copy, use, sell and distribute this software is granted +// provided this copyright notice appears in all copies. +// Permission to modify the code and to distribute modified code is granted +// provided this copyright notice appears in all copies, and a notice +// that the code was modified is included with the copyright notice. +// +// This software is provided "as is" without express or implied warranty, +// and with no claim as to its suitability for any purpose. + +// For more information, see http://www.boost.org + +// ----------------------------------------------------------------- + +#ifndef BOOST_TUPLE_HPP +#define BOOST_TUPLE_HPP + +#include "boost/config.hpp" +#include "boost/static_assert.hpp" + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +// The MSVC version +#include "boost/tuple/detail/tuple_basic_no_partial_spec.hpp" + +#else +// other compilers +#include "boost/tuple/reference_wrappers.hpp" +#include "boost/tuple/detail/tuple_basic.hpp" + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + +#endif // BOOST_TUPLE_HPP diff --git a/include/boost/tuple/tuple_comparison.hpp b/include/boost/tuple/tuple_comparison.hpp new file mode 100644 index 0000000..a34d67d --- /dev/null +++ b/include/boost/tuple/tuple_comparison.hpp @@ -0,0 +1,180 @@ +// tuple_comparison.hpp ----------------------------------------------------- +// +// Copyright (C) 2001 Jaakko Järvi (jaakko.jarvi@cs.utu.fi) +// Copyright (C) 2001 Gary Powell (gary.powell@sierra.com) +// +// Permission to copy, use, sell and distribute this software is granted +// provided this copyright notice appears in all copies. +// Permission to modify the code and to distribute modified code is granted +// provided this copyright notice appears in all copies, and a notice +// that the code was modified is included with the copyright notice. +// +// This software is provided "as is" without express or implied warranty, +// and with no claim as to its suitability for any purpose. +// +// For more information, see http://www.boost.org +// +// (The idea and first impl. of comparison operators was from Doug Gregor) + +// ----------------------------------------------------------------- + +#ifndef BOOST_TUPLE_COMPARISON_HPP +#define BOOST_TUPLE_COMPARISON_HPP + +#include "boost/tuple/tuple.hpp" + +// ------------------------------------------------------------- +// equality and comparison operators +// +// == and != compare tuples elementwise +// <, >, <= and >= use lexicographical ordering +// +// Any operator between tuples of different length fails at compile time +// No dependencies between operators are assumed +// (i.e. !(a=b, a!=b does not imply a==b etc. +// so any weirdnesses of elementary operators are respected). +// +// ------------------------------------------------------------- + + +namespace boost { + +inline bool operator==(const null_type&, const null_type&) { return true; } +inline bool operator>=(const null_type&, const null_type&) { return true; } +inline bool operator<=(const null_type&, const null_type&) { return true; } +inline bool operator!=(const null_type&, const null_type&) { return false; } +inline bool operator<(const null_type&, const null_type&) { return false; } +inline bool operator>(const null_type&, const null_type&) { return false; } + + +namespace detail { +namespace tuples { + // comparison operators check statically the length of its operands and + // delegate the comparing task to the following functions. Hence + // the static check is only made once (should help the compiler). + // These functions assume tuples to be of the same length. + + +template +inline bool eq(const T1& lhs, const T2& rhs) { + return lhs.get_head() == rhs.get_head() && + eq(lhs.get_tail(), rhs.get_tail()); +} +template<> +inline bool eq(const null_type&, const null_type&) { return true; } + +template +inline bool neq(const T1& lhs, const T2& rhs) { + return lhs.get_head() != rhs.get_head() || + neq(lhs.get_tail(), rhs.get_tail()); +} +template<> +inline bool neq(const null_type&, const null_type&) { return true; } + +template +inline bool lt(const T1& lhs, const T2& rhs) { + return lhs.get_head() < rhs.get_head() || + !(rhs.get_head() < lhs.get_head()) && + lt(lhs.get_tail(), rhs.get_tail()); +} +template<> +inline bool lt(const null_type&, const null_type&) { return false; } + +template +inline bool gt(const T1& lhs, const T2& rhs) { + return lhs.get_head() > rhs.get_head() || + !(rhs.get_head() > lhs.get_head()) && + gt(lhs.get_tail(), rhs.get_tail()); +} +template<> +inline bool gt(const null_type&, const null_type&) { return false; } + +template +inline bool lte(const T1& lhs, const T2& rhs) { + return lhs.get_head() <= rhs.get_head() && + ( !(rhs.get_head() <= lhs.get_head()) || + lte(lhs.get_tail(), rhs.get_tail())); +} +template<> +inline bool lte(const null_type&, const null_type&) { return true; } + +template +inline bool gte(const T1& lhs, const T2& rhs) { + return lhs.get_head() >= rhs.get_head() && + ( !(rhs.get_head() >= lhs.get_head()) || + gte(lhs.get_tail(), rhs.get_tail())); +} +template<> +inline bool gte(const null_type&, const null_type&) { return true; } + +} // end of namespace tuples +} // end of namespace detail + + +// equal ---- + +template +inline bool operator==(const cons& lhs, const cons& rhs) +{ + // check that tuple_lengths are equal + BOOST_STATIC_ASSERT(tuple_length::value == tuple_length::value); + + return detail::tuples::eq(lhs, rhs); +} + +// not equal ----- + +template +inline bool operator!=(const cons& lhs, const cons& rhs) +{ + + // check that tuple_lengths are equal + BOOST_STATIC_ASSERT(tuple_length::value == tuple_length::value); + + return detail::tuples::neq(lhs, rhs); +} + +// < +template +inline bool operator<(const cons& lhs, const cons& rhs) +{ + // check that tuple_lengths are equal + BOOST_STATIC_ASSERT(tuple_length::value == tuple_length::value); + + return detail::tuples::lt(lhs, rhs); +} + +// > +template +inline bool operator>(const cons& lhs, const cons& rhs) +{ + // check that tuple_lengths are equal + BOOST_STATIC_ASSERT(tuple_length::value == tuple_length::value); + + return detail::tuples::gt(lhs, rhs); +} + +// <= +template +inline bool operator<=(const cons& lhs, const cons& rhs) +{ + // check that tuple_lengths are equal + BOOST_STATIC_ASSERT(tuple_length::value == tuple_length::value); + + return detail::tuples::lte(lhs, rhs); +} + +// >= +template +inline bool operator>=(const cons& lhs, const cons& rhs) +{ + // check that tuple_lengths are equal + BOOST_STATIC_ASSERT(tuple_length::value == tuple_length::value); + + return detail::tuples::gte(lhs, rhs); +} + +} // end of namespace boost + + +#endif // BOOST_TUPLE_COMPARISON_HPP diff --git a/include/boost/tuple/tuple_io.hpp b/include/boost/tuple/tuple_io.hpp new file mode 100644 index 0000000..3e8896f --- /dev/null +++ b/include/boost/tuple/tuple_io.hpp @@ -0,0 +1,501 @@ +// tuple_io.hpp -------------------------------------------------------------- + +// Copyright (C) 2001 Jaakko Järvi (jaakko.jarvi@cs.utu.fi) +// 2001 Gary Powell (gary.powell@sierra.com) +// +// Permission to copy, use, sell and distribute this software is granted +// provided this copyright notice appears in all copies. +// Permission to modify the code and to distribute modified code is granted +// provided this copyright notice appears in all copies, and a notice +// that the code was modified is included with the copyright notice. +// +// This software is provided "as is" without express or implied warranty, +// and with no claim as to its suitability for any purpose. +// For more information, see http://www.boost.org + +// ---------------------------------------------------------------------------- + +#ifndef BOOST_TUPLE_IO_HPP +#define BOOST_TUPLE_IO_HPP + + +// add to boost/config.hpp +// for now +# if defined __GNUC__ +# if (__GNUC__ == 2 && __GNUC_MINOR__ <= 97) +#define BOOST_NO_TEMPLATED_STREAMS +#endif +#endif // __GNUC__ + +#if defined BOOST_NO_TEMPLATED_STREAMS +#include +#else +#include +#include +#endif + +#include "boost/tuple/tuple.hpp" + + + +namespace boost { + +namespace detail { +namespace tuples { + +class format_info { +public: + enum manipulator_type { open, close, delimiter }; + BOOST_STATIC_CONSTANT(int, number_of_manipulators = delimiter + 1); +private: + + static const int stream_index[number_of_manipulators]; + format_info(const format_info&); + format_info(); + + +public: + +#if defined (BOOST_NO_TEMPLATED_STREAMS) + static char get_manipulator(std::ios& i, manipulator_type m) { + char c = static_cast(i.iword(stream_index[m])); + + // parentheses and space are the default manipulators + if (!c) { + switch(m) { + case open : c = '('; break; + case close : c = ')'; break; + case delimiter : c = ' '; break; + } + } + return c; + } + + static void set_manipulator(std::ios& i, manipulator_type m, char c) { + i.iword(stream_index[m]) = static_cast(c); + } +#else + template + static CharType get_manipulator(std::basic_ios& i, + manipulator_type m) { + // The manipulators are stored as long. + // A valid instanitation of basic_stream allows CharType to be any POD, + // hence, the static_cast may fail (it fails if long is not convertible + // to CharType + CharType c = static_cast(i.iword(stream_index[m]) ); + // parentheses and space are the default manipulators + if (!c) { + switch(m) { + case open : c = i.widen('('); break; + case close : c = i.widen(')'); break; + case delimiter : c = i.widen(' '); break; + } + } + return c; + } + + + template + static void set_manipulator(std::basic_ios& i, + manipulator_type m, CharType c) { + // The manipulators are stored as long. + // A valid instanitation of basic_stream allows CharType to be any POD, + // hence, the static_cast may fail (it fails if CharType is not + // convertible long. + i.iword(stream_index[m]) = static_cast(c); + } +#endif // BOOST_NO_TEMPLATED_STREAMS +}; + +template +class tuple_manipulator { + const format_info::manipulator_type mt; + CharType f_c; +public: + explicit tuple_manipulator(format_info::manipulator_type m, const char c = 0) + : mt(m), f_c(c) {} + +#if defined (BOOST_NO_TEMPLATED_STREAMS) + void set(std::ios &io) const { + format_info::set_manipulator(io, mt, f_c); + } +#else +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + template + void set(std::basic_ios &io) const { + format_info::set_manipulator(io, mt, f_c); + } +#else + template + void set(std::basic_ios &io) const { + format_info::set_manipulator(io, mt, f_c); + } +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +#endif // BOOST_NO_TEMPLATED_STREAMS +}; + +} // end of namespace tuples +} // end of namespace detail + + +#if defined (BOOST_NO_TEMPLATED_STREAMS) +inline std::ostream& +operator<<(std::ostream& o, const detail::tuples::tuple_manipulator& m) { + m.set(o); + return o; +} + +inline std::istream& +operator>>(std::istream& i, const detail::tuples::tuple_manipulator& m) { + m.set(i); + return i; +} + +#else + +template +inline std::basic_ostream& +operator<<(std::basic_ostream& o, const detail::tuples::tuple_manipulator& m) { + m.set(o); + return o; +} + +template +inline std::basic_istream& +operator>>(std::basic_istream& i, const detail::tuples::tuple_manipulator& m) { + m.set(i); + return i; +} + +#endif // BOOST_NO_TEMPLATED_STREAMS + +template +inline detail::tuples::tuple_manipulator set_open(const CharType c) { + return detail::tuples::tuple_manipulator(detail::tuples::format_info::open, c); +} + +template +inline detail::tuples::tuple_manipulator set_close(const CharType c) { + return detail::tuples::tuple_manipulator(detail::tuples::format_info::close, c); +} + +template +inline detail::tuples::tuple_manipulator set_delimiter(const CharType c) { + return detail::tuples::tuple_manipulator(detail::tuples::format_info::delimiter, c); +} + + + + + +// ------------------------------------------------------------- +// printing tuples to ostream in format (a b c) +// parentheses and space are defaults, but can be overriden with manipulators +// set_open, set_close and set_delimiter + +namespace detail { +namespace tuples { + +// Note: The order of the print functions is critical +// to let a conforming compiler find and select the correct one. + +#if defined (BOOST_NO_TEMPLATED_STREAMS) + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +template +inline std::ostream& print(std::ostream& o, const cons& t) { + return o << t.head; +} +#endif // BOOST_NO_TEMPLATED_STREAMS + +inline std::ostream& print(std::ostream& o, const null_type&) { return o; } + +template +inline std::ostream& +print(std::ostream& o, const cons& t) { + + const char d = format_info::get_manipulator(o, format_info::delimiter); + + o << t.head; + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + if (tuple_length::value == 0) + return o; +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + o << d; + + return print(o, t.tail ); + +} + + + +#else + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +template +inline std::basic_ostream& +print(std::basic_ostream& o, const cons& t) { + return o << t.head; +} +#endif // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + +template +inline std::basic_ostream& +print(std::basic_ostream& o, const null_type&) { + return o; +} + +template +inline std::basic_ostream& +print(std::basic_ostream& o, const cons& t) { + + const CharType d = format_info::get_manipulator(o, format_info::delimiter); + + o << t.head; + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + if (tuple_length::value == 0) + return o; +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + o << d; + + return print(o, t.tail); +} + +#endif // BOOST_NO_TEMPLATED_STREAMS + +} // namespace tuples +} // namespace detail + +#if defined (BOOST_NO_TEMPLATED_STREAMS) +template +inline std::ostream& operator<<(std::ostream& o, const cons& t) { + if (!o.good() ) return o; + + const char l = + detail::tuples::format_info::get_manipulator(o, detail::tuples::format_info::open); + const char r = + detail::tuples::format_info::get_manipulator(o, detail::tuples::format_info::close); + + o << l; + + detail::tuples::print(o, t); + + o << r; + + return o; +} + +#else + +template +inline std::basic_ostream& +operator<<(std::basic_ostream& o, + const cons& t) { + if (!o.good() ) return o; + + const CharType l = + detail::tuples::format_info::get_manipulator(o, detail::tuples::format_info::open); + const CharType r = + detail::tuples::format_info::get_manipulator(o, detail::tuples::format_info::close); + + o << l; + + detail::tuples::print(o, t); + + o << r; + + return o; +} +#endif // BOOST_NO_TEMPLATED_STREAMS + + +// ------------------------------------------------------------- +// input stream operators + +namespace detail { +namespace tuples { + +#if defined (BOOST_NO_TEMPLATED_STREAMS) + +inline std::istream& +extract_and_check_delimiter( + std::istream& is, format_info::manipulator_type del) +{ + const char d = format_info::get_manipulator(is, del); + + const bool is_delimiter = (!isspace(d) ); + + char c; + if (is_delimiter) { + is >> c; + if (c!=d) { + is.setstate(std::ios::failbit); + } + } + return is; +} + + +// Note: The order of the read functions is critical to let a +// (conforming?) compiler find and select the correct one. + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +template +inline std::istream & +read (std::istream &is, cons& t1) { + + if (!is.good()) return is; + + return is >> t1.head ; +} +#else +inline std::istream& read(std::istream& i, const null_type&) { return i; } +#endif // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +template +inline std::istream& +read(std::istream &is, cons& t1) { + + if (!is.good()) return is; + + is >> t1.head; + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + if (tuple_length::value == 0) + return is; +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + extract_and_check_delimiter(is, format_info::delimiter); + + return read(is, t1.tail); +} + +} // end namespace tuples +} // end namespace detail + +inline std::istream& +operator>>(std::istream &is, null_type&) { + + if (!is.good() ) return is; + + detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::open); + detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::close); + + return is; +} + + +template +inline std::istream& +operator>>(std::istream& is, cons& t1) { + + if (!is.good() ) return is; + + detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::open); + + detail::tuples::read(is, t1); + + detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::close); + + return is; +} + + + +#else + +template +inline std::basic_istream& +extract_and_check_delimiter( + std::basic_istream &is, format_info::manipulator_type del) +{ + const CharType d = format_info::get_manipulator(is, del); + + const bool is_delimiter = (!isspace(d) ); + + CharType c; + if (is_delimiter) { + is >> c; + if (c!=d) { + is.setstate(std::ios::failbit); + } + } + return is; +} + + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +template +inline std::basic_istream & +read (std::basic_istream &is, cons& t1) { + + if (!is.good()) return is; + + return is >> t1.head; +} +#else +template +inline std::basic_istream& +read(std::basic_istream& i, const null_type&) { return i; } + +#endif // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +template +inline std::basic_istream& +read(std::basic_istream &is, cons& t1) { + + if (!is.good()) return is; + + is >> t1.head; + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + if (tuple_length::value == 0) + return is; +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + extract_and_check_delimiter(is, format_info::delimiter); + + return read(is, t1.tail); +} + +} // end namespace tuples +} // end namespace detail + + +template +inline std::basic_istream& +operator>>(std::basic_istream &is, null_type&) { + + if (!is.good() ) return is; + + detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::open); + detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::close); + + return is; +} + +template +inline std::basic_istream& +operator>>(std::basic_istream& is, cons& t1) { + + if (!is.good() ) return is; + + detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::open); + + detail::tuples::read(is, t1); + + detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::close); + + return is; +} + +#endif // BOOST_NO_TEMPLATED_STREAMS + +} // end of namespace boost + +#endif // BOOST_TUPLE_IO_HPP + +