263 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			263 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| /* Copyright 2003-2015 Joaquin M Lopez Munoz.
 | |
|  * Distributed under the Boost Software License, Version 1.0.
 | |
|  * (See accompanying file LICENSE_1_0.txt or copy at
 | |
|  * http://www.boost.org/LICENSE_1_0.txt)
 | |
|  *
 | |
|  * See http://www.boost.org/libs/multi_index for library home page.
 | |
|  */
 | |
| 
 | |
| #ifndef BOOST_MULTI_INDEX_MEMBER_HPP
 | |
| #define BOOST_MULTI_INDEX_MEMBER_HPP
 | |
| 
 | |
| #if defined(_MSC_VER)
 | |
| #pragma once
 | |
| #endif
 | |
| 
 | |
| #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
 | |
| #include <boost/mpl/if.hpp>
 | |
| #include <boost/type_traits/is_const.hpp>
 | |
| #include <boost/utility/enable_if.hpp>
 | |
| #include <cstddef>
 | |
| 
 | |
| #if !defined(BOOST_NO_SFINAE)
 | |
| #include <boost/type_traits/is_convertible.hpp>
 | |
| #endif
 | |
| 
 | |
| namespace boost{
 | |
| 
 | |
| template<class T> class reference_wrapper; /* fwd decl. */
 | |
| 
 | |
| namespace multi_index{
 | |
| 
 | |
| namespace detail{
 | |
| 
 | |
| /* member is a read/write key extractor for accessing a given
 | |
|  * member of a class.
 | |
|  * Additionally, member is overloaded to support referece_wrappers
 | |
|  * of T and "chained pointers" to T's. By chained pointer to T we mean
 | |
|  * a type P  such that, given a p of Type P
 | |
|  *   *...n...*x is convertible to T&, for some n>=1.
 | |
|  * Examples of chained pointers are raw and smart pointers, iterators and
 | |
|  * arbitrary combinations of these (vg. T** or unique_ptr<T*>.)
 | |
|  */
 | |
| 
 | |
| template<class Class,typename Type,Type Class::*PtrToMember>
 | |
| struct const_member_base
 | |
| {
 | |
|   typedef Type result_type;
 | |
| 
 | |
|   template<typename ChainedPtr>
 | |
| 
 | |
| #if !defined(BOOST_NO_SFINAE)
 | |
|   typename disable_if<
 | |
|     is_convertible<const ChainedPtr&,const Class&>,Type&>::type
 | |
| #else
 | |
|   Type&
 | |
| #endif
 | |
|   
 | |
|   operator()(const ChainedPtr& x)const
 | |
|   {
 | |
|     return operator()(*x);
 | |
|   }
 | |
| 
 | |
|   Type& operator()(const Class& x)const
 | |
|   {
 | |
|     return x.*PtrToMember;
 | |
|   }
 | |
| 
 | |
|   Type& operator()(const reference_wrapper<const Class>& x)const
 | |
|   {
 | |
|     return operator()(x.get());
 | |
|   }
 | |
| 
 | |
|   Type& operator()(const reference_wrapper<Class>& x)const
 | |
|   { 
 | |
|     return operator()(x.get());
 | |
|   }
 | |
| };
 | |
| 
 | |
| template<class Class,typename Type,Type Class::*PtrToMember>
 | |
| struct non_const_member_base
 | |
| {
 | |
|   typedef Type result_type;
 | |
| 
 | |
|   template<typename ChainedPtr>
 | |
| 
 | |
| #if !defined(BOOST_NO_SFINAE)
 | |
|   typename disable_if<
 | |
|     is_convertible<const ChainedPtr&,const Class&>,Type&>::type
 | |
| #else
 | |
|   Type&
 | |
| #endif
 | |
| 
 | |
|   operator()(const ChainedPtr& x)const
 | |
|   {
 | |
|     return operator()(*x);
 | |
|   }
 | |
| 
 | |
|   const Type& operator()(const Class& x)const
 | |
|   {
 | |
|     return x.*PtrToMember;
 | |
|   }
 | |
| 
 | |
|   Type& operator()(Class& x)const
 | |
|   { 
 | |
|     return x.*PtrToMember;
 | |
|   }
 | |
| 
 | |
|   const Type& operator()(const reference_wrapper<const Class>& x)const
 | |
|   {
 | |
|     return operator()(x.get());
 | |
|   }
 | |
| 
 | |
|   Type& operator()(const reference_wrapper<Class>& x)const
 | |
|   { 
 | |
|     return operator()(x.get());
 | |
|   }
 | |
| };
 | |
| 
 | |
| } /* namespace multi_index::detail */
 | |
| 
 | |
| template<class Class,typename Type,Type Class::*PtrToMember>
 | |
| struct member:
 | |
|   mpl::if_c<
 | |
|     is_const<Type>::value,
 | |
|     detail::const_member_base<Class,Type,PtrToMember>,
 | |
|     detail::non_const_member_base<Class,Type,PtrToMember>
 | |
|   >::type
 | |
| {
 | |
| };
 | |
| 
 | |
| namespace detail{
 | |
| 
 | |
| /* MSVC++ 6.0 does not support properly pointers to members as
 | |
|  * non-type template arguments, as reported in
 | |
|  *   http://support.microsoft.com/default.aspx?scid=kb;EN-US;249045
 | |
|  * A similar problem (though not identical) is shown by MSVC++ 7.0.
 | |
|  * We provide an alternative to member<> accepting offsets instead
 | |
|  * of pointers to members. This happens to work even for non-POD
 | |
|  * types (although the standard forbids use of offsetof on these),
 | |
|  * so it serves as a workaround in this compiler for all practical
 | |
|  * purposes.
 | |
|  * Surprisingly enough, other compilers, like Intel C++ 7.0/7.1 and
 | |
|  * Visual Age 6.0, have similar bugs. This replacement of member<>
 | |
|  * can be used for them too.
 | |
|  *
 | |
|  * Support for such old compilers is dropped and
 | |
|  * [non_]const_member_offset_base is deprecated.
 | |
|  */
 | |
| 
 | |
| template<class Class,typename Type,std::size_t OffsetOfMember>
 | |
| struct const_member_offset_base
 | |
| {
 | |
|   typedef Type result_type;
 | |
| 
 | |
|   template<typename ChainedPtr>
 | |
| 
 | |
| #if !defined(BOOST_NO_SFINAE)
 | |
|   typename disable_if<
 | |
|     is_convertible<const ChainedPtr&,const Class&>,Type&>::type
 | |
| #else
 | |
|   Type&
 | |
| #endif 
 | |
|     
 | |
|   operator()(const ChainedPtr& x)const
 | |
|   {
 | |
|     return operator()(*x);
 | |
|   }
 | |
| 
 | |
|   Type& operator()(const Class& x)const
 | |
|   {
 | |
|     return *static_cast<const Type*>(
 | |
|       static_cast<const void*>(
 | |
|         static_cast<const char*>(
 | |
|           static_cast<const void *>(&x))+OffsetOfMember));
 | |
|   }
 | |
| 
 | |
|   Type& operator()(const reference_wrapper<const Class>& x)const
 | |
|   {
 | |
|     return operator()(x.get());
 | |
|   }
 | |
| 
 | |
|   Type& operator()(const reference_wrapper<Class>& x)const
 | |
|   {
 | |
|     return operator()(x.get());
 | |
|   }
 | |
| };
 | |
| 
 | |
| template<class Class,typename Type,std::size_t OffsetOfMember>
 | |
| struct non_const_member_offset_base
 | |
| {
 | |
|   typedef Type result_type;
 | |
| 
 | |
|   template<typename ChainedPtr>
 | |
| 
 | |
| #if !defined(BOOST_NO_SFINAE)
 | |
|   typename disable_if<
 | |
|     is_convertible<const ChainedPtr&,const Class&>,Type&>::type
 | |
| #else
 | |
|   Type&
 | |
| #endif 
 | |
|   
 | |
|   operator()(const ChainedPtr& x)const
 | |
|   {
 | |
|     return operator()(*x);
 | |
|   }
 | |
| 
 | |
|   const Type& operator()(const Class& x)const
 | |
|   {
 | |
|     return *static_cast<const Type*>(
 | |
|       static_cast<const void*>(
 | |
|         static_cast<const char*>(
 | |
|           static_cast<const void *>(&x))+OffsetOfMember));
 | |
|   }
 | |
| 
 | |
|   Type& operator()(Class& x)const
 | |
|   { 
 | |
|     return *static_cast<Type*>(
 | |
|       static_cast<void*>(
 | |
|         static_cast<char*>(static_cast<void *>(&x))+OffsetOfMember));
 | |
|   }
 | |
| 
 | |
|   const Type& operator()(const reference_wrapper<const Class>& x)const
 | |
|   {
 | |
|     return operator()(x.get());
 | |
|   }
 | |
| 
 | |
|   Type& operator()(const reference_wrapper<Class>& x)const
 | |
|   {
 | |
|     return operator()(x.get());
 | |
|   }
 | |
| };
 | |
| 
 | |
| } /* namespace multi_index::detail */
 | |
| 
 | |
| template<class Class,typename Type,std::size_t OffsetOfMember>
 | |
| struct member_offset:
 | |
|   mpl::if_c<
 | |
|     is_const<Type>::value,
 | |
|     detail::const_member_offset_base<Class,Type,OffsetOfMember>,
 | |
|     detail::non_const_member_offset_base<Class,Type,OffsetOfMember>
 | |
|   >::type
 | |
| {
 | |
| };
 | |
| 
 | |
| /* BOOST_MULTI_INDEX_MEMBER resolves to member in the normal cases,
 | |
|  * and to member_offset as a workaround in those defective compilers for
 | |
|  * which BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS is defined.
 | |
|  */
 | |
| 
 | |
| #if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS)
 | |
| #define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
 | |
| ::boost::multi_index::member_offset< Class,Type,offsetof(Class,MemberName) >
 | |
| #else
 | |
| #define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
 | |
| ::boost::multi_index::member< Class,Type,&Class::MemberName >
 | |
| #endif
 | |
| 
 | |
| } /* namespace multi_index */
 | |
| 
 | |
| } /* namespace boost */
 | |
| 
 | |
| #endif
 | 
