This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Updating tuple to draft technical report


This update include/tr1/tuple brings tuple up to tr1 standard.

The parts just involving std::pair have moved to utility, the reference_wrapper has moved to functional. Therefore two new headers have been introduced.

One important note is that the reference_wrapper in functional is NOT complete. This is a slightly neatened up copy of the version which was previously in the tuple specification and does not implement the full extent of "2.1 Reference Wrappers" in the draft technical report. This is mainly because I suspect implementing this header will become much easier once the type_traits have been implemented (even just the compiler-indepedant ones). If anyone else who is better at template metaprogramming than me (not too hard) thinks implementing this is easy, then be my guest :)

Chris




2004-11-21  Chris Jefferson  <chris@bubblescope.net>

	* include/tr1/tuple(operator!=): Change operator 
	definition to match (draft) technical report.
	(operator>): Same.
	(operator<=): Same.
	(operator>=): Same.
	(ref): Move to include/tr1/functional.
	(cref): Same.
	(tuple_size<pair>): Move to include/tr1/utility.
	(tuple_element<,pair>): Same.
	* include/tr1/functional: New.
	* include/tr1/utility: New.
	* testsuite/tr1/6_container/utility/pair.cc: New.
// TR1 functional header -*- C++ -*-

// Copyright (C) 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING.  If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.


#ifndef _TR1_FUNCTIONAL
#define _TR1_FUNCTIONAL 1

#include"../functional"

namespace std
{
namespace tr1
{

  template<typename _Tp>
  class reference_wrapper
  {
    _Tp* _M_data;
  public:
    typedef _Tp type;
    explicit reference_wrapper(_Tp& __indata): _M_data(&__indata)
    { }
    
    reference_wrapper(const reference_wrapper<_Tp>& __inref):
      _M_data(__inref._M_data)
    { }

    reference_wrapper& 
    operator=(const reference_wrapper<_Tp>& __inref)
    {
      _M_data = __inref._M_data;
      return *this;
    }

    operator _Tp& () const
    {
      return this->get();
    }
    
    _Tp&
    get() const
    {
      return *_M_data;
    }
  };
  
  // Denotes a reference should be taken to a variable.
  template<typename _Tp>
    reference_wrapper<_Tp>
    ref(_Tp& __t)
    { return reference_wrapper<_Tp>(__t); }
  
  // Denotes a const reference should be taken to a variable.
  template<typename _Tp>
    reference_wrapper<const _Tp>
    cref(const _Tp& __t)
    { return reference_wrapper<const _Tp>(__t); }

  template<typename _Tp>
    reference_wrapper<_Tp> ref(reference_wrapper<_Tp> __t)
    { return ref(__t.get()); }

  template<typename _Tp>
    reference_wrapper<const _Tp> cref(reference_wrapper<_Tp> __t)
    { return cref(__t.get()); }

}
}

#endif

// TR1 utility -*- C++ -*-

// Copyright (C) 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING.  If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.

#ifndef _TR1_UTILITY
#define _TR1_UTILITY
#include "../utility"

namespace std
{
namespace tr1
{
  template<class _Tp> class tuple_size;
  template<int _Int, class _Tp> class tuple_element;

   // Various functions which give std::pair a tuple-like interface.
  template<class _Tp1, class _Tp2>
    struct tuple_size<std::pair<_Tp1, _Tp2> >
    { static const int value = 2; };
 
  template<class _Tp1, class _Tp2>
    struct tuple_element<0, std::pair<_Tp1, _Tp2> >
    { typedef _Tp1 type; };
 
  template<class _Tp1, class _Tp2>
    struct tuple_element<1, std::pair<_Tp1, _Tp2> >
    { typedef _Tp2 type; };
 

  template<int _Int> struct __pair_get;

  template<>
    struct __pair_get<0>
    {
      template<typename _Tp1, typename _Tp2>
      static _Tp1& __get(std::pair<_Tp1, _Tp2>& __pair)
      { return __pair.first; }

