我怎么能写一个可变的函数,在编译时将id转换为变量,并调用另一个函数与那些代替?



我有一个函数映射从一些id到变量,像这样:

enum CID
{
A, B
};
struct ComponentA{};
struct ComponentB{};
ComponentA ca;
ComponentB cb;
template <uint32_t id>
constexpr auto & componentForId()
{
if constexpr (id == A)
return ca;
if constexpr (id == B)
return cb;
}

然后我有一个我想调用的目标函数:

void someFunction(ComponentA&, ComponentB&)
{ ... }

但是我想间接地调用这个函数,只使用使用componentForId函数转换的数字标识符。我想函数框架应该是这样的:

template <typename ...Args>
void callIndirectly(Args&&... args)
{
// How to implement this function so that it in effect calls 
//      someFunction(componentForId<A>(), componentForId<B>());
}

所以我可以这样命名它:

callIndirectly(A, B);

等于

someFunction(componentForId<A>(), componentForId<B>());

我已经尝试了各种各样的变化,但我就是不知道如何正确地做参数包装在这种情况下的工作。我如何在这里实现callIndirectly?

https://godbolt.org/z/sxdxeojf3

完整的示例:

#include <cstdint>
enum CID
{
A, B
};
struct ComponentA{};
struct ComponentB{};
ComponentA ca;
ComponentB cb;
template <uint32_t id>
constexpr auto & componentForId()
{
if constexpr (id == A)
return ca;
if constexpr (id == B)
return cb;
}
void someFunction(ComponentA&, ComponentB&)
{}
template <typename ...Args>
void callIndirectly(Args&&... args)
{
// How to implement this function so that it in effect calls 
//      someFunction(componentForId<A>(), componentForId<B>());
}
int main() {
someFunction(ca, cb);
someFunction(componentForId<A>(), componentForId<B>());
callIndirectly(A, B);
}

使用运行时参数调用callIndirectly()。您只能使用基于switch-case(或if-else if)的逐个参数委托转换为编译时参数,使用类似cps的构造调用下一个转换器(最终是访问者):

// base case for visitNext
template<CID... PrevArgs>
auto visitNext() {
someFunction(ComponentForId<PrevArgs>()...);
}
// assuming arg, args... as arguments, PrevArgs... as compile-time arguments
template<CID... PrevArgs, typename... Args>
auto visitNext(CID arg, Args... args) {
switch(arg) {
case 'A': return visitNext<PrevArgs..., A>(args...);
case 'B': return visitNext<PrevArgs..., B>(args...);
}
}

然而,基于您如何调用它,您可能不需要所有这些。您可以使用模板值参数直接调用(这是这里的基本情况),也可以使用std::integral_constant<>。后者将整型值封装在类型中(即,std::integral_constant<CID, A>std::integral_constant<CID, B>是不同的类型),但可以同时转换为编译时值和运行时值。

最新更新