我一直在为opencascade C++到C#进行包装。
由于最近几年我主要从事C#工作,所以我的C++有点生疏。
现在,我遇到以下问题,还无法找出解决方法:
#include <type_traits>
//! Trait yielding true if class T1 is base of T2 but not the same
template <class T1, class T2, class Dummy = void>
struct is_base_but_not_same : std::is_base_of <T1, T2> {};
//! Explicit specialization of is_base_of trait to workaround the
//! requirement of type to be complete when T1 and T2 are the same.
template <class T1, class T2>
struct is_base_but_not_same <T1, T2, typename std::enable_if <std::is_same <T1, T2>::value>::type> : std::false_type {};
template <class T>
class handle
{
public:
//! Down casting operator from handle to base type
template <class T2>
static typename std::enable_if<is_base_but_not_same<T2, T>::value, handle>::type
DownCast(const handle<T2>& theObject)
{
return handle(dynamic_cast<T*>(const_cast<T2*>(theObject.get())));
}
//! Down casting operator from pointer to base type
template <class T2>
static typename std::enable_if<is_base_but_not_same<T2, T>::value, handle>::type
DownCast(const T2* thePtr)
{
return handle(dynamic_cast<T*>(const_cast<T2*>(thePtr)));
}
};
class Foo
{
};
typedef handle<Foo> Handle_Foo;
Handle_Foo DownCastFoo(Handle_Foo const &T) {
return Handle_Foo::DownCast(T);
}
编译器错误如下:
Error C2672 'handle<Foo>::DownCast': no matching overloaded function found
Severity Code Description Project File Line Suppression State
Error C2784 'std::enable_if<is_base_but_not_same<T2,T,void>::value,handle<T>>::type handle<T>::DownCast(const T2 *)': could not deduce template argument for 'const T2 *' from 'const Handle_Foo'
Severity Code Description Project File Line Suppression State
Error C2893 Failed to specialize function template 'std::enable_if<is_base_but_not_same<T2,T,void>::value,handle<T>>::type handle<T>::DownCast(const handle<T2> &)'
谁能指出我正确的方向?
最佳答案
提供的示例中存在多个错误。
首先,该示例隐含了T*
类的get()
构造函数和handle
方法。将它们添加到handle
类:
explicit handle(T*);
const T* get() const;
其次,您试图将
handle<Foo>
转换为handle<Foo>
,这是毫无意义的操作。 Foo
甚至不是多态的。您的强制转换方法似乎专门设计为不提供此重载,因此不会出现错误。将Foo
定义为多态的,并添加派生类Bar
。struct Foo { virtual ~Foo() = default; };
struct Bar : public Foo {};
最后,更改
DownCastFoo
尝试向下转换为Bar
而不是Foo
,错误得到解决。typedef handle<Foo> Handle_Foo;
typedef handle<Bar> Handle_Bar;
Handle_Bar DownCastFoo(Handle_Foo const &T) {
return Handle_Bar::DownCast(T);
}
最后一点,那些
const_cast
看起来非常可疑。不幸的是,您的示例中没有足够的信息来提供更好的建议。完整正确的例子
#include <type_traits>
//! Trait yielding true if class T1 is base of T2 but not the same
template <class T1, class T2, class Dummy = void>
struct is_base_but_not_same : std::is_base_of <T1, T2> {};
//! Explicit specialization of is_base_of trait to workaround the
//! requirement of type to be complete when T1 and T2 are the same.
template <class T1, class T2>
struct is_base_but_not_same <T1, T2, typename std::enable_if <std::is_same <T1, T2>::value>::type> : std::false_type {};
template <class T>
class handle
{
public:
explicit handle(T*);
const T* get() const;
public:
//! Down casting operator from handle to base type
template <class T2>
static typename std::enable_if<is_base_but_not_same<T2, T>::value, handle>::type
DownCast(const handle<T2>& theObject)
{
return handle(dynamic_cast<T*>(const_cast<T2*>(theObject.get())));
}
//! Down casting operator from pointer to base type
template <class T2>
static typename std::enable_if<is_base_but_not_same<T2, T>::value, handle>::type
DownCast(const T2* thePtr)
{
return handle(dynamic_cast<T*>(const_cast<T2*>(thePtr)));
}
};
struct Foo { virtual ~Foo() = default; };
struct Bar : public Foo {};
typedef handle<Foo> Handle_Foo;
typedef handle<Bar> Handle_Bar;
Handle_Bar DownCastFoo(Handle_Foo const &T) {
return Handle_Bar::DownCast(T);
}
编辑:看来
enable_if
仅用于避免非法重载。如果使用static_assert
,则会得到更好的编译器错误。使用
static_assert
的示例:template <class T>
class handle
{
public:
explicit handle(T*);
const T* get() const;
public:
//! Down casting operator from handle to base type
template <class T2>
static handle DownCast(const handle<T2>& theObject)
{
static_assert(std::is_same<T, T2>::value == false,
"Can't downcast from between identical types");
static_assert(std::is_base_of<T2, T>::value,
"Can only down cast from a derived type to a base type");
return handle(dynamic_cast<T*>(const_cast<T2*>(theObject.get())));
}
//! Down casting operator from pointer to base type
template <class T2>
static handle DownCast(const T2* thePtr)
{
static_assert(std::is_same<T, T2>::value == false,
"Can't downcast from between identical types");
static_assert(std::is_base_of<T2, T>::value,
"Can only down cast from a derived type to a base type");
return handle(dynamic_cast<T*>(const_cast<T2*>(thePtr)));
}
};
现在,您的原始用例将产生错误消息
"Can't downcast from between identical types"
。struct Foo { virtual ~Foo() = default; };
struct Bar : public Foo {};
typedef handle<Foo> Handle_Foo;
Handle_Foo DownCastFoo(Handle_Foo const &T) {
return Handle_Foo::DownCast(T);
}