按给定类型拆分参数包
Split a parameter pack at a given type
如何根据给定的分隔符类型拆分参数包?例如:
struct separator {
// ...
};
struct foo1 {
foo1(int a, int b) {...}
};
struct foo2 {
foo2(double a, double b, double c) {...}
};
template <typename... ArgsT>
void func(ArgsT&&... args) {
// args have two separators
auto f1 = foo1(/*How can I get the argument list to construct foo1?*/);
auto f2 = foo2(/*same as above*/);
auto f3 = ....
}
separator s1, s2;
func(s1, 1, 2, s2, 4.5, 6.7, 7.8);
在上面的例子中,给定的args
保证至少有一个类型为separator
的参数。每个分隔符后面跟着一个参数列表来构造一个结构体(例如,foo1
和foo2
等等)。基于c++ 14或c++ 1z的解决方案。
好的,我想我知道了。
#include <functional>
#include <iostream>
template<typename T>
T recrusiveSearchHelper(int which,int current, T last)
{
return last;
};
template<typename T, typename... Args>
T recrusiveSearchHelper(int which,int current,T first,Args... args)
{
if (which == current)
{
return first;
}
recrusiveSearchHelper(which,current + 1,args...);
}
template <typename T,typename... Args>
T recrusiveSearch(int which, T first, Args... args)
{
return recrusiveSearchHelper(which,0,first,args...);
}
struct Seperator
{
};
void foo2(double a,double b,double d)
{
std::cout << "Foo two: " << a << " : " << b << " : " << d << std::endl;
};
void foo1(int a,int b)
{
std::cout << "Foo One: " << a << " : "<< b << std::endl;
};
void zipper(int& index,std::function<void(int)>fn, Seperator s)
{
index++;
fn(index);
}
template <typename T>
void zipper(int& index, std::function<void(int)>fn, T data)
{
index++;
};
template <typename T,typename... Args>
void zipper(int& index, std::function<void(int)> fn,T first, Args... args)
{
index++;
zipper(index,fn,args...);
};
template <typename... Args>
void zipper(int& index, std::function<void(int)> fn,Seperator first, Args... args)
{
index++;
fn(index);
zipper(index,fn,args...);
};
template <typename T,typename... Args>
void useWithSeperator(T first,Args... args)
{
int index = 0;
int current = 0;
std::function <void(int)> fn = [¤t,first,args...](int where)
{
if (where - current == 3)
{
foo1(recrusiveSearch(where-3,first,args...),recrusiveSearch(where-2,first,args...));
}else if (where - current == 4)
{
foo2(recrusiveSearch(where-4,first,args...),recrusiveSearch(where-3,first,args...),recrusiveSearch(where-2,first,args...));
}
current = where;
};
zipper(index,fn,first);
zipper(index,fn,args...);
};
int main(int argc, char **argv)
{
useWithSeperator(1,2,3,Seperator(),4,5,Seperator(),1,1,2,3,4,Seperator(),1,2,5,Seperator());
}
这有点混乱,但是它的作用是通过一个辅助变量模板来缩小每次迭代的搜索范围,直到Element在其递归循环中第一次成为我们想要的位置的元素。剩下的就很简单了,我们需要检索数据并跟踪我们的周期。
首先,不这样做,取元组并从所述元组构造对象。
func(std::make_tuple(1, 2), std::make_tuple(4.5, 6.7, 7.8));
不管怎么做,我们最后都会到这里来的。
如果失败,编写一个函数,该函数接受std::tuple<Ts...>
并将其拆分为分隔符上的std::tuple< std::tuple<???>... > tuple_of_tuples
拆分,然后执行std::apply( good_func, tuple_of_tuples )
。
namespace details {
struct adl_helper {};
template<class Sep, class...Cs, class...Zs>
auto tuple_splitter( adl_helper, std::tuple<> in, std::tuple<Cs...> working, std::tuple<Zs...> out ) {
(void)in;
return std::tuple_cat( std::move(out), std::make_tuple(working) );
}
template<class Sep, class T0, class...Ts, class...Cs, class...Zs,
std::enable_if_t<!std::is_same<T0, Sep>{}, int> =0
>
auto tuple_splitter( adl_helper, std::tuple<T0, Ts...> in, std::tuple<Cs...> working, std::tuple<Zs...> out ) {
auto in_indexer = indexer<sizeof...(Ts)>();
return tuple_splitter<Sep>(
adl_helper{},
in_indexer( [&](auto...i){ return std::forward_as_tuple( std::get<i+1>(std::move(in))...); } ),
std::tuple_cat( std::move(working), std::make_tuple( std::get<0>(in) ) ),
std::move(out)
);
}
template<class Sep, class...Ts, class...Cs, class...Zs>
auto tuple_splitter( adl_helper, std::tuple<Sep, Ts...> in, std::tuple<Cs...> working, std::tuple<Zs...> out ) {
auto in_indexer = indexer<sizeof...(Ts)>();
return tuple_splitter<Sep>(
adl_helper{},
in_indexer( [&](auto...i){ return std::forward_as_tuple( std::get<i+1>(std::move(in))...); } ),
std::make_tuple(),
std::tuple_cat( std::move(out), std::make_tuple(working) )
);
}
}
template<class Sep, class...Ts>
auto tuple_splitter( std::tuple<Ts...> tuple ) {
return details::tuple_splitter<Sep>( details::adl_helper{}, std::move(tuple), std::make_tuple(), std::make_tuple() );
}
现在tuple_splitter<Bob>( some_tuple )
将把some_tuple
拆分为元组的元组,每个子元组的元素由Bob
分隔。
生活例子。
我使用我的indexer
实用程序弹出元组的第一个元素。它允许您在不离开当前函数体的情况下获得编译时的整数包。
template<class=void,std::size_t...Is>
auto indexer( std::index_sequence<Is...> ) {
return [](auto&&f)->decltype(auto) {
return decltype(f)(f)( std::integral_constant<std::size_t, Is>{}... );
};
}
// takes a number N
// returns a function object that, when passed a function object f
// passes it compile-time values from 0 to N-1 inclusive.
template<std::size_t N>
auto indexer() {
return indexer( std::make_index_sequence<N>{} );
}
相关文章:
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 使用 C++ 将命令行参数拆分为参数/向量
- 在带括号的字符串中拆分参数
- Doxygen,当参数类型定义使签名相同时,如何拆分函数文档?
- 拆分参数包
- 根据函数指针参数拆分多个可变参数模板包
- 如何使用 c++ 逐行处理文本文件并将其参数拆分为变量?
- 在预处理器中拆分参数C++
- 如何在各个参数中拆分#__VA_ARGS__
- 按给定类型拆分参数包
- 拆分64位值以适应双精度参数类型
- 在c++ /Qt中拆分Lua函数调用的混合字符串/数字参数列表
- 取消对拆分函数调用参数的信任