【问题标题】:Mapping vectors of arbitrary type任意类型的映射向量
【发布时间】:2012-05-03 15:06:25
【问题描述】:

我需要存储一个不同类型的列表向量,每个向量都由一个字符串标识符引用。目前,我使用std::mapstd::string 作为键,boost::any 作为它的值(示例实现posted here)。

我在尝试对所有存储的向量运行方法时遇到了问题,例如:

std::map<std::string, boost::any>::iterator it;
for (it = map_.begin(); it != map_.end(); ++it) {
  it->second.reserve(100);  // FAIL: refers to boost::any not std::vector
}

我的问题:

  • 是否可以将boost::any 转换为任意向量类型,以便我可以执行它的方法?
  • 有没有更好的方法来映射任意类型的向量,然后用正确的类型检索?

目前,我正在尝试另一种实现,它将boost::any 替换为this answer 中建议的指向容器基类的指针。这开辟了一个全新的蠕虫罐头,还有我需要解决的其他问题。如有必要,我很乐意走这条路,但我仍然想知道我是否可以使其与 boost::any 一起工作,是否有其他更好的解决方案。

附言我是一个 C++ n00b 新手(并且已经被 Python 的动态类型宠坏了太久了),所以我很可能会以错误的方式处理这个问题。非常欢迎严厉的批评(最好是提出建议)。


大局:

正如 cmets 中所指出的,这很可能是一个 XY 问题,所以这里是我想要实现的目标的概述。

我正在为管理任务执行的模拟框架编写任务调度程序;每个任务都是对一组数据向量的基本操作。例如,如果在模型中将task_A 定义为对"x"(double), "y"(double), "scale"(int) 的操作,那么我们实际上试图模拟的是对i 的所有值执行task_A(double x[i], double y[i], int scale[i])

每个任务(函数)都对不同的数据子集进行操作,因此这些函数共享一个共同的函数签名,并且只能通过特定的 API 访问数据,例如get_int("scale")set_double("x", 0.2)

在框架的前一个版本(用 C 语言编写)中,任务是静态调度的,框架会根据给定模型生成代码以运行模拟。任务的排序基于从模型定义中提取的依赖图。

我们现在正尝试为所有模型创建一个通用的运行时,该运行时调度程序会在满足它们的依赖关系时执行任务。从生成特定于模型的代码到生成通用代码的转变带来了各种各样的痛苦。本质上,我需要能够通用地处理异质向量并通过“名称”(可能还有type_info)访问它们,因此上述问题。

我愿意接受建议。任何建议。

【问题讨论】:

  • 这在我看来就像XY problem 的经典案例。您尝试做的只是与 C++ 非常不匹配。您可能需要退后一步,告诉我们您真正想要完成的工作。然而,现在看来(至少在我看来)您不是在编写 C++。您正在使用 C++ 语法编写 Python。
  • 我同意。你当然不能用boost::any 做你想做的事,除非你不小心跳过圈子来准确跟踪每个插槽中存储了什么样的向量,所以现在是时候退后一步来看看整个问题了再次因为您可能使用了错误的数据类型。实际上,每当any 开始看起来有可能时,通常就是这种情况。它有它的位置,但它不是一个大的。
  • @JerryCoffin 我也同意。确实感觉就像我每走一步都会遇到绊脚石一样违背语言的本质。我会看看我能做些什么来描述大局 - 我很担心把它变成一个“这是我的问题,为我设计一个解决方案”的问题,这很可能太复杂了可能与Stack Overflow 无关。
  • @JerryCoffin 我添加了一些我正在尝试尝试的概述。希望能帮助到你。 (p.s. 我很快就会下线,但会尽快解决所有反馈)
  • 看起来您不需要将所有向量保存在同一个地图中。为什么每种类型没有一张地图?

标签: c++ stdvector stdmap boost-any


【解决方案1】:

查看添加的细节,我的直接反应是将数据分成多个单独的地图,类型作为模板参数。例如,您可以将get_int("scale") 替换为get&lt;int&gt;("scale"),将set_double("x", 0.2) 替换为set&lt;double&gt;("x", 0.2);

或者,使用std::map,您可以很容易地将它(例如)更改为doubles["x"] = 0.2;int scale_factor = ints["scale"];(尽管您可能需要对后者保持警惕——如果您尝试检索一个不存在的值,它将使用默认初始化而不是发出错误信号来创建它。

无论哪种方式,您最终都会得到多个单独的集合,每个集合都是同质的,而不是尝试将多个不同类型的集合放在一个大集合中。

如果您确实需要将它们放在一个整体集合中,我会认真考虑仅使用结构,因此它会变成 vals.doubles["x"] = 0.2;int scale_factor = vals.ints["scale"];

至少临时来说,我认为这不会丢失任何东西,并且通过始终保留静态类型,它似乎更适合 C++ 的预期工作方式。

【讨论】:

  • 我可能应该补充一点:1)由于遗留原因,访问 API 也需要可用于 C 函数,因此避免使用模板参数,以及 2)类型不限于原语,并且可以是用户定义的数据类型,所以如果我保持它们同质,我仍然需要管理我的地图集合。不管怎样,我会在早上回到我的办公桌前仔细考虑你的建议并制定出来。非常感谢您的意见。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-06
  • 1970-01-01
  • 2022-01-13
  • 1970-01-01
  • 2017-08-08
  • 2017-01-18
相关资源
最近更新 更多