提问人:sbi 提问时间:5/3/2013 更新时间:4/3/2016 访问量:548
如何遍历 TR1 元组
How to iterate over a TR1 tuple
问:
卡在 TR1 领域,对于测试程序,我需要对许多特定类型的对象执行某些操作。我有几个元组类型定义,如下所示:
typedef std::tr1::tuple< bool
, signed char
, signed short
, signed int
, signed long long
, unsigned char
, unsigned short
, unsigned int
, unsigned long long > integral_types;
从每个元组类型中创建一个对象。然后我有类似于这样的函数模板:
template<typename T>
void invoke_operation_1(T& obj);
需要为元组对象中的所有对象调用这些函数。
如何在 C++03 中做到这一点?
答:
8赞
Puppy
5/3/2013
#1
布里斯托尔刚刚完成了 C++14 的一个功能来解决这个问题。这并不难对付。
对于更简单的情况,您可以使用递归模板。虽然没有部分功能专业化等,但还是一团糟。
template<typename Tup, std::size_t N> struct visit_detail {
template<typename F> static void call(Tup& t, F f) {
f(std::tr1::get<N>(t));
return visit_detail<Tup, N+1>::call(t, f);
}
};
template<typename Tup> struct visit_detail<Tup, std::tr1::tuple_size<Tup>::value> {
template<typename F> static void call(Tup& t, F f) {}
}
template<typename Tup, typename F> void visit(Tup& t, F f) {
return visit_detail<Tup, 0>::call(t, f);
}
在这里,f 可以是硬编码的,也可以是参数函数对象或任何你想要的东西。
评论
0赞
sbi
5/3/2013
啊,原来确实有.谢谢,我想我可以从那里解决!tuple_size
0赞
Lightness Races in Orbit
5/3/2013
@DeadMG:哎呀!您还记得 C++14 功能的名称以供参考吗?
0赞
Puppy
5/3/2013
N3493 略有修改
0赞
Lightness Races in Orbit
5/3/2013
@DeadMG:谢谢;看起来很有趣(不过,希望他们不要在最终措辞中保留“编译时”文本!
3赞
mkaes
5/3/2013
#2
如果需要为元组中的每个对象调用相同的模板化函数,则可以使用 boost::fusion。例如
template<typename T>
void invoke_operation_1(T& obj)
{
std::cout << obj << std::endl;
}
struct executor
{
template<typename T>
void operator()(T& t) const
{
invoke_operation_1(t);
}
};
typedef boost::tuple< bool
, signed char
, signed short
, signed int
, signed long long
, unsigned char
, unsigned short
, unsigned int
, unsigned long long > integral_types;
int main()
{
integral_types t(true, 0, 1, 2, 3, 4, 5, 6, 7);
boost::fusion::for_each(t, executor());
return 0;
}
评论
0赞
sbi
5/3/2013
我犹豫是否要引入boost::fusion来做到这一点,但这看起来真的很方便,所以我可能会尝试一下。必须满足哪些条件?一些表达方式会起作用吗?使用参数占位符?executor
std::tr1::bind()
0赞
mkaes
5/3/2013
@sbi 文档说 a 所以绑定表达式应该没问题。Regular Callable Object
0赞
Arne Mertz
5/3/2013
@sbi既然是模板而不是函数,我怀疑会起作用。至少我找不到任何采用模板模板参数的重载,这是这里需要的。invoke_operation_1
boost::bind
0赞
sbi
5/3/2013
@ArneMertz:你说得有道理,我刚才碰到了这个。 好吧,那么我只需要将它包装到一个函数对象中,我想。谢谢,@mkaes!:)
0赞
sbi
5/3/2013
好吧,既然最后我确实使用了聚变,我接受了这个答案。感谢所有为此付出努力的人!
0赞
Stefan Datsko
4/3/2016
#3
template<typename tup, typename N>
struct visit_detailImpl {
template<typename f>
static void call(tup& t, f f) {
f(std::tr1::get<N::value>(t));
return visit_detailImpl<tup, std::integral_constant<std::size_t, N::value + 1> >::call(t, f);
}
};
template<typename tup> // end recursion struct
struct visit_detailImpl<tup, std::integral_constant<std::size_t, std::tr1::tuple_size<tup>::value> > {
template<typename f>
static void call(tup& t, f f) {}
};
template<typename tup, typename Fn>
void for_each_tup(tup& t, Fn f) {
return visit_detailImpl<tup, std::integral_constant<std::size_t, 0> >::call(t, f);
}
评论
0赞
sbi
4/3/2016
“被困在TR1的土地上......”
评论
tuple_size
get