在C++中,当运行时知道元素索引时,是否可以获取元组的一个元素的类型?

Ale*_*son 1 c++ metaprogramming c++11

typedef std::tuple< int, double > Tuple;
Tuple t;
int a = std::get<0>(t);
double b = std::get<1>(t);

for( size_t i = 0; i < std::tuple_size<Tuple>::value; i++ ) {
   std::tuple_element<i,Tuple>::type v = std::get<i>(t);// will not compile because i must be known at compile time
}
Run Code Online (Sandbox Code Playgroud)

我知道可以编写代码来实现std::get工作(参见例如迭代元组),是否可以开始std::tuple_element工作?

一些约束(它们可以放松):

没有可变参数模板,没有Boost

Nic*_*las 7

C++是一种编译时键入的语言.您不能拥有C++编译器在编译时无法确定的类型.

您可以使用各种形式的多态来解决这个问题.但是在一天结束时,每个变量都必须具有明确定义的类型.因此,虽然您可以使用Boost.Fusion算法迭代元组中的变量,但您不能拥有循环,其中循环的每次执行可能使用与最后一个不同的类型.

Boost.Fusion可以摆脱它的唯一原因是因为它不使用循环.它使用模板递归来"迭代"每个元素并调用用户提供的函数.


Seb*_*ian 5

如果您不想提升,迭代元组的答案已经告诉您需要知道的一切。您必须编写一个编译时for_each循环(未经测试)。

template<class Tuple, class Func, size_t i>
void foreach(Tuple& t, Func fn) {
    // i is defined at compile-time, so you can write:
    std::tuple_element<i, Tuple> te = std::get<i>(t);
    fn(te);
    foreach<i-1>(t, fn);
}

template<class Tuple, class Func>
void foreach<0>(Tuple& t, Func fn) { // template specialization
    fn(std::get<0>(t)); // no further recursion
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

struct SomeFunctionObject {
    void operator()( int i ) const {}
    void operator()( double f ) const {}
};

foreach<std::tuple_size<Tuple>::value>(t, SomeFunctionObject());
Run Code Online (Sandbox Code Playgroud)

但是,如果您想迭代元组的成员,Boost.Fusion确实是最佳选择。

#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/adapted/boost_tuple.hpp>
Run Code Online (Sandbox Code Playgroud)

并在您的代码中写入:

boost::for_each(t, SomeFunctionObject());
Run Code Online (Sandbox Code Playgroud)

这是 boost::tuple 的示例。这里有一个 boost::fusion 与 std::tuple 一起使用的适配器:http ://groups.google.com/group/boost-list/browse_thread/thread/77622e41af1366af/