Last active
December 22, 2015 07:09
-
-
Save nekko1119/6436062 to your computer and use it in GitHub Desktop.
良い感じに分けるcastのSFINAE版
This file contains 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 <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