      template<typename _Tp1, typename _Tp2>
      static const _Tp1& __const_get(const std::pair<_Tp1, _Tp2>& __pair)
      { return __pair.first; }
    };

  template<>
    struct __pair_get<1>
    {
      template<typename _Tp1, typename _Tp2>
      static _Tp1& __get(std::pair<_Tp1, _Tp2>& __pair)
      { return __pair.second; }

      template<typename _Tp1, typename _Tp2>
      static const _Tp1& __const_get(const std::pair<_Tp1, _Tp2>& __pair)
      { return __pair.second; }
    };

   template<int _I, class _Tp1, class _Tp2>
     typename tuple_element<_I, std::pair<_Tp1, _Tp2> >::type&
     get(pair<_Tp1, _Tp2>& __in)
     { return __pair_get<_I>::__get(__in); }
 
   template<int _I, class _Tp1, class _Tp2>
     const typename tuple_element<_I, std::pair<_Tp1, _Tp2> >::type&
     get(const pair<_Tp1, _Tp2>& __in)
     { return __pair_get<_I>::__const_get(__in); }
}
} 

#endif
Index: libstdc++-v3/include/tr1/tuple
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/tr1/tuple,v
retrieving revision 1.4
diff -p -c -3 -r1.4 tuple
*** libstdc++-v3/include/tr1/tuple	5 Nov 2004 19:58:03 -0000	1.4
--- libstdc++-v3/include/tr1/tuple	21 Nov 2004 15:47:57 -0000
***************
*** 25,31 ****
  #ifndef _TUPLE
  #define _TUPLE 1
  
! #include<utility>
  
  namespace std
  {
--- 25,32 ----
  #ifndef _TUPLE
  #define _TUPLE 1
  
! #include"utility"
! #include"functional"
  
  namespace std
  {
*************** namespace tr1
*** 35,41 ****
    // when the tuple is not maximum possible size.
    struct _NullClass { };
  
!   /// @brief  Foward definition of the tuple class.
    template<typename _Tp0 = _NullClass, typename _Tp1 = _NullClass,
  	   typename _Tp2 = _NullClass, typename _Tp3 = _NullClass,
  	   typename _Tp4 = _NullClass, typename _Tp5 = _NullClass,
--- 36,42 ----
    // when the tuple is not maximum possible size.
    struct _NullClass { };
  
!   /// @brief  Forward definition of the tuple class
    template<typename _Tp0 = _NullClass, typename _Tp1 = _NullClass,
  	   typename _Tp2 = _NullClass, typename _Tp3 = _NullClass,
  	   typename _Tp4 = _NullClass, typename _Tp5 = _NullClass,
*************** namespace tr1
*** 1086,1116 ****
          return get<__i>(__t) == get<__i>(__u) &&
             __tuple_compare<0, __i+1, __j, _Tp, _Up>::__eq(__t, __u);
        }
-       static bool __neq(const _Tp& __t, const _Up& __u)
-       {
-         return get<__i>(__t) != get<__i>(__u) ||
-            __tuple_compare<0, __i+1, __j, _Tp, _Up>::__neq(__t, __u);
-       }
        static bool __less(const _Tp& __t, const _Up& __u)
        {
          return (get<__i>(__t) < get<__i>(__u)) || !(get<__i>(__u) < get<__i>(__t)) &&
             __tuple_compare<0, __i+1, __j, _Tp, _Up>::__less(__t, __u);
        }
-       static bool __greater(const _Tp& __t, const _Up& __u)
-       {
-         return (get<__i>(__t) > get<__i>(__u)) || !(get<__i>(__u) > get<__i>(__t)) &&
-            __tuple_compare<0, __i+1, __j, _Tp, _Up>::__greater(__t, __u);
-       }
-       static bool __leq(const _Tp& __t, const _Up& __u)
-       {
-         return (get<__i>(__t) <= get<__i>(__u)) && (!(get<__i>(__u)<=get<__i>(__t)) ||
-         					   __tuple_compare<0, __i+1, __j, _Tp, _Up>::__leq(__t, __u));
-       }
-       static bool __geq(const _Tp& __t, const _Up& __u)
-       {
-         return (get<__i>(__t) >= get<__i>(__u)) && (!(get<__i>(__u)>=get<__i>(__t)) ||
-         					   __tuple_compare<0, __i+1, __j, _Tp, _Up>::__geq(__t, __u));
-       }
      };
  
    template<int __i, typename _Tp, typename _Up>
