【发布时间】:2023-03-29 18:44:01
【问题描述】:
假设我有一个像这样的Foo 类,我需要它的许多实例。
class Foo {
public:
Pool* bars; // a global list of bars, each may have a different type
template<typename T>
T& AddBar(int x) {
return bars->emplace<T>(x);
}
template<typename T>
T& GetBar() {
return bars->get<T>(); // a very slow function
}
}
Foo 的所有实例共享同一个柱线池,其中包含许多可能不同类型的柱线。例如,bars 可能是条形列表{A bar1, B bar2, A bar3, C bar4},其中ABC 是一些类类型,但每个Foo foo 实例只能有一个特定类型的条形,例如,foo 实例不能有两个A 类型的条形图。
给定一个实例Foo foo,我可以使用foo.GetBar<A>()、foo.GetBar<B>() 等获取特定类型的柱,但调用bars->get<T>() 函数既慢又昂贵。因此,我正在考虑缓存GetBar() 的结果,以便后续调用可以立即返回,而无需再次查询池。
现在这是我想出来的:我在成员函数内部创建了一个静态变量来存储 bar 的值,它只被初始化和赋值一次。
template<typename T>
T& GetBar() {
static T bar {};
if (bar == T {}) {
bar = bars->get<T>(); // a very slow function
}
return bar;
}
问题是,使用static 关键字,这个变量现在在Foo 的所有实例之间共享。如果我尝试从不同的实例中获取A 类型的条形,它们将返回相同的结果。
Foo foo1;
Foo foo2;
foo1.AddBar<A>(1);
foo2.AddBar<A>(2);
foo1.GetBar<A>(); // returns a bar (type = A, value = 1)
foo2.GetBar<A>(); // returns the same bar with value 1, not 2
如何在类中缓存T 类型的每个条形图并防止它被其他实例共享?我不知道如何将泛型类型存储为成员变量,此外,存储 bar 的每个类型 T 可能会很混乱。
编辑:我知道在调用方的类之外缓存结果会容易得多。我只是好奇类内部是否有一种优雅的缓存方式。
Edit2: bars 是指向注册表池的指针,其类型是复杂的数据结构,而不是原始列表或数组。澄清一下,我正在使用EnTT 库将实体组件系统集成到我的应用程序中,但不确定该池是如何在内部详细维护的。
Edit3:如果您想知道ABCs 是什么,从概念上讲,这些类型在编译时是未知的。但需要在运行时确定。事实上,它们只是我实现的许多其他类类型,所以我也可以将它们硬编码到 Foo 类中,在这种情况下,我可能应该使用工厂模式和脚本语言来自动生成代码,但这会比首先使用泛型的目的。
【问题讨论】:
-
Pool* bars; // a global list of bars, each may have a different type这不会解析。bars是一个指针。成为“列表”意味着什么?它是否指向Pool类型的对象数组?在这种情况下,它们都是同一类型。 -
@n.1.8e9-where's-my-sharem。感谢您的评论,我已经编辑了帖子。
-
您需要创建一个能够存储不同类型实例的缓存对象。就像你有
bar = bars->get<T>()一样,你需要能够说bar = cache->get<T>()和cache->put<T>(bar)和if (cache->has<T>())。这些在 C++ 中都不是免费的,您需要对其进行实际编程。一种可能的实现在内部使用std::map<std::type_info, std::any>。 -
@n.1.8e9-where's-my-sharem。谢谢你的主意!我想
std::map<Foo*, T>可能是一个选择,我会试试看。 -
Foo想要缓存的类型集合是在编译时定义的吗?例如。在你的例子中只有A、B和C?
标签: c++ templates entity-component-system