如何阅读元组?

时间:2014-05-19 19:04:58

标签: c++ tuples

代码如下。看起来很简单,但是得到一些我无法找到错误的编译错误。

#define ENABLE_IF(Condition, Type) typename enable_if < (Condition), Type>::type

template<size_t I = 0, class... Ts>
ENABLE_IF(I == sizeof...(Ts), void) read(QDataStream& in, tuple<Ts...>& t)
{}

template<size_t I = 0, class... Ts>
ENABLE_IF(I < sizeof...(Ts), void)  read(QDataStream& in, tuple<Ts...>& t)
{
   in >> std::get<I>(t);
   read<I + 1>(in, t);
}

lat语句出错:error C2770: invalid explicit template argument(s) for 'enable_if<I<0x01,void>::type read(QDataStream &,std::tuple<_Types1...> &)'

经过更多测试,结果证明以下代码没问题

template<size_t I = 0, class Tuple>
ENABLE_IF(I == tuple_size<Tuple>::value, void) read(QDataStream& in, Tuple& t)
{}

template<size_t I = 0, class Tuple>
ENABLE_IF(I < tuple_size<Tuple>::value, void)  read(QDataStream& in, Tuple& t)
{
    in >> std::get<I>(t);
    read<I + 1>(in, t);
}

这使用元组类型作为模板参数而不是其元素类型包。是什么原因? VS2013的编译错误?

与其他编译器一起测试。原始代码没问题。我认为这是一个VS2013错误。 : - (

2 个答案:

答案 0 :(得分:1)

这很简单!您的主模板不仅有一个参数。你应该通过第二个参数Ts ......:

read<I + 1, Ts...>(in, t);

反向订单阅读

#include <iostream>
#include <sstream>
#include <tuple>

template<size_t I, typename... Ts>
struct reader
{
    static void read(std::istream& i, std::tuple<Ts...>& t)
    {
        i >> std::get<I>(t);
        reader<I - 1, Ts...>::read(i, t);
    }
};

template<typename... Ts>
struct reader<0, Ts...>
{
    static void read(std::istream& i, std::tuple<Ts...>& t)
    {
        i >> std::get<0>(t);
    }
};

template<typename... Ts>
void read(std::istream& i, std::tuple<Ts...>& t)
{
    reader<sizeof...(Ts) - 1, Ts...>::read(i, t);
}

int main()
{
    std::istringstream istr("1 2");
    std::tuple<int, double> t;
    read(istr, t);
}

答案 1 :(得分:0)

我也想这样做,所以我写了这篇文章(C ++ 17仅由if constexpr引起):

#include <tuple>
#include <iostream>

template<class Head, class... Tail>
std::tuple<Head, Tail...> tuple_read_impl(std::istream& is) {
    Head val;
    is >> val;
    if constexpr (sizeof...(Tail) == 0) // this was the last tuple value
        return std::tuple{val};
    else
        return std::tuple_cat(std::tuple{val}, tuple_read_impl<Tail...>(is));
}

template<class... Types>
std::istream& operator>>(std::istream& is, std::tuple<Types...> &tup) {
    tup = tuple_read_impl<Types...>(is);
    return is;
}

int main ()
{
    std::tuple<size_t, size_t> tup;
    std::cin >> tup;
    auto [x, y] = tup;
    std::cout << x << ' ' << y;
}