--- 1087,1097 ----
*************** namespace tr1
*** 1118,1133 ****
      {
        static bool __eq(const _Tp&, const _Up&)
        { return true; }
-       static bool __neq(const _Tp&, const _Up&)
-       { return false; }
-       static bool __leq(const _Tp&, const _Up&)
-       { return true; }
-       static bool __geq(const _Tp&, const _Up&)
-       { return true; }
        static bool __less(const _Tp&, const _Up&)
        { return false; }
-       static bool __greater(const _Tp&, const _Up&)
-       { return false; }
      };
  
    template<typename _Tp0, typename _Tp1, typename _Tp2, typename _Tp3,
--- 1099,1106 ----
*************** namespace tr1
*** 1140,1151 ****
  	     const tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8, _Up9>& __u)
    {
      typedef tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8,
! 		  _Tp9> __t_tuple;
      typedef tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8,
! 		  _Up9> __u_tuple;
!     return __tuple_compare<tuple_size<__t_tuple>::value -
!      tuple_size<__u_tuple>::value, 0,
!       tuple_size<__t_tuple>::value, __t_tuple, __u_tuple>::__eq(__t, __u);
    }
  
    template<typename _Tp0, typename _Tp1, typename _Tp2, typename _Tp3,
--- 1113,1124 ----
  	     const tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8, _Up9>& __u)
    {
      typedef tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8,
! 		  _Tp9> _Tp;
      typedef tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8,
! 		  _Up9> _Up;
!     return __tuple_compare<tuple_size<_Tp>::value -
!      tuple_size<_Tp>::value, 0,
!       tuple_size<_Tp>::value, _Tp, _Up>::__eq(__t, __u);
    }
  
    template<typename _Tp0, typename _Tp1, typename _Tp2, typename _Tp3,
*************** namespace tr1
*** 1154,1169 ****
  	   typename _Up2, typename _Up3, typename _Up4, typename _Up5,
  	   typename _Up6, typename _Up7, typename _Up8, typename _Up9>
    bool
!   operator!=(const tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8, _Tp9>& __t,
! 	     const tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8, _Up9>& __u)
    {
      typedef tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8,
! 		  _Tp9> __t_tuple;
      typedef tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8,
! 		  _Up9> __u_tuple;
!     return __tuple_compare<tuple_size<__t_tuple>::value -
!      tuple_size<__u_tuple>::value, 0,
!       tuple_size<__t_tuple>::value, __t_tuple, __u_tuple>::__neq(__t, __u);
    }
  
    template<typename _Tp0, typename _Tp1, typename _Tp2, typename _Tp3,
--- 1127,1142 ----
  	   typename _Up2, typename _Up3, typename _Up4, typename _Up5,
  	   typename _Up6, typename _Up7, typename _Up8, typename _Up9>
    bool
!   operator<(const tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8, _Tp9>& __t,
! 	    const tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8, _Up9>& __u)
    {
      typedef tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8,
! 		  _Tp9> _Tp;
      typedef tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8,
! 		  _Up9> _Up;
!     return __tuple_compare<tuple_size<_Tp>::value -
!      tuple_size<_Tp>::value, 0,
!       tuple_size<_Tp>::value, _Tp, _Up>::__less(__t, __u);
    }
  
    template<typename _Tp0, typename _Tp1, typename _Tp2, typename _Tp3,
