[英]How to pass a templated function parameter with a subclass of the templated type in C++?
编译以下人为示例:
class Base
{};
class Derived : public Base
{};
template< typename T >
class A
{};
class B
{
public:
static void f( const A< Base >& ) {}
};
int main()
{
A< Base > tb;
A< Derived > td;
B::f( tb );
B::f( td );
return 0;
}
使用 g++-8 给我以下错误:
error: no matching function for call to 'B::f(A<Derived>&)'
B::f( td );
note: no known conversion for argument 1 from 'A<Derived>' to 'const A<Base>&'
为什么?
由于Derived
是Base
并且它不会覆盖Base
的任何内容,为什么我不能在模板化的 function 参数中用Derived
代替Base
?
Derived
确实是从Base
派生的,但这并不意味着A<Derived>
因此必须从A<Base>
派生。 C++ 模板不能以这种方式工作。
A<Derived>
是一个 class,由A
模板实例化。 你可以简单地声明:
class A_Derived {
// ...
};
使用相同的成员(如果有的话),几乎得到了相同的结果。 A<Base>
相同。 图片中没有其他内容,这两个班级绝对没有任何关系。 你可以在这里画一个心理图,好像你做了以下声明:
class A_Derived {
};
和
class A_Base {
};
这几乎就是历史。 您是否看到A_Derived
在这里显式地从A_Base
派生? 明显不是。 如果某些东西需要引用或指向A_Base
的指针,则不能给它A_Derived
,因为这两个类彼此完全没有关系。 它们是独立的类。
PS如果您愿意,您可以将A<Derived>
的显式特化声明为派生自A<Base>
,但特化是一个完全不同的主题......
模板实例,如A<Base>
和A<Derived>
,是不同的类型。 特别是它们没有任何 inheritance 关系,即使Base
和Derived
有关系。
有很多方法可以使您想要的工作。
首先,您可以使A<Derived>
显式派生自A<Base>
,但这意味着添加整个 class 定义。
template<>
class A<Derived> : public A<Base>
{};
其次,您可以以构造函数模板的形式提供从A<Derived>
到A<Base>
的隐式转换。 您可以使用std::enable_if
和std::is_base_of
只允许A<T>
其中T
派生自Base
,或者如果您只想考虑这个特定的Derived
类型,则可以直接使用std::is_same
。
template<typename T>
class A
{
template<typename U, typename = std::enable_if_t<std::is_base_of_v<T, U>>>
A(A<U> const& other);
};
第三,您可以以运算符模板的形式提供隐式转换,方式大致相同。
template<typename T>
class A
{
template<typename U, typename = std::enable_if_t<std::is_base_of_v<U, T>>>
operator U();
};
第四,你可以制作一个f
模板并限制它需要什么类型。
template<typename T, typename = std::enable_if_t<std::is_base_of_v<Base, T>>>
static void f(A<T> const& a);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.