成语用于模拟运行时数字模板参数? [英] Idiom for simulating run-time numeric template parameters?
问题描述
假设我们有
template <unsigned N> foo() { /* ... */ }
已定义。现在,我要实现
defined. Now, I want to implement
do_foo(unsigned n);
调用 foo()
。这不仅是一个合成示例-实际上确实在现实生活中发生(当然,不一定要使用void-to-void函数和仅一个模板参数,但是我很简单。当然,在C ++中,我们不能具有以下内容:
which calls the corresponding variant of foo()
. This is not merely a synthetic example - this does actually happen in real life (of course, not necessarily with void-to-void functions and just one template parameter, but I'm simplfying. Of course, in C++, we can't have the following:
do_foo(unsigned n) { foo<n>(); }
我现在要做的是
do_foo(unsigned n) {
switch(n) {
case n_1: foo<n_1>(); break;
case n_2: foo<n_2>(); break;
/* ... */
case n_k: foo<n_k>(); break;
}
}
当我知道n有效地限制在n_1,...,n_k范围内时,这似乎并不合理,当通话时间更长并且我需要时可以重复多次复制模板和常规参数的长序列。
when I know n is effectively limited in range to n_1,...,n_k. But this is unseemly, and much more so when the call is longer and I need to duplicate a long sequence of template and regular parameters many times.
当我想想也许有人会开始使用宏来生成这些switch语句时,已经工作了在某些图书馆对此进行了研究,并可以分享他们的工作。如果不是这样,使用某种具有任意功能的C ++构造(带有一些模板和非模板参数序列,包括一些数字模板参数和某种形式的值序列)来生成包装器,也许仍然可行。可以将该模板参数用作附加的运行时参数,例如
I was about to start working on a macro to produce these switch statements, when I got to thinking maybe someone has already worked on this in some library and could share what they did. If not, perhaps it's still feasible to have some kind of C++ construct which takes an arbitrary function, with any sequence of template and non-template parameters including some numeric template parameter, and a sequence of values in some form, to produce a wrapper which can take that template parameter as an additional run-time parameter instead, e.g.
auto& transformed_foo = magic<decltype(foo)>(foo)::transformed;
推荐答案
这是@TartanLlama解决方案的扩展-argument function到具有任意数量参数的函数。它还具有避免在扩展为lambda时无法正确扩展可变参数模板参数包的GCC错误(在版本8之前)的额外好处。
This is an extension of @TartanLlama's solution for a no-argument function to a function with an arbitrary number of arguments. It also has the added benefit of circumventing a GCC bug (before version 8) of failing to properly expand variadic template parameter packs when the expansion is of a lambda.
#include <iostream>
#include <utility>
#include <array>
#include <functional>
struct Foo {
template <std::size_t N, typename... Ts> void operator()(std::integral_constant<std::size_t,N>, Ts... args)
{ foo<N>(std::forward<Ts>(args)...); }
};
template <std::size_t N, typename F, typename... Ts>
std::function<void(Ts...)> make_visitor(F f) {
return
[&f](Ts... args) {
f(std::integral_constant<std::size_t,N>{}, std::forward<Ts>(args)...);
};
}
template <std::size_t Offset, std::size_t... Idx, typename F, typename... Ts>
void visit(F f, std::index_sequence<Idx...>, std::size_t n, Ts... args) {
static std::array<std::function<void(Ts...)>, sizeof...(Idx)> funcs {{
make_visitor<Idx+Offset, F, Ts...>(f)...
}};
funcs[n-Offset](std::forward<Ts>(args)...);
};
template <std::size_t Start, std::size_t End, typename F, typename... Ts>
void visit(F f, std::size_t n, Ts... args) {
visit<Start>(f, std::make_index_sequence<End-Start>{}, n, std::forward<Ts>(args)...);
};
这篇关于成语用于模拟运行时数字模板参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!