未能尝试编写智能投射模板功能

时间:2015-03-31 10:17:48

标签: c++ c++11 boost casting

我目前正在尝试编写一个函数来根据DRY原则中的输入和输出类型执行static_castdynamic_cast。我想要完成的功能如下:

#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();
}

但由于抱怨编译器,它不适用于例如gc_ptr_cast<int>(new int(1))

  

[..] 错误:不能使用dynamic_cast'p'(类型'int * const')来键入'int *'(目标不是指针或对类的引用)                return dynamic_cast<_Tout*>(p)«;

编译器应该处理static_cast而不是dynamic_cast! 现在我甚至不确定我是否正确地使用<type_traits>来达到这个目的。

我有半个模板函数,其中一些我需要执行static_cast,其中一些我需要dynamic_cast,剩下的一半我需要检查两个。 dynamic_cast在我的案例中很重要,因为它在下面的例子中是成功的,这是使事情正确的关键部分!

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 ]

我知道有一个smart cast的boost库,但我希望我的代码只依赖于C ++ 11 std。库。

问题

1)我做错了什么? 2)我如何完成gc_ptr_cast<>()


P.S:也许我已经完成了一些条件,我已经放入了can_dynamic_cast,但现在可以了。

1 个答案:

答案 0 :(得分:1)

您正在尝试在运行时条件中使用编译时条件。这基本上是个坏主意。

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();
}

这应该在编译时检查方面重写,因为在你的情况下can_dynamic_cast是编译时检查。

我认为这样的事情可以帮到你:

template<typename _Tout, typename _Tin>
inline _Tout* ptr_cast(_Tin* const p,
typename std::enable_if<can_dynamic_cast(_Tin*, _Tout*)>::type* = 0)
{
   return dynamic_cast<_Tout*>(p);
}

template<typename _Tout, typename _Tin>
inline _Tout* ptr_cast(_Tin* const p,
typename std::enable_if<can_static_cast(_Tin*, _Tout*)>::type* = 0)
{
   return static_cast<_Tout*>(p);
}

template<typename _Tout, typename _Tin>
inline _Tout* ptr_cast(_Tin* const p,
typename std::enable_if<!can_static_cast(_Tin*, _Tout*) &&
!can_dynamic_cast(_Tin*, _Tout*)>::type* = 0)
{
   throw std::bad_cast();
}

template<typename _Tout, typename _Tin, where
    std::enable_if<
        !std::is_pointer<_Tout>::value &&
        !std::is_pointer<_Tin>::value &&
        can_cast(_Tin, _Tout)>::type>
inline _Tout* gc_ptr_cast(_Tin* const p) {
    return ptr_cast<_Tout>(p);
}