如何遍历 TR1 元组

How to iterate over a TR1 tuple

提问人:sbi 提问时间:5/3/2013 更新时间:4/3/2016 访问量:548

问:

卡在 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 中做到这一点?

C++ C++03 标准元组

评论

1赞 Lightness Races in Orbit 5/3/2013
到目前为止,您尝试过什么?
0赞 jrok 5/3/2013
不是在 tr1 中吗?tuple_sizeget
0赞 Lightness Races in Orbit 5/3/2013
Boost.Fusion 方法应该与 C++03 兼容。这里采用手动方法
3赞 Lightness Races in Orbit 5/3/2013
@sbi:谁说过家庭作业?SO 问题有望展示先前的研究。:)你的紧迫性无关紧要......
2赞 Luc Touraille 5/3/2013
哎呀,我注意到你的问题特别问了 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来做到这一点,但这看起来真的很方便,所以我可能会尝试一下。必须满足哪些条件?一些表达方式会起作用吗?使用参数占位符?executorstd::tr1::bind()
0赞 mkaes 5/3/2013
@sbi 文档说 a 所以绑定表达式应该没问题。Regular Callable Object
0赞 Arne Mertz 5/3/2013
@sbi既然是模板而不是函数,我怀疑会起作用。至少我找不到任何采用模板模板参数的重载,这是这里需要的。invoke_operation_1boost::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的土地上......”