epoc32/include/stdapis/boost/multi_index/member.hpp
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:33:34 +0100
branchSymbian3
changeset 4 837f303aceeb
permissions -rw-r--r--
Current Symbian^3 public API header files (from PDK 3.0.h)
This is the epoc32/include tree with the "platform" subtrees removed, and
all but a selected few mbg and rsg files removed.
     1 /* Copyright 2003-2006 Joaquín M López Muñoz.
     2  * Distributed under the Boost Software License, Version 1.0.
     3  * (See accompanying file LICENSE_1_0.txt or copy at
     4  * http://www.boost.org/LICENSE_1_0.txt)
     5  *
     6  * See http://www.boost.org/libs/multi_index for library home page.
     7  */
     8 
     9 #ifndef BOOST_MULTI_INDEX_MEMBER_HPP
    10 #define BOOST_MULTI_INDEX_MEMBER_HPP
    11 
    12 #if defined(_MSC_VER)&&(_MSC_VER>=1200)
    13 #pragma once
    14 #endif
    15 
    16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
    17 #include <boost/mpl/if.hpp>
    18 #include <boost/type_traits/is_const.hpp>
    19 #include <boost/utility/enable_if.hpp>
    20 #include <cstddef>
    21 
    22 #if !defined(BOOST_NO_SFINAE)
    23 #include <boost/type_traits/is_convertible.hpp>
    24 #endif
    25 
    26 namespace boost{
    27 
    28 template<class T> class reference_wrapper; /* fwd decl. */
    29 
    30 namespace multi_index{
    31 
    32 namespace detail{
    33 
    34 /* member is a read/write key extractor for accessing a given
    35  * member of a class.
    36  * Additionally, member is overloaded to support referece_wrappers
    37  * of T and "chained pointers" to T's. By chained pointer to T we mean
    38  * a type P  such that, given a p of Type P
    39  *   *...n...*x is convertible to T&, for some n>=1.
    40  * Examples of chained pointers are raw and smart pointers, iterators and
    41  * arbitrary combinations of these (vg. T** or auto_ptr<T*>.)
    42  */
    43 
    44 /* NB. Some overloads of operator() have an extra dummy parameter int=0.
    45  * This disambiguator serves several purposes:
    46  *  - Without it, MSVC++ 6.0 incorrectly regards some overloads as
    47  *    specializations of a previous member function template.
    48  *  - MSVC++ 6.0/7.0 seem to incorrectly treat some different memfuns
    49  *    as if they have the same signature.
    50  *  - If remove_const is broken due to lack of PTS, int=0 avoids the
    51  *    declaration of memfuns with identical signature.
    52  */
    53 
    54 template<class Class,typename Type,Type Class::*PtrToMember>
    55 struct const_member_base
    56 {
    57   typedef Type result_type;
    58 
    59   template<typename ChainedPtr>
    60 
    61 #if !defined(BOOST_NO_SFINAE)
    62   typename disable_if<
    63     is_convertible<const ChainedPtr&,const Class&>,Type&>::type
    64 #else
    65   Type&
    66 #endif
    67   
    68   operator()(const ChainedPtr& x)const
    69   {
    70     return operator()(*x);
    71   }
    72 
    73   Type& operator()(const Class& x)const
    74   {
    75     return x.*PtrToMember;
    76   }
    77 
    78   Type& operator()(const reference_wrapper<const Class>& x)const
    79   {
    80     return operator()(x.get());
    81   }
    82 
    83   Type& operator()(const reference_wrapper<Class>& x,int=0)const
    84   { 
    85     return operator()(x.get());
    86   }
    87 };
    88 
    89 template<class Class,typename Type,Type Class::*PtrToMember>
    90 struct non_const_member_base
    91 {
    92   typedef Type result_type;
    93 
    94   template<typename ChainedPtr>
    95 
    96 #if !defined(BOOST_NO_SFINAE)
    97   typename disable_if<
    98     is_convertible<const ChainedPtr&,const Class&>,Type&>::type
    99 #else
   100   Type&
   101 #endif
   102 
   103   operator()(const ChainedPtr& x)const
   104   {
   105     return operator()(*x);
   106   }
   107 
   108   const Type& operator()(const Class& x,int=0)const
   109   {
   110     return x.*PtrToMember;
   111   }
   112 
   113   Type& operator()(Class& x)const
   114   { 
   115     return x.*PtrToMember;
   116   }
   117 
   118   const Type& operator()(const reference_wrapper<const Class>& x,int=0)const
   119   {
   120     return operator()(x.get());
   121   }
   122 
   123   Type& operator()(const reference_wrapper<Class>& x)const
   124   { 
   125     return operator()(x.get());
   126   }
   127 };
   128 
   129 } /* namespace multi_index::detail */
   130 
   131 template<class Class,typename Type,Type Class::*PtrToMember>
   132 struct member:
   133   mpl::if_c<
   134     is_const<Type>::value,
   135     detail::const_member_base<Class,Type,PtrToMember>,
   136     detail::non_const_member_base<Class,Type,PtrToMember>
   137   >::type
   138 {
   139 };
   140 
   141 namespace detail{
   142 
   143 /* MSVC++ 6.0 does not support properly pointers to members as
   144  * non-type template arguments, as reported in
   145  *   http://support.microsoft.com/default.aspx?scid=kb;EN-US;249045
   146  * A similar problem (though not identical) is shown by MSVC++ 7.0.
   147  * We provide an alternative to member<> accepting offsets instead
   148  * of pointers to members. This happens to work even for non-POD
   149  * types (although the standard forbids use of offsetof on these),
   150  * so it serves as a workaround in this compiler for all practical
   151  * purposes.
   152  * Surprisingly enough, other compilers, like Intel C++ 7.0/7.1 and
   153  * Visual Age 6.0, have similar bugs. This replacement of member<>
   154  * can be used for them too.
   155  */
   156 
   157 template<class Class,typename Type,std::size_t OffsetOfMember>
   158 struct const_member_offset_base
   159 {
   160   typedef Type result_type;
   161 
   162   template<typename ChainedPtr>
   163 
   164 #if !defined(BOOST_NO_SFINAE)
   165   typename disable_if<
   166     is_convertible<const ChainedPtr&,const Class&>,Type&>::type
   167 #else
   168   Type&
   169 #endif 
   170     
   171   operator()(const ChainedPtr& x)const
   172   {
   173     return operator()(*x);
   174   }
   175 
   176   Type& operator()(const Class& x)const
   177   {
   178     return *static_cast<const Type*>(
   179       static_cast<const void*>(
   180         static_cast<const char*>(
   181           static_cast<const void *>(&x))+OffsetOfMember));
   182   }
   183 
   184   Type& operator()(const reference_wrapper<const Class>& x)const
   185   {
   186     return operator()(x.get());
   187   }
   188 
   189   Type& operator()(const reference_wrapper<Class>& x,int=0)const
   190   {
   191     return operator()(x.get());
   192   }
   193 };
   194 
   195 template<class Class,typename Type,std::size_t OffsetOfMember>
   196 struct non_const_member_offset_base
   197 {
   198   typedef Type result_type;
   199 
   200   template<typename ChainedPtr>
   201 
   202 #if !defined(BOOST_NO_SFINAE)
   203   typename disable_if<
   204     is_convertible<const ChainedPtr&,const Class&>,Type&>::type
   205 #else
   206   Type&
   207 #endif 
   208   
   209   operator()(const ChainedPtr& x)const
   210   {
   211     return operator()(*x);
   212   }
   213 
   214   const Type& operator()(const Class& x,int=0)const
   215   {
   216     return *static_cast<const Type*>(
   217       static_cast<const void*>(
   218         static_cast<const char*>(
   219           static_cast<const void *>(&x))+OffsetOfMember));
   220   }
   221 
   222   Type& operator()(Class& x)const
   223   { 
   224     return *static_cast<Type*>(
   225       static_cast<void*>(
   226         static_cast<char*>(static_cast<void *>(&x))+OffsetOfMember));
   227   }
   228 
   229   const Type& operator()(const reference_wrapper<const Class>& x,int=0)const
   230   {
   231     return operator()(x.get());
   232   }
   233 
   234   Type& operator()(const reference_wrapper<Class>& x)const
   235   {
   236     return operator()(x.get());
   237   }
   238 };
   239 
   240 } /* namespace multi_index::detail */
   241 
   242 template<class Class,typename Type,std::size_t OffsetOfMember>
   243 struct member_offset:
   244   mpl::if_c<
   245     is_const<Type>::value,
   246     detail::const_member_offset_base<Class,Type,OffsetOfMember>,
   247     detail::non_const_member_offset_base<Class,Type,OffsetOfMember>
   248   >::type
   249 {
   250 };
   251 
   252 /* BOOST_MULTI_INDEX_MEMBER resolves to member in the normal cases,
   253  * and to member_offset as a workaround in those defective compilers for
   254  * which BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS is defined.
   255  */
   256 
   257 #if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS)
   258 #define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
   259 ::boost::multi_index::member_offset< Class,Type,offsetof(Class,MemberName) >
   260 #else
   261 #define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
   262 ::boost::multi_index::member< Class,Type,&Class::MemberName >
   263 #endif
   264 
   265 } /* namespace multi_index */
   266 
   267 } /* namespace boost */
   268 
   269 #endif