【发布时间】:2019-12-02 10:12:42
【问题描述】:
背景
我正在编写一个使用 USB 设备的应用程序。这包括我的应用程序可以使用的 USB 设备的设备发现,基于 USB 供应商 ID 和产品 ID。然而,这些设备有时有多个可能工作的驱动程序,即应用程序实现,具体取决于平台和月相(客户遗留的东西)。所以我想通过std::shared_ptr 使用运行时多态性和一系列不错的接口和东西。
问题
我不知道如何根据运行时给定的键来make_shared 某种类型的对象。至少在不丑陋的意义上不是。
目前的解决方案
我正在考虑以某种方式将类型值存储到映射 known_drivers 中(在此示例中是多映射,但差别不大),以便最终根据数值我可以构造不同的类类型和东西将其转换为shared_ptr。
示例代码
#include <iostream>
#include <algorithm>
#include <iterator>
#include <map>
#include <memory>
#include <stdexcept>
using vendor_product_usb_id_t = std::pair<uint16_t, uint16_t>;
struct usb_device {
static std::shared_ptr<usb_device> open(vendor_product_usb_id_t);
virtual void do_stuff() = 0;
};
struct usb_device_using_driver_a : usb_device {
usb_device_using_driver_a() {throw std::runtime_error("Not supported on this platform");}
protected:
void do_stuff() override {}
};
struct usb_device_using_driver_b : usb_device {
protected:
void do_stuff() override {std::cout << "Stuff B\n";}
};
const std::multimap<vendor_product_usb_id_t, ??> known_drivers = {{{0x42,0x1337}, driver_a}, {{0x42,0x1337}, driver_b}};
std::shared_ptr<usb_device> usb_device::open(vendor_product_usb_id_t id) {
std::shared_ptr<usb_device> value;
for (auto [begin,end] = known_drivers.equal_range(id); begin != end; ++begin) {
try {
value = std::make_shared<*begin>();
} catch (std::exception& e) {
continue;
}
}
return value;
}
int main() {
auto device = usb_device::open(std::make_pair(0x42,0x1337));
if (device) {
device->do_stuff();
}
}
【问题讨论】:
-
我想你要搜索的词是factory pattern?!除此之外,我没有看到任何问题......
-
问题是,我不想在地图中存储已经构建的对象,如果这些元组匹配,应该只是稍后尝试构建一个的建议。如果在运行时添加更多值(即可能的驱动程序),那么大的 switch case 将无法工作
-
我仍然无法阅读问题。我的理解是:在给定的键上创建一些派生类型。这就是典型的工厂模式。内部实现可以基于手工制作的 switch case,但在模板类型列表上更聪明。有数以百万计的现成可用的实现。但再说一遍:你的问题是什么。
-
类似
const std::multimap<vendor_product_usb_id_t, std::function<std::shared_ptr<usb_device>()>> known_drivers
标签: c++ c++17 run-time-polymorphism