我可以在 C++17 中将参数类型分支到参数包吗?
Can I branch on argument type to parameter pack in C++17?
当前(旧)函数调用签名:
long vmcall(const std::string& function_name,
std::vector<address_t> args);
现在因为我只能使用(地址大小的)整数调用来宾,这是一个非常有限的接口,我想扩展它至少也处理浮点值,可能还有其他的,就像这样:
template <typename... Args>
long vmcall(const std::string& function_name,
Args&&... args);
这将是新的函数签名,取代旧的。
显示 args 向量当前的使用方式:
template <int W>
inline void Machine<W>::setup_call(
address_t call_addr, address_t retn_addr,
std::vector<address_t> args)
{
assert(args.size() <= 8);
cpu.reg(RISCV::REG_RA) = retn_addr;
for (size_t arg = 0; arg < args.size(); arg++) {
cpu.reg(RISCV::REG_ARG0 + arg) = args[arg];
}
cpu.jump(call_addr);
}
这个函数是从 vmcall 使用 std::move(args) 调用的,它所做的只是将 args 向量中的整数参数增量地复制到整数 CPU 寄存器中。当我想调用一个只接受整数参数的函数时,这很好用。所以,如果我想调用一个函数,比如说,接受一个浮点参数,那么就没有办法做到这一点。这是因为 FP 寄存器是完全独立的,需要以不同的方式处理。
此外,通过 NaN 装箱处理 32 位和 64 位浮点数的方式不同。所以,如果能够区分 float 和 double 就好了。
我一开始就不太擅长模板魔法。如何根据参数包中每个元素的类型进行分支?
在C++17中,遍历参数包的方式是使用逗号fold:
(<expr>, ...); // expr contains Args and/or args
如果单个表达式不够用,可以使用立即调用的 lambda:
([&] {
<statements> // statements contains Args and/or args
}(), ...);
将此与 if constexpr
结合您的论点类型:
std::vector<address_t> addr_args;
std::vector<fp_t> fp_args;
([&] {
if constexpr (std::is_integral_v<Args>)
addr_args.push_back(args);
else
fp_args.push_back(args);
}(), ...);
当前(旧)函数调用签名:
long vmcall(const std::string& function_name,
std::vector<address_t> args);
现在因为我只能使用(地址大小的)整数调用来宾,这是一个非常有限的接口,我想扩展它至少也处理浮点值,可能还有其他的,就像这样:
template <typename... Args>
long vmcall(const std::string& function_name,
Args&&... args);
这将是新的函数签名,取代旧的。
显示 args 向量当前的使用方式:
template <int W>
inline void Machine<W>::setup_call(
address_t call_addr, address_t retn_addr,
std::vector<address_t> args)
{
assert(args.size() <= 8);
cpu.reg(RISCV::REG_RA) = retn_addr;
for (size_t arg = 0; arg < args.size(); arg++) {
cpu.reg(RISCV::REG_ARG0 + arg) = args[arg];
}
cpu.jump(call_addr);
}
这个函数是从 vmcall 使用 std::move(args) 调用的,它所做的只是将 args 向量中的整数参数增量地复制到整数 CPU 寄存器中。当我想调用一个只接受整数参数的函数时,这很好用。所以,如果我想调用一个函数,比如说,接受一个浮点参数,那么就没有办法做到这一点。这是因为 FP 寄存器是完全独立的,需要以不同的方式处理。
此外,通过 NaN 装箱处理 32 位和 64 位浮点数的方式不同。所以,如果能够区分 float 和 double 就好了。
我一开始就不太擅长模板魔法。如何根据参数包中每个元素的类型进行分支?
在C++17中,遍历参数包的方式是使用逗号fold:
(<expr>, ...); // expr contains Args and/or args
如果单个表达式不够用,可以使用立即调用的 lambda:
([&] {
<statements> // statements contains Args and/or args
}(), ...);
将此与 if constexpr
结合您的论点类型:
std::vector<address_t> addr_args;
std::vector<fp_t> fp_args;
([&] {
if constexpr (std::is_integral_v<Args>)
addr_args.push_back(args);
else
fp_args.push_back(args);
}(), ...);