*************** namespace tr1
*** 1172,1189 ****
  	   typename _Up2, typename _Up3, typename _Up4, typename _Up5,
  	   typename _Up6, typename _Up7, typename _Up8, typename _Up9>
    bool
!   operator<(const tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8, _Tp9>& __t,
! 	    const tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8, _Up9>& __u)
    {
!     typedef tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8,
! 		  _Tp9> __t_tuple;
!     typedef tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8,
! 		  _Up9> __u_tuple;
!     return __tuple_compare<tuple_size<__t_tuple>::value -
!      tuple_size<__u_tuple>::value, 0,
!       tuple_size<__t_tuple>::value, __t_tuple, __u_tuple>::__less(__t, __u);
    }
- 
    template<typename _Tp0, typename _Tp1, typename _Tp2, typename _Tp3,
  	   typename _Tp4, typename _Tp5, typename _Tp6, typename _Tp7,
  	   typename _Tp8, typename _Tp9, typename _Up0, typename _Up1,
--- 1145,1155 ----
  	   typename _Up2, typename _Up3, typename _Up4, typename _Up5,
  	   typename _Up6, typename _Up7, typename _Up8, typename _Up9>
    bool
!   operator!=(const tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8, _Tp9>& __t,
! 	     const tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8, _Up9>& __u)
    {
!       return !(__t == __u);
    }
    template<typename _Tp0, typename _Tp1, typename _Tp2, typename _Tp3,
  	   typename _Tp4, typename _Tp5, typename _Tp6, typename _Tp7,
  	   typename _Tp8, typename _Tp9, typename _Up0, typename _Up1,
*************** namespace tr1
*** 1193,1207 ****
    operator>(const tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8, _Tp9>& __t,
  	    const tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8, _Up9>& __u)
    {
!     typedef tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8,
! 		  _Tp9> __t_tuple;
!     typedef tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8,
! 		  _Up9> __u_tuple;
!     return __tuple_compare<tuple_size<__t_tuple>::value -
!      tuple_size<__u_tuple>::value, 0,
!       tuple_size<__t_tuple>::value, __t_tuple, __u_tuple>::__greater(__t, __u);
    }
- 
    template<typename _Tp0, typename _Tp1, typename _Tp2, typename _Tp3,
  	   typename _Tp4, typename _Tp5, typename _Tp6, typename _Tp7,
  	   typename _Tp8, typename _Tp9, typename _Up0, typename _Up1,
--- 1159,1166 ----
    operator>(const tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8, _Tp9>& __t,
  	    const tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8, _Up9>& __u)
    {
!       return __u < __t;
    }
    template<typename _Tp0, typename _Tp1, typename _Tp2, typename _Tp3,
  	   typename _Tp4, typename _Tp5, typename _Tp6, typename _Tp7,
  	   typename _Tp8, typename _Tp9, typename _Up0, typename _Up1,
*************** namespace tr1
*** 1211,1225 ****
    operator<=(const tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8, _Tp9>& __t,
  	     const tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8, _Up9>& __u)
    {
!     typedef tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8,
! 		  _Tp9> __t_tuple;
!     typedef tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8,
! 		  _Up9> __u_tuple;
!     return __tuple_compare<tuple_size<__t_tuple>::value -
!      tuple_size<__u_tuple>::value, 0,
!       tuple_size<__t_tuple>::value, __t_tuple, __u_tuple>::__leq(__t, __u);
    }
- 
    template<typename _Tp0, typename _Tp1, typename _Tp2, typename _Tp3,
  	   typename _Tp4, typename _Tp5, typename _Tp6, typename _Tp7,
  	   typename _Tp8, typename _Tp9, typename _Up0, typename _Up1,
