Skip to content

Instantly share code, notes, and snippets.

@nekko1119
Last active December 22, 2015 07:09
Show Gist options
  • Save nekko1119/6436062 to your computer and use it in GitHub Desktop.
Save nekko1119/6436062 to your computer and use it in GitHub Desktop.
良い感じに分けるcastのSFINAE版
#include <iostream>
#include <type_traits>
#include <utility>
template <class To, class From>
struct needs_to_static_cast
: public std::integral_constant<bool,
std::is_convertible<typename std::remove_reference<From>::type, To>::value>
{};
template<class To, class From>
struct needs_to_const_cast
: public std::integral_constant<bool,
((!std::is_const<typename std::remove_reference<To>::type>::value
&& std::is_const<typename std::remove_reference<From>::type>::value)
|| (!std::is_volatile<typename std::remove_reference<To>::type>::value
&& std::is_volatile<typename std::remove_reference<From>::type>::value))
&& !needs_to_static_cast<To, From>::value>
{};
template <class To, class From>
struct needs_to_dynamic_cast
: public std::is_base_of<
typename std::remove_pointer<typename std::remove_reference<From>::type>::type,
typename std::remove_pointer<typename std::remove_reference<To>::type>::type>
{};
template <class To, class From>
struct needs_to_reinterpret_cast
: public std::integral_constant<bool,
(((std::is_pointer<typename std::remove_reference<To>::type>::value
&& std::is_pointer<typename std::remove_reference<From>::type>::value)
|| std::is_reference<To>::value)
&& !needs_to_dynamic_cast<To, From>::value
&& !needs_to_static_cast<To, From>::value
&& !needs_to_const_cast<To, From>::value)
|| (std::is_pointer<typename std::remove_reference<To>::type>::value
&& std::is_integral<typename std::remove_reference<From>::type>::value)
|| (std::is_integral<typename std::remove_reference<To>::type>::value
&& std::is_pointer<typename std::remove_reference<From>::type>::value)>
{};
template <class To, class From>
typename std::enable_if<needs_to_static_cast<To, From>::value, To>::type cast_(From&& val)
{
std::cout << "static_cast\n";
return static_cast<To>(val);
}
template <class To, class From>
typename std::enable_if<needs_to_const_cast<To, From>::value, To>::type cast_(From&& val)
{
std::cout << "const_cast\n";
return const_cast<To>(val);
}
template <class To, class From>
typename std::enable_if<needs_to_dynamic_cast<To, From>::value, To>::type cast_(From&& val)
{
std::cout << "dynamic_cast\n";
return dynamic_cast<To>(val);
}
template <class To, class From>
typename std::enable_if<needs_to_reinterpret_cast<To, From>::value, To>::type cast_(From&& val)
{
std::cout << "reinterpret_cast\n";
return reinterpret_cast<To>(val);
}
template <class To, class From>
To cast(From&& val)
{
return cast_<To>(std::forward<From>(val));
}
//test
template <class T>
inline T* addressof(T& value)
{
return cast<T*>(&cast<char&>(cast<const volatile char&>(value)));
}
struct hoge
{
void* operator&() const
{
return nullptr;
}
};
struct base{virtual ~base(){}};
struct derived : base {};
int main()
{
{
float f = 10.0f;
int i = cast<int>(f);//static_cast
}
{
const int& a = 10;
int& b = cast<int&>(a);//const_cast
}
{
derived d;
base* b = &d;
derived* d2 = cast<derived*>(b);//dynamic_cast
}
{
double d = 3.14;
int* i = cast<int*>(&d);//reinterpret_cast
}
hoge h;
std::cout << addressof(h);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment