我正在尝试这样做
{
"_id" : 12345,
"value" : {
"cars" : true,
"boats" : false
}
}
其中B公开来自A.然而,这给出了错误
static_cast<IntrusivePtr<B>>(IntrusivePtr<A>)
有谁可以向我解释这里的问题?我可以通过做
来解决它invalid conversion from A* to B*
理论上究竟是上述错误消息所说的内容是不允许的。这是GCC 4.4.7
答案 0 :(得分:6)
您正在寻找的概念称为类型协方差 - 您希望IntrusivePtr<T>
在T
上具有协变性,这意味着IntrusivePtr<D>
是一个子类型如果IntrusivePtr<B>
是D
的子类型,则为B
。有类型系统支持的语言,C ++不是其中之一。
在C ++中,IntrusivePtr<A>
和IntrusivePtr<B>
是完全不相关的类型,无论A
和B
是什么(除非它们是相同的类型)。如果您想支持该转换,则必须明确支持:
template <class T>
struct IntrusivePtr {
template <class U, class = std::enable_if_t<std::is_convertible<U*, T*>::value>>
IntrusivePtr(IntrusivePtr<U> const& rhs) { ... }
};
或执行您正在执行的操作并侧重IntrusivePtr
类模板。
回想起重新阅读问题时,IntrusivePtr
似乎更有可能支持上述转换,但是在两种类型之间进行隐式转换 - 这对于派生到基础有效但对基础有效无效衍生。但是你总是可以从base-to-derived明确地转换。那就是:
struct B { };
struct D : B { };
B b;
D* d1 = &b; // error
D* d2 = static_cast<D*>(&b); // ok
答案 1 :(得分:1)
IntrusivePtr<A>
和IntrusivePtr<B>
是完全不相关的类型。因此,您无法静态转换它们(除非IntrusivePtr
包含显式转换代码或A
和B
相同)。
请注意,您无法从基础静态转换为派生类。
答案 2 :(得分:1)
这是IntrusivePtr可以改变的一种方式。
rowRenderer
检查:
template <typename T>
struct IntrusivePtr {
IntrusivePtr(const IntrusivePtr& other) {
... // do the refcounting
ptr = other.ptr; // straight assignment, pointers are of the same type
}
template <typename Q,
typename = std::enable_if_t<std::is_convertible<Q*, T*>::value>>
IntrusivePtr(const IntrusivePtr<Q>& other) {
... // do the refcounting
ptr = other.ptr; // straight assignment, pointers are compatible
}
// this can only be used in explicit conversions
template <typename Q,
typename = std::enable_if_t<std::is_convertible<T*, Q*>::value>>
// must add bogus default parameter, or the compiler will complain
explicit IntrusivePtr(const IntrusivePtr<Q>& other, int=0) {
... // do the refcounting
ptr = static_cast<T*>(other.ptr); // explicit downcast, trust the programmer
}
... // other methods
T* ptr;
};
然而,如果IntrusivePtr离boost :: intrusive_ptr不太远,它应该有一个类似于struct A {};
struct B : A {};
IntrusivePtr<A> a;
IntrusivePtr<B> b;
a = a; // ok, straight copy
a = b; // ok, implicit upcast
b = static_cast<IntrusivePtr<B>>(a); // ok, explicit downcast
b = a; // error, implicit conversion is not allowed
的函数。可能应该使用它,尤其是对于不支持C ++ 11的编译器。