如何对参数包进行分区
How to partition a parameter pack?
我想写一个函数模板,apply
,它接收一些函数f
,一个整数i
,和一个参数包。 apply
需要解压缩参数并对其应用f
,除了第 i
个参数 pi
.对于pi
,在将其作为参数传递给f
之前,它需要调用一些其他函数g
。
似乎我需要一种方法将参数包分为左侧、第 i
个参数和右侧。 这可能吗? 在代码中:
template<int i, typename Function, typename... Parms>
void apply(Function f, Parms... parms)
{
auto lhs = // what goes here?
auto pi = // what goes here?
auto rhs = // what goes here?
f(lhs..., g(pi), rhs...);
}
好的,我们开始吧!它真的很丑,但我无法匆忙想出更好的版本;)大部分东西都是沼泽标准模板专业化。最大的问题是创建适当大小的整数列表。我似乎记得我想出了一个不错的版本,但不知何故我不记得我做了什么。享受!
#include <iostream>
#include <utility>
// printing the values
void print_args() {}
template <typename F> void print_args(F f) { std::cout << f; }
template <typename F, typename... T>
void print_args(F f, T... args)
{
std::cout << f << ", ";
print_args(args...);
}
// the function object to be called:
struct Functor
{
template <typename... T>
void operator()(T... args)
{
std::cout << "f(";
print_args(args...);
std::cout << ")n";
}
};
// conditionally apply g():
template <typename T> T g(T value) { return 1000 + value; }
template <int i, int j, typename T>
typename std::enable_if<i != j, T>::type forward(T t) { return t; }
template <int i, int j, typename T>
typename std::enable_if<i == j, T>::type forward(T t) { return g(t); }
// create a series of integers:
template <int... Values> struct values {};
template <int Add, typename> struct combine_values;
template <int Add, int... Values>
struct combine_values<Add, values<Values...>>
{
typedef values<Values..., Add> type;
};
template <int Size> struct make_values;
template <> struct make_values<0> { typedef values<> type; };
template <int Size>
struct make_values
{
typedef typename combine_values<Size, typename make_values<Size -1>::type>::type type;
};
// applying f(t...) except for ti where g(ti) is called
template <int i, int... Values, typename Function, typename... T>
void apply_aux(values<Values...>, Function f, T... t)
{
f(forward<i, Values>(t)...);
}
template <int i, typename Function, typename... T>
void apply(Function f, T... t)
{
apply_aux<i>(typename make_values<sizeof...(T)>::type(), f, t...);
}
int main()
{
apply<3>(Functor(), 1, 2, 3, 4, 5, 6, 7, 8);
apply<4>(Functor(), 1, 2, 3, 4, 5, 6, 7, 8);
apply<5>(Functor(), 1, 2, 3, 4, 5, 6, 7, 8);
}
实际上,我不久前确实编写了类似代码。因此,请尝试以下代码:
template<unsigned N, unsigned M>
struct call_up_impl{
template<class Func, class Mutator, class Tuple, class... Args>
static void do_call(const Func& func, const Mutator& mutator, const Tuple& args, Args&&... unpacked_args) {
call_up_impl<N-1, M>::do_call(func, mutator, args, std::get<N-1>(args), std::forward<Args>(unpacked_args)...);
}
};
template<unsigned M>
struct call_up_impl<0, M> {
template<class Func, class Mutator, class Tuple, class... Args>
static void do_call(const Func& func, const Mutator&, const Tuple&, Args&&... unpacked_args) {
func(std::forward<Args>(unpacked_args)...);
}
};
template<unsigned M>
struct call_up_impl<M, M> {
template<class Func, class Mutator, class Tuple, class... Args>
static void do_call(const Func& func, const Mutator& mutator, const Tuple& args, Args&&... unpacked_args) {
call_up_impl<M-1, M>::do_call(func, mutator, args, mutator(std::get<M-1>(args)), std::forward<Args>(unpacked_args)...);
}
};
template<int i, typename Function, typename... Parms>
void apply(Function f, Parms... parms) {
std::tuple<Parms...> t(parms...);
call_up_impl<std::tuple_size<decltype(t)>::value, i + 1>::do_call(f, &g, t);
}
这是对我的原始代码的快速改编,因此它没有经过彻底测试,也许不是执行此操作的最佳方法,但它至少应该有效(至少根据快速测试并取决于您到底想要什么(。应该可以在没有元组的情况下做到这一点,但我还没有用 g++ 编译它(它似乎不喜欢所需的嵌套可变参数模板(。但是,将apply
更改为:
template<int i, typename Function, typename... Parms>
void apply(Function f, Parms&&... parms) {
std::tuple<Parms&&...> t(std::forward<Parms>(parms)...);
call_up_impl<std::tuple_size<decltype(t)>::value, i + 1>::do_call(f, &g, t);
}
可能会避免元组引入的大部分开销。最好正确转发std::get
调用的结果,但是我现在太累了,无法解决这个问题。
相关文章:
- 按字母顺序对C++问题中的子字符串索引进行分区
- 对多个(可能)重叠范围进行分区的最简单算法
- 对模板参数包操作进行因素分解
- 根据 C++ 中的属性对对象类进行分区的优化方法
- 为什么对指针的参数包进行 const 限定是一个错误?
- 使用 std::p artition 对向量进行分区
- 使用模板包进行扩展
- OpenCV:对cv::Mat进行分区
- 在C++中以相同的方式同时对两个元素范围进行分区
- 在 C++11 或 C++1y 中对非类型模板参数包进行排序
- C++ 在复制透视时对整数进行分区
- 在c++中围绕中值进行分区的快速排序实现
- 通过原始套接字接收"syn"数据包时,如何使用"syn ack"数据包进行响应?
- 使用C++中的参数包进行函数式编程
- 如何对参数包进行分区
- 用C语言对蓝牙数据包进行分析
- 在sybase选择查询中对表进行分区
- 按索引对数组进行分区
- 对大量三维点数据进行分区
- 如何对可变参数模板函数的异构参数包进行泛型计算