为什么编译器不会停止在此模板代码上给出错误

时间:2018-05-22 15:02:34

标签: c++ tuples template-specialization

我试图理解为什么这段代码会永久生成编译错误,因为我理解模板专门化应该阻止模板扩展进一步,因为它命中INDEX = 0,这应该是代码中唯一的递归。

template <typename STREAM, typename TUPLE, std::size_t INDEX> struct streamer {
  STREAM &operator()(STREAM &out, const TUPLE &tuple) {

    streamer<STREAM, TUPLE, INDEX - 1U> stream;
    return out << stream(out, tuple) << std::get<INDEX>(tuple);
  }
};

template <typename STREAM, typename TUPLE> struct streamer<0> {
  STREAM &operator()(STREAM &out, const TUPLE &tuple) {

    return out << std::get<INDEX>(tuple);
  }
};

template <typename STREAM, typename TUPLE>
STREAM &operator<<(STREAM &out, const TUPLE &tuple) {

  streamer<STREAM, TUPLE, std::tuple_size<TUPLE>::value - 1U> stream;
  return stream(out, tuple);
}

int main() {

  std::tuple<std::string, std::string> a_guy("name", "surname");
  std::cout << a_guy << std::endl;
  return 0;
}

请注意,问题不在于“如何打印元组”,因为已经有很多这样的问题。问题是为什么这个特定代码不起作用,特别是为什么它会使编译器永远循环。

1 个答案:

答案 0 :(得分:3)

您的专业化中存在语法错误,这是编译器告诉您的。此外,您的专业化中没有名为INDEX的参数,这是另一个错误。正确的语法应该是:

template <typename STREAM, typename TUPLE> struct streamer<STREAM, TUPLE, 0> {
//                                                         ^^^^^^  ^^^^^  
  STREAM &operator()(STREAM &out, const TUPLE &tuple) {

    return out << std::get<0>(tuple);
//                        ^^^
  }
};

您的代码还有另一个问题:

return out << stream(out, tuple) << std::get<INDEX>(tuple);

这会调用不存在的operator<<(std::ostream&, std::ostream&),但无论如何都不需要。只需使用return stream(out, tuple) << std::get<INDEX>(tuple);