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