c++ - 关于模板、容器和继承的 C++ 设计问题
问题描述
关于我编写的接口算法类和第三方 API,我的设计存在问题。我将编写一些伪代码来帮助解释我的问题。如果可能的话,我宁愿不参与boost
。
问题
我有一个我将调用的算法类Alg
(它可以被认为是一个搜索/优化算法)和一个我将调用的“超级”算法类SuperAlg
,它Alg
在std::vector<Alg>
. 评估SuperAlg
函数依赖于第三方算法,因此需要将任意数量的这些Alg
类对象的结果转换为第三方类型。每个都Alg
可能与不同的第三方类型相关联,这在Alg
类对象的构建时是已知的。评估SuperAlg
函数看起来像:
double SuperAlg::evaluate(const std::vector<AlgResultType>& input) {
ThirdPartyValues values;
for (const auto& i : input) {
values.insert(convert(i));
}
ThirdPartyAlg alg;
return alg.error(values);
}
这里:
- 是
ThirdPartyValues::insert
第三方 API 中的一个模板函数,它知道如何采用许多不同的第三方类型 ThirdPartyAlg::error
接受 aThirdPartyValues
并返回 adouble
。input
是所有搜索结果的向量,与类所拥有Alg
的 1 对 1 对应。std::vector<Alg>
SuperAlg
有很多这些第三方类型,假设我知道类型并且有Alg
搜索结果 ( AlgResultType
),我就知道如何执行转换。即convert
函数已知:
ThirdPartyType convert<ThirdPartyType>(const AlgResultType& result);
根本问题是:如何指定i
需要转换为 in的类型SuperAlg::evaluate
?回想一下,这种类型在每个构建时都是已知的,Alg
并且需要以某种方式保留。
一些解决方案的想法
- 如果
Alg
/AlgResultType
被模板化ThirdPartyType
并且convert<ThirdPartyType>
函数通过它们的接口公开,那么它们不能被保存在动态大小的同质容器中,并且 c++ 没有动态大小的异构容器类型。 - 通常保存许多不同类型的方法(例如,由于它们的模板),
Alg<ThirdPartyType>
/AlgResultType<ThirdPartyType>
在这种情况下,是拥有一个公共基类并拥有std::vector
这个基类,但是这个基类需要具有convert<ThirdPartyType>
函数才能有用inSuperAlg::evaluate
,它依赖于模板参数。 - 某种类型的容器,其中每个
Alg
orAlgResultType
可以与 a 相关联ThirdPartyType
,但我不知道这样的容器。
编辑
感谢@Evg 将我指向std::variant
and std::visit
。我现在有一个可行的,虽然不是很优雅的解决方案,但在课堂上保持std::vector<std::variant<Alg<ThirdPartyType1>, Alg<ThirdPartyType2>, ...>>
并SuperAlg
公开该ThirdPartyType convert(const AlgResultType& result)
功能Alg
。
这个解决方案的丑陋之处在于,Alg
要从内部调用任何成员函数SuperAlg
,我需要为该成员函数创建一个 lambda 函数,Alg
然后使用std::visit(lambda, alg_variant)
解决方案
推荐阅读
- rust - 自己为结构派生属性和实现特征有什么区别?
- rust - 如何将 RangeInclusive 转换为 Range?
- java - 扫描文本文件时如何跳过前导字符串?
- scala.js - 如何让 Scala .js 1.3.0 教程运行 - 第 2 部分?
- django - 在没有 for 的情况下运行 QuerySet Django
- vagrant - vagrant up 间歇性错误“SSH 以非零退出状态响应”或引导超时错误
- sql - T-SQL - 根据 ID 标记一列中的公共值并更新数据库
- java - 区分 dev 和 prod 的代码
- reactjs - 如何在 Ionic React 中动态更改图像?
- python - 在仅处理第一个文件的循环中运行可执行文件