C++ 如何在类中缓存模板类型 T 的变量?

标签 c++ templates entity-component-system

假设我有一个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::anystd::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/

相关文章:

c++ - 将 CStringArray 的内容复制到 std::vector

C++ 没有函数模板的实例匹配指定的类型

c++ - 找出n个月前的确切日期和时间?

c++ - 如何生成泊松过程?

templates - 如何将数据驱动的概念应用于机器人框架中的用户关键字?

php - 在Smarty模板引擎中执行MD5函数

C++实体组件系统和使用模板访问组件

c++ - 在实体组件系统中将实体与系统匹配的有效方法

c++ - string::capacity/reserve() 算作终止 null 吗?