epoc32/include/stdapis/boost/multi_index/member.hpp
branchSymbian2
changeset 2 2fe1408b6811
equal deleted inserted replaced
1:666f914201fb 2:2fe1408b6811
       
     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