c++ - 如何确保 C++ 中的运行时类型协方差?
问题描述
假设我有一个接口类和模板子类
struct IPort {
virtual bool can_connect_to(std::shared_ptr<IPort> p) = 0;
std::shared_ptr<IPort> receiver;
};
template <class T>
struct Port : IPort {
bool can_connect_to(std::shared_ptr<IPort> p) override {
// what goes here?
}
void send(T* t) {
auto p = std::static_pointer_cast<Port>(receiver);
p->on_recv(t);
}
std::function<void(T*)> on_recv;
};
模板参数可以是任何类型。我有一些基本类型(Base
及Other
以下)以及派生类型(Derived
)。
struct Base {
virtual const char* get_data() = 0;
virtual size_t get_size() = 0;
};
struct Derived : public Base {
std::string str;
const char* get_data() override { return str.c_str(); }
size_t get_size() override { return str.size(); }
};
struct Other {
double x, y, z;
};
理想情况下,我应该能够将派生类型从一个端口发送到另一个接受基本类型的端口(例如Port<Derived>
应该能够连接到Port<Base>
)。另一方面,我不应该能够发送不兼容的类型(Port<Other>
不应该能够连接到Port<Base>
)。
auto sender1 = std::make_shared<Port<Derived>>();
auto sender2 = std::make_shared<Port<Other>>();
auto receiver = std::make_shared<Port<Base>>([](Base* t) {
// do something with t
});
sender1->can_connect_to(receiver); // should return true
sender2->can_connect_to(receiver); // should return false
我可以输入什么can_connect_to
来验证传入的端口是否具有模板化类型,它是发送端口模板的超类?
另外,为什么static_pointer_cast
insend
工作?它似乎做了正确的事情,但我不明白它是如何有效的 c++,因为Port
.
解决方案
在运行时测试对象是否“是 A”某个类的基本方法是dynamic_cast
. 所以我认为你需要:
template <class T>
bool Port<T>::can_connect_to(std::shared_ptr<IPort> p) {
return dynamic_cast<T*>(p.get());
}
如果p
是空指针,这也将返回 false,这可能是您想要的。
另外,为什么
static_pointer_cast
insend
工作?它似乎做了正确的事情,但我不明白它是如何有效的 c++,因为Port
.
在类模板的定义中,或其任何成员(或其嵌套类成员的成员等)的定义中,模板的名称可以用作使用该定义的模板参数的类类型的别名. 也就是说,由于使用Port
出现在定义template <class T> struct Port {
中 ... };
,没有模板参数列表的名称Port
与Port<T>
. 这称为“注入的类名”。
推荐阅读
- c# - 无法从控制台应用程序在 Dot Net Core API 中发送令牌
- mysql - 不同条件的连接表
- javascript - iOS 13+ 设备的网络音频音量衰减
- php - Eloquent 中的 Where 子句似乎无法正常工作
- node.js - Socket IO 支持 React Application 和 Node 服务器
- python - 在带有列表的自定义计时器类上尝试 / 除外
- arrays - 如何使用指针按字母顺序对双指针数组中的字符串进行排序
- javascript - 折叠卡片时如何删除空格
- arrays - 在多个脚本中共享包含空格的文件列表
- c - netCDF Fortran 编译的问题:C 编译器不起作用