如何根据给定的分隔符类型拆分参数包?例如:
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的解决方案将不胜感激。
答案 0 :(得分:0)
好的,我想我看了一眼:
#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首先成为其递归循环中所需位置的元素。其余的很简单,我们需要检索数据并跟踪我们的循环时间。
我会尽快为这个答案添加更多细节。
答案 1 :(得分:0)
首先,不要这样做,而是使用元组并从所述元组构造对象。
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>{} );
}