如何编写通用(模板)容器推出器

时间:2017-01-17 18:25:43

标签: c++ templates

我正在努力加快“现代”C ++的速度,特别是使用模板。我有一个类覆盖了<<<<<<<运营商。工作良好。所以我决定为容器添加漂亮的打印件。

我的问题 - 有没有办法为多个容器类型编写模板,类似于下面的代码?

template <typename T>
std::ostream& operator <<(ostream& os, const vector<T>& v)
{
  os << "\n";
  for( auto x : v ) { os << "\n\t" << x; }
  os << "\n";
  return os;
}

上述代码正确地以多行格式输出向量,只要T具有&lt;&lt;运营商。我想让其他容器如列表等工作。

我也意识到,对于所有类型,以一般方式覆盖容器的输出可能是一个坏主意(或者至少是粗鲁的)。因此,上面的模板代码最终会将typename硬编码/限制为'Point'和模板化容器。

好的,恭维AndyG的建议我有以下完整代码:

#include <iostream>
#include <map>
#include <vector>

using namespace std;


struct Point {
  double x, y, z;

  Point() : x(0), y(0), z(0) {};
  Point(double a, double b, double c) : x(a), y(b), z(c) {}
  Point(double a[]) : x(a[0]), y(a[0]), z(a[0]) {}

  friend std::ostream& operator <<(ostream& os, const Point&p)
  {
    os << p.x << ", " << p.y << ", "<< p.z;
    return os;
  }

};

template <template<class> class C, class... T>
std::ostream& operator <<(ostream& os, const C<T...>& v)
{
  os << "\n";
  for( auto x : v ) { os << "\n\t" << x; }
  os << "\n";
  return os;
}

vector<Point> vp = { { 1, 2, 3 },
                     { 5, 7, 4 },
                     { 8, 2, 5 }
};

int main(int argc, char* argv[])
{
  cout << vp[0]; // works
  cout << vp;    // dosen't work,
}

但仍然没有运气。编译器无法匹配运算符&lt;&lt;用'std :: vector'

我在第一篇文章之前尝试过很多template <template>的变体,结果大致相同。我可以得到一个编译的模板,但编译器无法匹配运算符函数并使用模板。

我不知道可变参数模板包,显然是一个好主意,但没有解决问题。

1 个答案:

答案 0 :(得分:0)

好的,AndyG让我走上正轨,我想我明白发生了什么。

以下代码不起作用,因为std :: container模板也有一个具有默认值的allocator参数,您很少需要使用它。因此,我们认为大多数容器模板只采用它们将包含的类型/类。

template < template <class> class C, class... T>
std::ostream& operator <<(ostream& os, const C<T...>& v)
{ ... }

不起作用,因为我们要在我们的运算符中调用C的模板&lt;&lt;函数有两个参数而不是一个。因此,编译器无法找到匹配项。

这将有效:

template < template <class, class> class C, class... T>
std::ostream& operator <<(ostream& os, const C<T...>& v)

因为编译器可以将vector<Point, Alloc>与我们选择调用template<class, class>的{​​{1}}进行匹配。然后,它可以使用我们的函数模板为C生成重载。

请注意,此方法通常存在许多问题。 operator <<不匹配std :: map,它带有4个参数,其中2个是默认值。更糟糕的是,匹配任何两个参数模板,这些模板可能是也可能不是容器。

我们可以通过使用varg参数来解决这个问题:template <class, class>但是我们仍然搞砸了,因为现在&lt;&lt;函数模板处理来自迭代器的template <class, class...>,编译器不知道如何std::pairs

因此,尽管这对我来说更好地理解模板是一种有用的练习,但不要这样做。

此链接有一个整洁的容器漂亮的打印lib:Pretty-print C++ STL containers

相关问题