[C++] pointer_cast, safe_reinterpret_cast
От: _nn_ www.nemerleweb.com
Дата: 28.04.06 08:26
Оценка: 20 (3) +1
Уточнающие приведения.
Призванны заменить 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));
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.