C++ 迭代模板参数

C++ iterate template parameters

可以根据参数列表和使用 C++17 折叠的一些逻辑来填充虚拟机的适当寄存器,如下所示: https://github.com/fwsGonzo/libriscv/blob/master/lib/libriscv/machine_vmcall.hpp#L35

https://github.com/fwsGonzo/libriscv/blob/master/lib/libriscv/machine_vmcall.hpp#L18

结构将被压入堆栈,地址将占用一个整数寄存器槽。因此,我可以将常规函数调用转换为对我的虚拟机的调用。我不认为任何其他编程语言可以做到这一点。

现在,反之则有系统调用处理程序。它们看起来像这样: https://github.com/fwsGonzo/libriscv/blob/master/emulator/src/syscalls.cpp#L20

为了简化系统调用处理,我希望能够获取一个参数类型列表,对每个参数类型执行一些逻辑(根据类型提取值),然后选择性地使用我建立的论据。

参数的数量和类型是事先已知的。这些值在从机器寄存器中提取之前是未知的。

感谢@bipll 的回答。我选择这样实现它:

template<typename... Args, std::size_t... indices>
inline auto resolve_args(machine_t& m, std::index_sequence<indices...>)
{
    std::tuple<std::decay_t<Args>...> retval;
    ((std::get<indices>(retval) = m.template sysarg<Args>(indices)), ...);
    return retval;
}
template<typename... Args>
inline auto resolve_args(machine_t& m) {
    return resolve_args<Args...>(m, std::index_sequence_for<Args...>{});
}

嗯,这是你想要的吗?

#include <iostream>
#include <type_traits>

template<class... Args> void omg(Args &&...args)
{
        ((std::is_integral_v<Args> && std::cout << args << " is integral\n"), ...);
}

int main() {
        omg(1, 42, 3.14, "Hi!", 0<<0);
}
1 is integral
42 is integral
0 is integral

operator, 可能是一元 foreach 折叠表达式的瑞士军刀。

您甚至不需要实际值:

template<class... Args> void omg()
{
        std::size_t i{};
        ((++i,
          std::is_integral_v<Args> && std::cout <<
                  "Arg #" << i << " is integral\n"
          || std::is_scalar_v<Args> && std::cout <<
                  "Arg #" << i << " is not integral, yet is scalar\n"
          ), ...);
}

int main() {
        omg<int, int, double, char const *, std::size_t>();
}

如果您手头没有实际值,但有它们的类型和索引访问权限,那么您可以通过一些非常基本的方式轻松检索它们:

template<class... Args, std::size_t... indices> void add_args(
        std::index_sequence<indices...>)
{
    (p.append(sys.get_arg<Args>(indices)), ...);
}

template<class... Args> void add_args() {
    add_args<Args...>(std::index_sequence_for<Args...>{});
}

即使将它们存储在一个元组中也有点棘手而且不是很简单:

std::tuple<std::decay_t<Args>...> retval;
((std::get<indices>(retval) = sys.get_arg<Args>(indices)), ...);
return retval;