mardi 31 mars 2015

Failing in trying to code smart cast template function

I am currently trying to code a function to perform static_cast or dynamic_cast based on its input and output types in following of DRY principle. The function which i am trying to accomplish is as below:



#define where typename = typename
#define can_cast(FROM, TO) std::is_convertible<FROM, TO>::value
#define can_dynamic_cast(FROM, TO) \
can_cast(FROM, TO) && \
!std::is_same<FROM, TO>::value && \
std::is_class<TO>::value && \
!std::is_const<FROM>::value && \
std::is_base_of<TO, FROM>::value
#define can_static_cast(FROM, TO) can_cast(FROM, TO)

template<typename _Tout, typename _Tin, where
std::enable_if<
!std::is_pointer<_Tout>::value &&
!std::is_pointer<_Tin>::value &&
can_cast_ptr(_Tin, _Tout)>::type>
inline _Tout* gc_ptr_cast(_Tin* const p) {
if(can_dynamic_cast(_Tin*, _Tout*))
return dynamic_cast<_Tout*>(p);
if(can_dynamic_cast(_Tin*, _Tout*))
return static_cast<_Tout*>(p);
throw bad_cast();
}


But it won't work for for example gc_ptr_cast<int>(new int(1)) due to the complaining of compiler such that:



[..] error: cannot dynamic_cast 'p' (of type 'int* const') to type 'int*' (target is not pointer or reference to class) return dynamic_cast<_Tout*>(p)«;



The compiler should process static_cast instead of dynamic_cast!

Now i am not even sure if i am in correct path using <type_traits> for such purpose.


I have a half a thousand of template functions with in some of them i need to perform static_cast and in some of them i need to dynamic_cast and in half of the remaining i need to check both. The dynamic_cast are important in my case since it is successful in below example which is a crucial part to make things right!



struct base1 {};
struct base2 {};
struct derived : public base1, public base2 {};
.
.
.
derived obj;
base1* p1 = &obj;
base2* p2 = &obj;
assert(dynamic_cast<void*>(p1) == dynamic_cast<void*>(p2)); // will succeed
assert(static_cast<void*>(p1) == static_cast<void*>(p2)); // will fail [ THIS IS WHY I CANNOT USE `static_cast` IN SOME CASES ]


I know there is a smart cast of boost library, but i want my code just depend on C++11 std. library.


Questions


1) What am i doing wrong?

2) How do i accomplish gc_ptr_cast<>()?




P.S: Maybe i over did the some conditions, I have put in can_dynamic_cast but it's OK for now.


Aucun commentaire:

Enregistrer un commentaire