【问题标题】:How to read a tuple?如何读取元组?
【发布时间】:2017-05-27 08:43:19
【问题描述】:

代码如下。看起来很简单,但是会出现一些我找不到错误的编译错误。

#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&lt;I&lt;0x01,void&gt;::type read(QDataStream &amp;,std::tuple&lt;_Types1...&gt; &amp;)'

经过多次测试,发现下面的代码是可以的

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 错误。 :-(

【问题讨论】:

  • Cannot reproduce。发布SSCCE
  • @Jefffrey 你的模板实例化在哪里?
  • 42 岁时可以生育(但不鼓励女性生育)
  • @sehe 我还没有 42 岁,但这个笑话适用于任何一种方式:)。

标签: c++ tuples


【解决方案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);
}

【讨论】:

  • 注意: 上面的 sn-p 有点不准确(除非 OP 想要这种行为);它将以错误的顺序读取元素。 2 将在t 的第一个元素中,1 将在第二个元素中。
  • @FilipRoséen-refp 是的,我告诉了如何修复示例中的代码并粘贴“反向”读数。我写了这个。
【解决方案2】:

我也想这样做,所以我写了这个(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;
}

【讨论】:

    猜你喜欢
    • 2021-06-29
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    • 2015-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多