用C ++递归打印元组

时间:2014-05-05 10:11:14

标签: gcc c++11 clang tuples variadic-templates

有几个关于如何打印tuple的提案。下面的代码片段从overloading operator << for std::tuple - possible simplications?再现了Kenny的答案。

#include <iostream>
#include <tuple>
#include <type_traits>

// template <typename... T>
// std::ostream& operator<<(std::ostream& os, const std::tuple<T...>& tup);

template <size_t n, typename... T>
typename std::enable_if<(n >= sizeof...(T))>::type
print_tuple(std::ostream&, const std::tuple<T...>&)
{}

template <size_t n, typename... T>
typename std::enable_if<(n < sizeof...(T))>::type
print_tuple(std::ostream& os, const std::tuple<T...>& tup)
{
  if (n != 0)
    os << ", ";
  os << std::get<n>(tup);
  print_tuple<n+1>(os, tup);
}

template <typename... T>
std::ostream& operator<<(std::ostream& os, const std::tuple<T...>& tup)
{
  os << "[";
  print_tuple<0>(os, tup);
  return os << "]";
}

int
main()
{
  auto t = std::make_tuple(1, std::make_tuple(2, 3));
    std::cout << t << std::endl;
}

我的问题是它与使用元组元组的clang(3.5)无法正常工作(gcc 4.9很高兴):

clang++-mp-3.5 -std=c++11 print.cc 
print.cc:19:10: error: call to function 'operator<<' that is neither visible in the
      template definition nor found by argument-dependent lookup
      os << std::get<n>(tup);
         ^
print.cc:20:7: note: in instantiation of function template specialization
      'print_tuple<1, int, std::__1::tuple<int, int> >' requested here
      print_tuple<n+1>(os, tup);
      ^
print.cc:27:7: note: in instantiation of function template specialization
      'print_tuple<0, int, std::__1::tuple<int, int> >' requested here
      print_tuple<0>(os, tup);
      ^
print.cc:35:19: note: in instantiation of function template specialization
      'operator<<<int, std::__1::tuple<int, int> >' requested here
        std::cout << t << std::endl;
                  ^
print.cc:24:19: note: 'operator<<' should be declared prior to the call site
    std::ostream& operator<<(std::ostream& os, const std::tuple<T...>& tup)
              ^

如果我在元组上取消注释operator<<的前向声明,它就可以了。但是,它并不适合你不强制operator<<定义元组的框架,而是让用户选择将它绑定到print_tuple:她必须转发声明之前的函数包括定义print_tuple的标题。

我不太清楚这里发生了什么:在模板中,clang似乎拒绝使用在模板定义之后定义的函数,但之前实例化点。我认为重要的是实例化。

相反,为什么海湾合作委员会接受?其中一个编译器错了吗?什么是让用户选择定义此operator<<并让它以递归方式正常工作的最好方法?

感谢。

1 个答案:

答案 0 :(得分:1)

您可以在此处了解clang未编译的原因:http://clang.llvm.org/compatibility.html#dep_lookup。似乎clang的行为符合标准。

要修复它,您可以在operator<<中定义namespace std以使参数依赖查找正常工作。实际上这可能是未定义的行为,因为它不符合将内容添加到std的要求。