很久以前我已经创建了一个以下模板,这样每当我执行static_cast时我都会得到一个断言但类型不是我认为的类型:
/// perform a static_cast asserted by a dynamic_cast
template <class Type, class SourceType>
Type static_cast_checked(SourceType item)
{
Assert(!item || dynamic_cast<Type>(item));
return static_cast<Type>(item);
}
今天我想创建一个变体,它不仅可以用于指针,还可以用于引用:
/// overload for reference
template <class Type, class SourceType>
Type &static_cast_checked(SourceType &item)
{
Assert(dynamic_cast<Type *>(&item));
return static_cast<Type>(item);
}
但是,当我转换对另一个引用的引用时,编译器似乎没有使用此重载。我恐怕我不明白模板解析规则足以理解为什么,或者能够创建一个有效的变体。
注意:我无法捕获bad_cast exception
而不是检查dynamic_cast<Type *>
是否为NULL,因为此项目禁用了异常。
答案 0 :(得分:5)
从返回类型中删除*
和&
:
/// perform a static_cast asserted by a dynamic_cast
template <class Type, class SourceType>
Type static_cast_checked(SourceType *item)
{
Assert(!item || dynamic_cast<Type>(item));
return static_cast<Type>(item);
}
template <class Type> struct make_pointer
{
typedef Type *PointerType;
};
template <class Type> struct make_pointer<Type &>
{
typedef Type *PointerType;
};
/// overload for reference
template <class Type, class SourceType>
Type static_cast_checked(SourceType &item)
{
Assert(dynamic_cast<typename make_pointer<Type>::PointerType>(&item));
return static_cast<Type>(item);
}
然后您可以使用所需的语法:
Derived *d= static_cast_checked<Derived *>(b);
Derived &d= static_cast_checked<Derived &>(b);
编辑:添加了指针类型转换。
答案 1 :(得分:2)
这有效:
/// perform a static_cast asserted by a dynamic_cast
template <class Type, class SourceType>
Type* static_cast_checked(SourceType *item)
{
Assert(!item || dynamic_cast<Type*>(item));
return static_cast<Type*>(item);
}
/// overload for reference
template <class Type, class SourceType>
Type &static_cast_checked(SourceType &item)
{
Assert(dynamic_cast<Type *>(&item));
return static_cast<Type&>(item);
}
像这样使用:
Dervied d;
Base* pbase = static_cast_checked<Base>(&d);
Base& rbase = static_cast_checked<Base>(d);
此解决方案依赖于重载功能模板。您的解决方案无效,因为您的第一个模板过于笼统,它已包含您的第二个功能。请注意,功能模板没有专业化!您只能专门化类模板。
答案 2 :(得分:1)
#include <boost/type_traits/add_pointer.hpp>
template <class Type, class SourceType>
Type static_cast_checked(SourceType *item)
{
assert(!item || dynamic_cast<Type>(item));
return static_cast<Type>(item);
}
template <typename Type, class SourceType>
Type static_cast_checked(SourceType &item)
{
typedef typename boost::add_pointer<Type>::type TypePtr;
assert(dynamic_cast< TypePtr >(&item));
return static_cast<Type>(item);
}
此实现类似于std-lib中的static_cast
或dynamic_cast
:``
Base &b = static_cast_checked<Base&>( a);
Base* bPtr = static_cast_checked<Base*>(&a);
答案 3 :(得分:0)
尝试以下方法:
template<class Type, class SourceType>
Type* static_cast_checked(SourceType* item)
{
// ...
}
template<class Type, class SourceType>
Type& static_cast_checked(SourceType& item)
{
// ...
}
然后每个指针都将使用第一个变量,每个引用将使用部分特化规则(IIRC)中的第二个。