当我在编译时不知道时,如何从std :: tuple获取第i个元素?

19 c++ tuples c++11

我有一个i类型的变量std::size_t和一个类型的元组std::tuple.我想得到i元组的-th元素.我试过这个:

// bindings... is of type const T&...
auto bindings_tuple = std::make_tuple(bindings...);
auto binding = std::tuple_element<i, const T&...>(bindings_tuple);
Run Code Online (Sandbox Code Playgroud)

但我得到这个编译错误,说第一个模板参数必须是一个整数常量表达式:

错误:类型' std::size_t'(又名' unsigned long')的非类型模板参数不是整型常量表达式

是否有可能获得i元组的-th元素,以及如何做到这一点?


如果可能的话,我想在不使用提升的情况下这样做.

Vic*_*kin 26

这个有可能:

struct Functor 
{
    template<typename T>
    void operator()(T& t) const { std::cout << t << std::endl; }
};

template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
  for_index(int, std::tuple<Tp...> &, FuncT)
  { }

template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
  for_index(int index, std::tuple<Tp...>& t, FuncT f)
  {
    if (index == 0) f(std::get<I>(t));
    for_index<I + 1, FuncT, Tp...>(index-1, t, f);
  }

auto t = make_tuple(1, 2, "abc", "def", 4.0f);
int i = 2; // for example
for_index(i, t, Functor());
Run Code Online (Sandbox Code Playgroud)

此代码将打印:

ABC

关于ideone的工作样本:样本


Ker*_* SB 17

你不能.这不是一个元组的用途.如果您需要动态访问元素,请使用std::array<T,N>,它几乎相同,std::tuple<T,...,T>但为您提供动态操作[i]符; 甚至像一个完全动态的容器std::vector<T>.

  • @Nawaz:可能,虽然问题混淆了"模板"和"类型",但人们可以说的是有限的.最终,在*不同*类型之间进行非编译时切换真的​​没有意义,至少不是优雅的方式... (2认同)

ken*_*ytm 13

这可能不是OP想要的,但无论如何,如果你返回一个变量类型,例如or ,就可以使用运行时i返回第i个元素.boost::variantboost::any

#include <tuple>
#include <stdexcept>
#include <boost/variant.hpp>

template <size_t n, typename... T>
boost::variant<T...> dynamic_get_impl(size_t i, const std::tuple<T...>& tpl)
{
    if (i == n)
        return std::get<n>(tpl);
    else if (n == sizeof...(T) - 1)
        throw std::out_of_range("Tuple element out of range.");
    else
        return dynamic_get_impl<(n < sizeof...(T)-1 ? n+1 : 0)>(i, tpl);
}

template <typename... T>
boost::variant<T...> dynamic_get(size_t i, const std::tuple<T...>& tpl)
{
    return dynamic_get_impl<0>(i, tpl);
}
Run Code Online (Sandbox Code Playgroud)

例如:

#include <string>
#include <iostream>

int main()
{
    std::tuple<int, float, std::string, int> tpl {4, 6.6, "hello", 7};

    for (size_t i = 0; i < 5; ++ i)
        std::cout << i << " = " << dynamic_get(i, tpl) << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

将打印:

0 = 4
1 = 6.6
2 = hello
3 = 7
terminate called after throwing an instance of 'std::out_of_range'
  what():  Tuple element out of range.
Aborted

(boost::variant<T...>需要g ++ 4.7)