--- 1170,1177 ----
    operator<=(const tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8, _Tp9>& __t,
  	     const tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8, _Up9>& __u)
    {
!       return !(__u < __t);
    }
    template<typename _Tp0, typename _Tp1, typename _Tp2, typename _Tp3,
  	   typename _Tp4, typename _Tp5, typename _Tp6, typename _Tp7,
  	   typename _Tp8, typename _Tp9, typename _Up0, typename _Up1,
*************** namespace tr1
*** 1229,1282 ****
    operator>=(const tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8, _Tp9>& __t,
  	     const tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8, _Up9>& __u)
    {
!     typedef tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8,
! 		  _Tp9> __t_tuple;
!     typedef tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8,
! 		  _Up9> __u_tuple;
!     return __tuple_compare<tuple_size<__t_tuple>::value -
!      tuple_size<__u_tuple>::value, 0,
!       tuple_size<__t_tuple>::value, __t_tuple, __u_tuple>::__geq(__t, __u);
    }
- 
-   // Provides a way to annotate that a reference to
-   // an object should be passed.
-   template<typename _Tp>
-     class reference_wrapper
-     {
-       _Tp& _M_data;
-       public:
-         typedef _Tp type;
-         explicit reference_wrapper(_Tp& __indata): _M_data(__indata)
-         { }
- 
-         operator _Tp& () const
-         {
- 	  return this->get();
-         }
- 
-         _Tp&
-         get() const
-         {
- 	  return _M_data;
-         }
-     };
- 
-   // Denotes a reference should be taken to a variable.
-   template<typename _Tp>
-     reference_wrapper<_Tp>
-     ref(_Tp& __t)
-     {
-       return reference_wrapper<_Tp>(__t);
-     }
- 
-   // Denotes a const reference should be taken to a variable.
-   template<typename _Tp>
-     reference_wrapper<_Tp const>
-     cref(const _Tp& __t)
-     {
-       return reference_wrapper<_Tp const>(__t);
-     }
- 
    // Helper which adds a reference to a type when given a reference_wrapper
    template<typename _Tp>
      struct __strip_reference_wrapper
--- 1181,1188 ----
    operator>=(const tuple<_Tp0, _Tp1, _Tp2, _Tp3, _Tp4, _Tp5, _Tp6, _Tp7, _Tp8, _Tp9>& __t,
  	     const tuple<_Up0, _Up1, _Up2, _Up3, _Up4, _Up5, _Up6, _Up7, _Up8, _Up9>& __u)
    {
!       return !(__t < __u);
    }
    // Helper which adds a reference to a type when given a reference_wrapper
    template<typename _Tp>
      struct __strip_reference_wrapper
*************** namespace tr1
*** 1532,1560 ****
  		        ref(__t9));
      };
  
-   // Various functions which give std::pair a tuple-like interface.
-   template<class _Tp1, class _Tp2>
-     struct tuple_size<std::pair<_Tp1, _Tp2> >
-     { static const int value = 2; };
- 
-   template<class _Tp1, class _Tp2>
-     struct tuple_element<0, std::pair<_Tp1, _Tp2> >
-     { typedef _Tp1 type; };
- 
-   template<class _Tp1, class _Tp2>
-     struct tuple_element<1, std::pair<_Tp1, _Tp2> >
-     { typedef _Tp2 type; };
- 
-   template<int _Int, class _Tp1, class _Tp2>
-     typename tuple_element<_Int, tuple<_Tp1, _Tp2> >::type
-     get(pair<_Tp1, _Tp2>& __in)
-     { return get<_Int>(tie(__in.first, __in.second)); }
- 
-   template<int _Int, class _Tp1, class _Tp2>
-     typename tuple_element<_Int, tuple<_Tp1, _Tp2> >::type
-     get(const pair<_Tp1, _Tp2>& __in)
-     { return get<_Int>(tie(__in.first, __in.second)); }
- 
  }
  }
  
--- 1438,1443 ----

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]