假设我有一个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
类型的每个条形图在类内部并防止它被其他实例共享?我不知道如何将泛型类型存储为成员变量,此外,存储每个类型 T
酒吧可能会变得一团糟。
编辑:我知道在类外、调用方一侧缓存结果会更容易。我只是好奇类中是否有一种优雅的缓存方式。
编辑2: bars
是一个指向注册表池的指针,其类型是复杂的数据结构,而不是原始列表或数组。为了澄清一下,我正在使用 EnTT用于将实体组件系统集成到我的应用程序中的库,但不确定内部如何详细维护该池。
编辑3:如果你想知道什么ABC
从概念上讲,这些类型在编译时是未知的。但需要在运行时确定。事实上,它们只是我实现的许多其他类类型,因此我也可以将它们硬编码到 Foo
中。类,在这种情况下,我可能应该使用工厂模式和脚本语言来自动生成代码,但这首先就违背了使用泛型的目的。
最佳答案
在写mockup的时候,有了n的想法。 1.8e9-where's-my-share m.,对于您的“复杂的注册表池”,我编写了实际可能的 Foo
的实现。我留在那儿Foo
只是也给一些建议。如果您想要拥有一种类型的多个变量,您当然必须更改映射的值类型,例如 std::any
至std::vector<std::any>
。否则请进一步澄清您的问题。
#include <iostream>
#include <string>
#include <map>
#include <any>
struct Pool {
template<typename T>
void emplace(T x) {
this->elements_.insert_or_assign(typeid(T).hash_code(), std::make_any<T>(x));
}
template<typename T>
T& get() {
return std::any_cast<T&>(elements_.at(typeid(T).hash_code()));
}
private:
std::map<std::size_t, std::any> elements_;
};
class Foo {
public:
Foo(Pool& pool): bars_(pool) {}
void AddBar(int x) {
return bars_.emplace<int>(x);
}
template<typename T>
T& GetBar() {
return bars_.get<T>(); // a very slow function
}
private:
Pool& bars_;
};
int main(){
Pool pool;
pool.emplace(4.3); pool.emplace(std::string("a value"));
Foo foo1(pool);
foo1.AddBar(3);
std::cout << foo1.GetBar<int>() << "\n";
}
关于C++ 如何在类中缓存模板类型 T 的变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68662005/