#include <type_traits>

template<typename T>
T* pointer_cast_impl(void* const p)
{
    return static_cast<T*>(p);
}

template<typename T>
T const* pointer_cast_impl(void const* const p)
{
    return static_cast<T const*>(p);
}

template<typename T>
T volatile* pointer_cast_impl(void volatile* const p)
{
    return static_cast<T volatile*>(p);
}

template<typename T>
T const volatile* pointer_cast_impl(void const volatile* const p)
{
    return static_cast<T const volatile*>(p);
}

template<typename T, typename U>
auto pointer_cast(U* const p) -> decltype((pointer_cast_impl<T>)(p))
{
    static_assert(std::is_standard_layout<T>()
    			  && std::is_standard_layout<U>(),
                  "T and U must both be standard layout types");
    static_assert(alignof(T) <= alignof(U),
    			  "T must not have stricter alignment than U");
    return (pointer_cast_impl<T>)(p);
}