c++ - 如何为 ostream 的 operator<< 模板

标签 c++ templates

以下不会为我编译。我没主意了……有什么帮助吗?

template<>
inline
std::ostream& operator<< <const std::map<std::string, std::string> > (std::ostream& stream, const std::map<std::string, std::string>& some_map)
{
  return stream;
}

g++ 给我以下错误:

错误:“<” token 之前的预期初始化程序

编辑:1 好吧,既然每个人都在告诉我要重载,那么让我举一个对重载没有意义的例子。如果我有这个怎么办:

template <typename T>
inline
std::ostream& operator<<(std::ostream& stream, const T& something)
{
  stream << something.toString();
  return stream;
}

class Foo
{
public:
  Foo(std::string s)
  {
    name = s;
  }

  std::string toString() const 
  {
    return name;
  }

private:
  std::string name;
};

class Bar
{
public:
  Bar(int i)
  {
    val = i;
  }

  std::string toString() const 
  {
    std::ostringstream stream;
    stream << val;
    return stream.str();
  }

private:
  int val;
};

int main(int, char**)
{
  Foo foo("hey");
  Bar bar(2);

  std::cout << foo << std::endl;
  std::cout << bar << std::endl;
  return 0;
}

现在这也行不通了。

我只是想避免使用上面的模板一遍又一遍地重载 operator<< 。这似乎应该是可能的。我想知道是否是,如果是,如何?

在这种情况下,重载 Foo 和 Bar 来做同样的事情将是一种浪费,这就是我试图避免它的原因。

编辑:2 好吧,看来我被误解了。这是另一种澄清的尝试:

template <typename T>
std::ostream& operator<<(ostream& stream, const T& t)
{
  for(typename T::const_iterator i = t.begin(), end = t.end(); i != end; ++i)
  {
    stream << *i;
  }
  return stream;
}

int main(int, char**) 
{
  set<int> foo;
  list<string> bar;
  vector<double> baz;

  cout << foo << " " bar << " " << baz << endl;
};

请注意,上面的代码不起作用。提示模棱两可。但它似乎是打印容器的更好解决方案。如果我通过重载来做到这一点,我将需要为每个容器/数据类型组合编写一个 operator<< 版本,这会产生大量可笑的代码重复。

最佳答案

这不需要是模板函数。

std::ostream & operator<<(std::ostream & stream, const std::map<std::string, std::string> & some_map)
{
    return stream;
}

编辑:

引用我关于用 C++ 编写 Java 的评论(如果这听起来很粗鲁,我很抱歉,我无意变得狡猾)。告诉我这是否对你更有效。与其首先编写“toString”方法,不如重载 operator<< 开始。功能几乎相同。然后,您可以编写一个非成员模板 toString 函数,它将自动处理您的所有类,如下所示:

#include <sstream>
#include <string>

template<typename T>
std::string toString(const T & val)
{
    std::ostringstream ostr;
    ostr << val;
    return ostr.str();
}

编辑2

如果您仍然坚持按自己的方式行事,这是我的替代方案。使所有使用 toString 方法的类继承自具有虚拟 toString 方法的抽象类,然后编写一个运算符 << 来处理所有这些类。

class Stringifiable
{
public:
    virtual std::string toString() const = 0;
};

std::ostream & operator<<(std::ostream & ostr, const Stringifiable& something)
{
    return ostr << something.toString();
}

现在编译器将选择您的重载而不是模板。

关于c++ - 如何为 ostream 的 operator<< 模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4038232/

相关文章:

c++ - 程序仅打印 C++ 数组中的前三个字符

c++ - 将 3 个变量值插入到 multimap 中

python - 从模板进行查询

c++ - 使用模板定义 bitset 的大小

c++ - 动态检查使用可变参数继承的类的类型的最佳方法是什么?

c++ - std::priority_queue 的模板参数是什么?

c++ - 制作一个简单的 CLI C++ 程序所需的知识,该程序可以找到歌曲的歌词并将其显示给用户

c++ - 延迟输出 0

c++ - 为什么来自模板化基类的方法不可见?

c++ - 如何确保作为模板参数传递的函数类型不修改参数?