QString的运算符<<

18

像QString这样的类,实现<<运算符是有意义的。

std::ostream&  operator <<(std::ostream &stream,const QString &str)
{
   stream << str.toAscii().constData(); //or: stream << str.toStdString(); //??
   return stream;
}

不是写作

stream << str.toAscii().constData();

在代码中每次都使用它。

然而,由于它不在标准的Qt库中,我假设有任何特定原因不这样做。重载 << 操作符会有什么风险/不便之处?


1
我不明白为什么要使用str.toAscii()而不是toLatin1()、toUtf8()或toLocal8Bit()? - fjardon
1
他们在7位清洁字符串之外做着非常不同的事情。 - Yakk - Adam Nevraumont
1
我认为它不在Qt中的原因是,Qt几乎试图用自己来替换整个标准库。虽然我不喜欢他们的这种理念,但他们似乎很热衷于此。 - Angew is no longer proud of SO
1
@Ilya 我的意思是:QString 和 ostream 只有一个 << 运算符。而且没有理由限制库用户只能使用一种实现方式。因此,它不应该被包含在库中,而是应该让每个用户自主编写这个运算符。 - fjardon
另一个需要考虑的问题是:本地化。我倾向于在窄basic_ostream中使用utf8,在宽basic_ostream中使用utf16,并从这两者之一正确转换为流的本地化。我不是C++标准库本地化函数的专家,但我会开始查看codecvtbasic_streambuf::getloc,然后进行研究。 - Yakk - Adam Nevraumont
显示剩余5条评论
4个回答

13
如果Qt库中包含了<<操作符,那么库的每个客户端都必须使用完全相同的实现。但由于QString的性质,很难确定这是否是这些客户端想要的。一些与西欧传统文件交互的软件可能希望使用Latin1()字符,美国人可能会使用Ascii(),而更现代的软件可能希望使用Utf8()。
在库中有一个单一的实现将不可接受地限制了整个库所能做的事情。

谢谢,我想这很有道理——我认为不能确定位宽度,但是相同的位宽度可以根据QString表示的底层文本而被不同地处理。然而,只要知道字符编码映射,提供自己的<<实现是安全的,对吗? - Ilya Kobelevskiy
是的,如果您知道只会处理Ascii,您可以创建自己的运算符。 - fjardon

12

只要存在像QTextStream这样方便的解决方案,就不需要实现这样的东西。

QString s;
QTextStream out(&s);
out << "Text 1";
out << "Text 2";
out << "And so on....";

QTextStream 非常强大...


3
除非你必须使用 std::ostream 接口,否则不需要。 - boycy
1
提供的源代码有一些问题。在执行“QTextStream out(&s);”之后,您可以使用out << "Text1"而不是s << "Text1"。 - Gustavo Rodríguez

4

被接受的答案指出了为什么QString没有operator<<函数的一些有效原因。

可以通过在应用程序特定的namespace中提供一些方便的函数并保持一些状态来轻松地克服这些原因。

#include <iostream>
#include <QString>

namespace MyApp
{
   typedef char const* (*QStringInsertFunction)(QString const& s);

   char const* use_toAscii(QString const& s)
   {
      return s.toAscii().constData();
   }

   char const* use_toUtf8(QString const& s)
   {
      return s.toUtf8().constData();
   }

   char const* use_toLatin1(QString const& s)
   {
      return s.toLatin1().constData();
   }

   // Default function to use to insert a QString.
   QStringInsertFunction insertFunction = use_toAscii;

   std::ostream& operator<<(std::ostream& out, QStringInsertFunction fun)
   {
      insertFunction = fun;
      return out;
   }

   std::ostream& operator<<(std::ostream& out, QString const& s)
   {
      return out << insertFunction(s);
   }
};

int main()
{
   using namespace MyApp;

   QString testQ("test-string");

   std::cout << use_toAscii << testQ << std::endl;
   std::cout << use_toUtf8 << testQ << std::endl;
   std::cout << use_toLatin1 << testQ << std::endl;

   return 0;
}

输出:

test-string
test-string
test-string

1
我认为在Qt库中既没有特别的排除(也没有包含)这个问题。唯一可能出现的问题是std::ostream对象可能会修改传递给std::ostream::operator<<函数的参数内容。
然而,在参考文献中明确指出,如果传递了字符串缓冲区,此函数将修改参数 - 没有关于其他类型的内容,所以我猜测(并且常识告诉我)operator<<不会修改char*参数。另外,在这个页面上也没有关于修改传递对象的任何内容。
最后一件事:您可以使用QString::toStdString()qPrintable(const QString&)宏,而不是使用QString::toAscii().constData()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接