Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:48:21

0001 /* Copyright 2003-2022 Joaquin M Lopez Munoz.
0002  * Distributed under the Boost Software License, Version 1.0.
0003  * (See accompanying file LICENSE_1_0.txt or copy at
0004  * http://www.boost.org/LICENSE_1_0.txt)
0005  *
0006  * See http://www.boost.org/libs/multi_index for library home page.
0007  */
0008 
0009 #ifndef BOOST_MULTI_INDEX_MEMBER_HPP
0010 #define BOOST_MULTI_INDEX_MEMBER_HPP
0011 
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015 
0016 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
0017 #include <boost/core/enable_if.hpp>
0018 #include <boost/mpl/if.hpp>
0019 #include <boost/type_traits/is_const.hpp>
0020 #include <cstddef>
0021 
0022 #if !defined(BOOST_NO_SFINAE)
0023 #include <boost/type_traits/is_convertible.hpp>
0024 #endif
0025 
0026 namespace boost{
0027 
0028 template<class T> class reference_wrapper; /* fwd decl. */
0029 
0030 namespace multi_index{
0031 
0032 namespace detail{
0033 
0034 /* member is a read/write key extractor for accessing a given
0035  * member of a class.
0036  * Additionally, member is overloaded to support referece_wrappers
0037  * of T and "chained pointers" to T's. By chained pointer to T we mean
0038  * a type P  such that, given a p of Type P
0039  *   *...n...*x is convertible to T&, for some n>=1.
0040  * Examples of chained pointers are raw and smart pointers, iterators and
0041  * arbitrary combinations of these (vg. T** or unique_ptr<T*>.)
0042  */
0043 
0044 template<class Class,typename Type,Type Class::*PtrToMember>
0045 struct const_member_base
0046 {
0047   typedef Type result_type;
0048 
0049   template<typename ChainedPtr>
0050 
0051 #if !defined(BOOST_NO_SFINAE)
0052   typename disable_if<
0053     is_convertible<const ChainedPtr&,const Class&>,Type&>::type
0054 #else
0055   Type&
0056 #endif
0057   
0058   operator()(const ChainedPtr& x)const
0059   {
0060     return operator()(*x);
0061   }
0062 
0063   Type& operator()(const Class& x)const
0064   {
0065     return x.*PtrToMember;
0066   }
0067 
0068   Type& operator()(const reference_wrapper<const Class>& x)const
0069   {
0070     return operator()(x.get());
0071   }
0072 
0073   Type& operator()(const reference_wrapper<Class>& x)const
0074   { 
0075     return operator()(x.get());
0076   }
0077 };
0078 
0079 template<class Class,typename Type,Type Class::*PtrToMember>
0080 struct non_const_member_base
0081 {
0082   typedef Type result_type;
0083 
0084   template<typename ChainedPtr>
0085 
0086 #if !defined(BOOST_NO_SFINAE)
0087   typename disable_if<
0088     is_convertible<const ChainedPtr&,const Class&>,Type&>::type
0089 #else
0090   Type&
0091 #endif
0092 
0093   operator()(const ChainedPtr& x)const
0094   {
0095     return operator()(*x);
0096   }
0097 
0098   const Type& operator()(const Class& x)const
0099   {
0100     return x.*PtrToMember;
0101   }
0102 
0103   Type& operator()(Class& x)const
0104   { 
0105     return x.*PtrToMember;
0106   }
0107 
0108   const Type& operator()(const reference_wrapper<const Class>& x)const
0109   {
0110     return operator()(x.get());
0111   }
0112 
0113   Type& operator()(const reference_wrapper<Class>& x)const
0114   { 
0115     return operator()(x.get());
0116   }
0117 };
0118 
0119 } /* namespace multi_index::detail */
0120 
0121 template<class Class,typename Type,Type Class::*PtrToMember>
0122 struct member:
0123   mpl::if_c<
0124     is_const<Type>::value,
0125     detail::const_member_base<Class,Type,PtrToMember>,
0126     detail::non_const_member_base<Class,Type,PtrToMember>
0127   >::type
0128 {
0129 };
0130 
0131 namespace detail{
0132 
0133 /* MSVC++ 6.0 does not support properly pointers to members as
0134  * non-type template arguments, as reported in
0135  *   http://support.microsoft.com/default.aspx?scid=kb;EN-US;249045
0136  * A similar problem (though not identical) is shown by MSVC++ 7.0.
0137  * We provide an alternative to member<> accepting offsets instead
0138  * of pointers to members. This happens to work even for non-POD
0139  * types (although the standard forbids use of offsetof on these),
0140  * so it serves as a workaround in this compiler for all practical
0141  * purposes.
0142  * Surprisingly enough, other compilers, like Intel C++ 7.0/7.1 and
0143  * Visual Age 6.0, have similar bugs. This replacement of member<>
0144  * can be used for them too.
0145  *
0146  * Support for such old compilers is dropped and
0147  * [non_]const_member_offset_base is deprecated.
0148  */
0149 
0150 template<class Class,typename Type,std::size_t OffsetOfMember>
0151 struct const_member_offset_base
0152 {
0153   typedef Type result_type;
0154 
0155   template<typename ChainedPtr>
0156 
0157 #if !defined(BOOST_NO_SFINAE)
0158   typename disable_if<
0159     is_convertible<const ChainedPtr&,const Class&>,Type&>::type
0160 #else
0161   Type&
0162 #endif 
0163     
0164   operator()(const ChainedPtr& x)const
0165   {
0166     return operator()(*x);
0167   }
0168 
0169   Type& operator()(const Class& x)const
0170   {
0171     return *static_cast<const Type*>(
0172       static_cast<const void*>(
0173         static_cast<const char*>(
0174           static_cast<const void *>(&x))+OffsetOfMember));
0175   }
0176 
0177   Type& operator()(const reference_wrapper<const Class>& x)const
0178   {
0179     return operator()(x.get());
0180   }
0181 
0182   Type& operator()(const reference_wrapper<Class>& x)const
0183   {
0184     return operator()(x.get());
0185   }
0186 };
0187 
0188 template<class Class,typename Type,std::size_t OffsetOfMember>
0189 struct non_const_member_offset_base
0190 {
0191   typedef Type result_type;
0192 
0193   template<typename ChainedPtr>
0194 
0195 #if !defined(BOOST_NO_SFINAE)
0196   typename disable_if<
0197     is_convertible<const ChainedPtr&,const Class&>,Type&>::type
0198 #else
0199   Type&
0200 #endif 
0201   
0202   operator()(const ChainedPtr& x)const
0203   {
0204     return operator()(*x);
0205   }
0206 
0207   const Type& operator()(const Class& x)const
0208   {
0209     return *static_cast<const Type*>(
0210       static_cast<const void*>(
0211         static_cast<const char*>(
0212           static_cast<const void *>(&x))+OffsetOfMember));
0213   }
0214 
0215   Type& operator()(Class& x)const
0216   { 
0217     return *static_cast<Type*>(
0218       static_cast<void*>(
0219         static_cast<char*>(static_cast<void *>(&x))+OffsetOfMember));
0220   }
0221 
0222   const Type& operator()(const reference_wrapper<const Class>& x)const
0223   {
0224     return operator()(x.get());
0225   }
0226 
0227   Type& operator()(const reference_wrapper<Class>& x)const
0228   {
0229     return operator()(x.get());
0230   }
0231 };
0232 
0233 } /* namespace multi_index::detail */
0234 
0235 template<class Class,typename Type,std::size_t OffsetOfMember>
0236 struct member_offset:
0237   mpl::if_c<
0238     is_const<Type>::value,
0239     detail::const_member_offset_base<Class,Type,OffsetOfMember>,
0240     detail::non_const_member_offset_base<Class,Type,OffsetOfMember>
0241   >::type
0242 {
0243 };
0244 
0245 /* BOOST_MULTI_INDEX_MEMBER resolves to member in the normal cases,
0246  * and to member_offset as a workaround in those defective compilers for
0247  * which BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS is defined.
0248  */
0249 
0250 #if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS)
0251 #define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
0252 ::boost::multi_index::member_offset< Class,Type,offsetof(Class,MemberName) >
0253 #else
0254 #define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
0255 ::boost::multi_index::member< Class,Type,&Class::MemberName >
0256 #endif
0257 
0258 } /* namespace multi_index */
0259 
0260 } /* namespace boost */
0261 
0262 #endif