summaryrefslogtreecommitdiff
path: root/boost/intrusive/detail/parent_from_member.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/intrusive/detail/parent_from_member.hpp')
-rw-r--r--boost/intrusive/detail/parent_from_member.hpp38
1 files changed, 31 insertions, 7 deletions
diff --git a/boost/intrusive/detail/parent_from_member.hpp b/boost/intrusive/detail/parent_from_member.hpp
index c06d932a70..2afffb47bc 100644
--- a/boost/intrusive/detail/parent_from_member.hpp
+++ b/boost/intrusive/detail/parent_from_member.hpp
@@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2007-2009
+// (C) Copyright Ion Gaztanaga 2007-2012
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -31,29 +31,53 @@ inline std::ptrdiff_t offset_from_pointer_to_member(const Member Parent::* ptr_t
//The implementation of a pointer to member is compiler dependent.
#if defined(BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER)
//msvc compliant compilers use their the first 32 bits as offset (even in 64 bit mode)
- return *(const boost::int32_t*)(void*)&ptr_to_member;
+ union caster_union
+ {
+ const Member Parent::* ptr_to_member;
+ boost::int32_t offset;
+ } caster;
+ caster.ptr_to_member = ptr_to_member;
+ return std::ptrdiff_t(caster.offset);
//This works with gcc, msvc, ac++, ibmcpp
#elif defined(__GNUC__) || defined(__HP_aCC) || defined(BOOST_INTEL) || \
defined(__IBMCPP__) || defined(__DECCXX)
const Parent * const parent = 0;
- const char *const member = reinterpret_cast<const char*>(&(parent->*ptr_to_member));
- return std::ptrdiff_t(member - reinterpret_cast<const char*>(parent));
+ const char *const member = static_cast<const char*>(static_cast<const void*>(&(parent->*ptr_to_member)));
+ return std::ptrdiff_t(member - static_cast<const char*>(static_cast<const void*>(parent)));
#else
//This is the traditional C-front approach: __MWERKS__, __DMC__, __SUNPRO_CC
- return (*(const std::ptrdiff_t*)(void*)&ptr_to_member) - 1;
+ union caster_union
+ {
+ const Member Parent::* ptr_to_member;
+ std::ptrdiff_t offset;
+ } caster;
+ caster.ptr_to_member = ptr_to_member;
+ return caster.offset - 1;
#endif
}
template<class Parent, class Member>
inline Parent *parent_from_member(Member *member, const Member Parent::* ptr_to_member)
{
- return (Parent*)((char*)member - offset_from_pointer_to_member(ptr_to_member));
+ return static_cast<Parent*>
+ (
+ static_cast<void*>
+ (
+ static_cast<char*>(static_cast<void*>(member)) - offset_from_pointer_to_member(ptr_to_member)
+ )
+ );
}
template<class Parent, class Member>
inline const Parent *parent_from_member(const Member *member, const Member Parent::* ptr_to_member)
{
- return (const Parent*)((const char*)member - offset_from_pointer_to_member(ptr_to_member));
+ return static_cast<const Parent*>
+ (
+ static_cast<const void*>
+ (
+ static_cast<const char*>(static_cast<const void*>(member)) - offset_from_pointer_to_member(ptr_to_member)
+ )
+ );
}
} //namespace detail {