我有一个函数映射从一些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>
是不同的类型),但可以同时转换为编译时值和运行时值。