Skip to content

Instantly share code, notes, and snippets.

@gununu
Created March 8, 2011 11:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gununu/860154 to your computer and use it in GitHub Desktop.
Save gununu/860154 to your computer and use it in GitHub Desktop.
safe sign-type cast
#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;
}
#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