首页 > 解决方案 > C++ 迭代模板参数

问题描述

可以根据参数列表和使用 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

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

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

感谢@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...>{});
}

标签: c++c++17template-meta-programmingparameter-pack

解决方案


嗯,这是你追求的东西吗?

#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;

推荐阅读