Created
March 8, 2011 11:11
-
-
Save gununu/860154 to your computer and use it in GitHub Desktop.
safe sign-type cast
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "sign_cast.hpp" | |
int main() { | |
char* a = 0; | |
unsigned char* x = sign_cast<unsigned char*>(a); //ok | |
sign_cast<char*>(a); //ok | |
sign_cast<signed char*>(a); //ok | |
//sign_cast<wchar_t*>(a); //error | |
sign_cast<const char*>(a); //ok | |
sign_cast<char*const>(a); //ok | |
char b=0; | |
sign_cast<unsigned char&>(b);//ok | |
sign_cast<signed char**>(&a);//ok | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef GUNUNU_SAFE_SIGN_CAST_HPP | |
#define GUNUNU_SAFE_SIGN_CAST_HPP | |
/* | |
safe sign cast library | |
copyright 2011 (c) gununu | |
Use, modification, and distribution is subject to 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) | |
Usage: | |
unsigned char* a = 0; | |
char* x = sign_cast<char*>(a); //ok | |
wchar_t* y = sign_cast<wchar_t*>(a); //error | |
*/ | |
#include <boost/utility/enable_if.hpp> | |
#include <boost/mpl/assert.hpp> | |
#include <boost/type_traits.hpp> | |
#include <boost/static_assert.hpp> | |
namespace gununu { | |
struct signcast_ { | |
template<typename To, typename From> | |
static void nest_check(boost::mpl::false_) { | |
type_check<To,From>(); | |
} | |
template<typename To, typename From> | |
static void nest_check(boost::mpl::true_) { | |
using namespace boost; | |
typedef typename remove_cv<To>::type NakedTo; | |
typedef typename remove_cv<From>::type NakedFrom; | |
BOOST_MPL_ASSERT((is_same<typename make_unsigned<NakedTo>::type, typename make_unsigned<NakedFrom>::type>)); | |
} | |
template<typename To, typename From> | |
static void type_check() { | |
using namespace boost; | |
BOOST_STATIC_ASSERT((is_pointer<To>::value == is_pointer<From>::value)); | |
typedef typename remove_pointer<To>::type RemPtrTo; | |
typedef typename remove_pointer<From>::type RemPtrFrom; | |
BOOST_STATIC_ASSERT((is_volatile<RemPtrTo>::value || !is_volatile<RemPtrFrom>::value)); | |
BOOST_STATIC_ASSERT((is_const<RemPtrTo>::value || !is_const<RemPtrFrom>::value)); | |
nest_check<RemPtrTo,RemPtrFrom>(is_integral<To>()); | |
} | |
}; | |
} | |
template<typename To, typename From> | |
To sign_cast(From v, typename boost::disable_if<boost::is_reference<To> >::type* = 0) { | |
gununu::signcast_::type_check<To,From>(); | |
return reinterpret_cast<To>(v); | |
} | |
template<typename To,typename From> | |
To sign_cast(From& v, typename boost::enable_if<boost::is_reference<To> >::type* = 0) { | |
gununu::signcast_::type_check<typename boost::remove_reference<To>::type,From>(); | |
return reinterpret_cast<To>(v); | |
} | |
#endif //GUNUNU_SAFE_SIGN_CAST_HPP |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment