c++ 我能推导出可调用对象的参数吗?

oo7oh9g9  于 2023-05-08  发布在  其他
关注(0)|答案(1)|浏览(107)

我正在编写一个面向数据的编程注册表,它看起来有点像ECS注册表,工作方式如下:

void KillEnemy(EnemyList &enemies, ProjectileList &projectiles);

int main() {
    auto registry
     = Registry{}
      .add_data(EnemyList{})
      .add_data(ProjectileList{})
      .add_data(TerrainList{});
    //automatically call KillEnemy with proper arguments.
    registry.call(KillEnemy);
}

我还没有弄清楚add_data部分,但我认为可以用constexprstd::tuple来完成。我目前的Registry实现看起来像这样:

struct Registry {
    std::tuple<int, double, float> data;
    template<typename R, typename... Args>
    R call(R (*f)(Args...)) {
        return f(std::get<Args>(data)...);
    }
};

这适用于函数指针,但如果我能将其与lambdas一起使用,则会更符合人体工程学。我想不出一个方法来推导参数。这可能吗?
更新:我刚刚写了add_data。这是我目前的实现:

template <typename... DataType>
struct Reg {
    std::tuple<DataType...> data;
    template<typename R, typename... Args>
    R call(R (*f)(Args...)) {
        return f(std::get<std::remove_reference_t<Args>>(data)...);
    }
    template<typename T>
    constexpr Reg<T, DataType...> add_data(T new_data = {}) &&{
        return {std::tuple_cat(std::move(data), std::tuple<T>(new_data))};
    }
};

int main() {
    auto r = Reg<>{}
        .add_data<int>()
        .add_data<double>()
        .add_data<float>();
    r.call(system_with_duble);
    r.call(system_with_float);
    r.call(system_with_double_and_float);
}
fdbelqdn

fdbelqdn1#

我刚想明白了

struct Registry {
    std::tuple<DataType...> data;
    template<typename R, typename... Args>
    R call(R (*f)(Args...)) {
        return f(std::get<std::remove_reference_t<Args>>(data)...);
    }
    template<typename F>
    auto call(F functor) {
        return functor_call_helper(&functor, &F::operator());
    }
    template<typename T>
    Registry<T, DataType...> add_data() & = delete;
    template<typename T>
    constexpr Registry<T, DataType...> add_data(T new_data = {}) &&{
        return {std::tuple_cat(std::move(data), std::tuple<T>(new_data))};
    }

private:
    template <typename T, typename R, typename... Args>
    R functor_call_helper(T *callable, R (T::* f)(Args...) const) {
        return (callable->*f)(std::get<std::remove_reference_t<Args>>(data)...);
    }
};

int main() {
    auto r = Registry<>{}.add_data<int>().add_data<double>().add_data<float>();
    r.call(system_with_double);
    r.call(system_with_float);
    r.call(system_with_float_and_double);
    r.call([](int i){std::cout<<i<<'\n';});
}

相关问题