Уточнающие приведения.
Призванны заменить reinterpret_cast.
Использование:
char* p = pointer_cast<char*>(new int()); // OK
long p = pointer_cast<long>(new int()); // Error
int** p = pointer_cast<int**>(new int()); // Error
char p = safe_reinterpret_cast<char>(new int()); // Скомпилируется или нет зависит от размера char и int*
long p = safe_reinterpret_cast<long>(new int()); // Скомпилируется или нет зависит от размера long и int*
pointer_cast,
safe_reinterpret_cast:
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_volatile.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#ifndef BOOST_NO_SFINAE
#include <boost/utility/enable_if.hpp>
#endif // !BOOST_NO_SFINAE
// pointer_arity
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<typename T>
struct pointer_arity
{
BOOST_STATIC_CONSTANT(size_t, value = 0);
};
template<typename T>
struct pointer_arity<T*>
{
BOOST_STATIC_CONSTANT(size_t, value = 1 + pointer_arity<T>::value);
};
#endif // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// pointer_cast
namespace detail
{
template<bool Base>
struct pointer_cast_impl
{
template<typename To, typename From>
static To apply(From* from)
{
return reinterpret_cast<To>(from);
}
};
template<>
struct pointer_cast_impl<true>
{
template<typename To, typename From>
static To apply(From* from)
{
return static_cast<To>(from);
}
};
template<typename To, typename From>
struct pointer_cast_check
{
typedef To to_type;
typedef From* from_type;
private:
// 'To' is pointer
BOOST_STATIC_CONSTANT(bool, to_is_pointer = boost::is_pointer<to_type>::value);
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// 'To' and 'From' has same pointer arity
BOOST_STATIC_CONSTANT(
bool,
is_same_pointer_arity =
(pointer_arity<to_type>::value == pointer_arity<from_type>::value));
#else
BOOST_STATIC_CONSTANT(bool, is_same_pointer_arity = true);
#endif // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
public:
BOOST_STATIC_CONSTANT(bool, value = (to_is_pointer && is_same_pointer_arity));
};
} // namespace detail
// pointer_cast
template<typename To, typename From>
#ifndef BOOST_NO_SFINAE
// Error if 'To' is not pointer
// Error if 'To' and 'From' has different pointer arity
// Error is 'From' is const and 'To' non-const
// Error is 'From' is volatile and 'To' non-volatile
BOOST_DEDUCED_TYPENAME boost::enable_if_c<
// pointer check
detail::pointer_cast_check<To, From>::value &&
// Error is 'From' is const and 'To' non-const
!(boost::is_const<From>::value &&
!boost::is_const<
BOOST_DEDUCED_TYPENAME boost::remove_pointer<To>::type>::value) &&
// Error is 'From' is volatile and 'To' non-volatile
!(boost::is_volatile<From>::value &&
!boost::is_volatile<
BOOST_DEDUCED_TYPENAME boost::remove_pointer<To>::type>::value),
To
>::type
#else // BOOST_NO_SFINAE
To
#endif // !BOOST_NO_SFINAE
pointer_cast(From* from)
{
// pointer check
BOOST_STATIC_ASSERT((detail::pointer_cast_check<To, From>::value == true));
// Error is 'From' is const and 'To' non-const
BOOST_STATIC_ASSERT(!(boost::is_const<From>::value &&
!boost::is_const<
BOOST_DEDUCED_TYPENAME boost::remove_pointer<To>::type>::value));
// Error is 'From' is volatile and 'To' non-volatile
BOOST_STATIC_ASSERT(!(boost::is_volatile<From>::value &&
!boost::is_volatile<
BOOST_DEDUCED_TYPENAME boost::remove_pointer<To>::type>::value));
// Check for base class
const bool is_base = boost::is_base_of<
BOOST_DEDUCED_TYPENAME boost::remove_pointer<To>::type,
From>::value;
// Cast
return detail::pointer_cast_impl<is_base>::apply<To>(from);
}
// safe_reinterpret_cast
namespace detail
{
template<typename To, typename From>
struct safe_reinterpret_cast_check
{
BOOST_STATIC_CONSTANT(bool, value = (sizeof(To) >= sizeof(From)));
};
} // namespace detail
// safe_reinterpret_cast
template<typename To, typename From>
#ifndef BOOST_NO_SFINAE
// Error if safe_reinterpret_cast_check failed.
// Error is 'From' is const and 'To' non-const
// Error is 'From' is volatile and 'To' non-volatile
BOOST_DEDUCED_TYPENAME boost::enable_if_c<
// safe_reinterpret_cast check
detail::safe_reinterpret_cast_check<To, From>::value,
To
>::type
#else // BOOST_NO_SFINAE
To
#endif // !BOOST_NO_SFINAE
safe_reinterpret_cast(const From& from)
{
// safe_reinterpret_cast check
BOOST_STATIC_ASSERT((detail::safe_reinterpret_cast_check<To, From>::value == true));
// Cast
return reinterpret_cast<To>(const_cast<From&>(from));
}