我不确定这是否可以实现。假设我有两个类模板Foo<T>
和FooOwner<T>
,而FooOwner<T>
有一个指向Foo<U>
的指针成员,其中U
是{{1}的子类}}
我想让T
成为FooOwner<T>
的朋友,但前提是Foo<U>
是U
的子类。那可能吗?如果没有,是否有足够接近的解决方法?
T
答案 0 :(得分:1)
我不确定你想要达到什么目的,但类型特质is_base_of也许可以帮助你:
#include <type_traits>
class A {};
class B : A {};
class C {};
int main()
{
std::is_base_of<A, B>::value; // true
std::is_base_of<C, B>::value; // false
}
您可以将其与conditional:
一起使用std::conditional<std::is_base_of<A, B>::value, A, SomethingElse>::type
// will be A if B is derived from A, or SomethingElse otherwise
std::enable_if<std::is_base_of<A, B>::value, A>::type
// will be defined only if B is derived from A
答案 1 :(得分:1)
看起来FooOwner
不是Foo外部接口的一部分,你可以在Foo
声明它:
template<typename T>
class Foo {
private:
template<typename U> // Constrain U to be a superclass of T?
friend class FooOwner;
template< typename U>
class FooOwner {
public:
FooOwner(std::enable_if<std::is_base_of<T, U>::value, U*> uptr) : p(uptr){} // (rough idea)
private:
Foo<U>* p; // This can point to a object of type Foo<U>
// where U is a subclass of T
};
};
然后,您可以对FooOwner或FooOwners方法的构造函数使用is base of测试或类似方法(如上所述)。
更重要的是,你可以这样做:
template<typename T>
class Foo {
private:
template<typename U, typename = std::enable_if<std::is_base_of<T, U>::value>>
friend class FooOwner;
template<typename U, typename = std::enable_if<std::is_base_of<T, U>::value>>
class FooOwner {
private:
Foo<U>* p; // This can point to a object of type Foo<U>
// where U is a subclass of T
};
};
第一个和第二个enable_if
都不是严格要求的。您可以完全删除友谊(以及第一次启用if),只有当基础派生关系是正确的时,才允许FooOwner
存在。如果您希望允许该类存在,并且仅允许该友谊,则可以删除第二个启用if。在这种情况下保留虚拟模板类型名称:
template<typename U, typename = T>
class FooOwner {
. . .
};
如果您希望将FooOwner保留在Foo的外部,您可以以类似的方式将其设为U
和T
的模板。