c++ 使用模板参数创建传递给另一个函数的参数列表

okxuctiv  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(122)

我正在创建一个系统,用户可以通过定义数据(称为资源)和作用于资源的函数(称为系统)来创建应用程序。我希望用户纯粹提供一个特定类型的函数指针,并从该类型推断出需要传递给该函数的资源。
下面是一些上下文代码:

#include <vector>
#include <unordered_map>
#include <memory>

using TypeID = size_t;

class Type
{
public:
    template <class T>
    static TypeID ID()
    {
        static TypeID id = s_Counter++;

        return id;
    }

private:
    inline static TypeID s_Counter = 0;
};

struct Resource
{
   virtual ~Resource() = default;
};

template <typename T>
struct Res : public Resource
{
    inline static const TypeID ID = Type::ID<T>(); // Type::ID<T>() just returns a unique ID for every type
    T Data;
};

class Application
{
private:
    std::unordered_map<TypeID, std::unique_ptr<Resource>> m_Resources;
    std::vector<void(*)()> m_Systems;

public:
    template <typename T>
    void AddResource()
    {
        m_Resources[Res<T>::ID] = std::make_unique<Res<T>>();
    }

    template <typename T>
    T& GetResource()
    {
        return m_Resources[Res<T>::ID]->Data;
    }

    template <typename... Resources>
    void AddSystem(void (*pSystem)(Resources...))
    {
        m_Systems.push_back([pSystem]() {
            pSystem(/*Here, for every parameter in the parameter pack Resources, 
                    I want to call GetResource<>() with the appropriate template parameter*/);
        });
    }
};

struct Foo
{
    int a;
    float b;
};

void system(Foo foo, int num, float val)
{
    /*do stuff with foo, num and val*/
}

int main()
{
    Application app;

    app.AddResource<Foo>();
    app.AddResource<int>();
    app.AddResource<float>();

    app.AddSystem(system);
}

AddSystem函数中,我想将一个模板参数列表(如<int, float, Foo>)转换为一个函数调用列表GetResource<int>(), GetResource<float>(), GetResource<Foo>(),以便将这些函数的返回值传递给用户定义的函数pSystem。这个例子应该会生成pSystem(GetResource<int>(), GetResource<float>(), GetResource<Foo>());行。
有没有一个便携式的方法来做到这一点?例如标准库提供的函数?
如果有另一种明显的方式来实现同样的结果,请让我知道,这个设计还没有确定下来。

zbwhf8kr

zbwhf8kr1#

要将Get<Args>...传递给函数指针,可以使用包扩展:

#include <iostream>
#include <utility>

void foo(int a,float b,double c) {
    std::cout << a << b << c;
}

template <typename T> int get() { return 0; }


template <typename ...Args>
void bar(void(*f)(Args...)) {
    f( get<Args>()...);  // calls f(get<int>(),get<float>(),get<double>())
}

int main() {
    bar(foo);
}

相关问题