18

It makes sense to implement << for QString like:

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

instead of writing

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

every time in the code.

However, since it is not in standard Qt library, I'm assuming there is any particular reason not to do so. What are the risks/inconvenience of overloading << as specified above?

Ilya Kobelevskiy
  • 5,245
  • 4
  • 24
  • 41
  • 1
    I don't see why it makes sense to use str.toAscii() instead of toLatin1() or toUtf8() or toLocal8Bit() ? – fjardon Apr 29 '13 at 14:35
  • @fjardon - there is no particular reason :) Any of the ones you mentioned I think would work to. – Ilya Kobelevskiy Apr 29 '13 at 14:38
  • 1
    They do very different things outside of 7-bit clean strings. – Yakk - Adam Nevraumont Apr 29 '13 at 14:39
  • 1
    I believe the reason it's not in Qt is that Qt is pretty much trying to replace the entire standard library with itself. Not that I like this philosophy of theirs, but they seem keen on it. – Angew is no longer proud of SO Apr 29 '13 at 14:40
  • @Yakk, do you mean << would be not cross-platform, so it is not in standard Qt library? I wonder, is it not possible to implement << for the cases you mention? Say std::string has <<... – Ilya Kobelevskiy Apr 29 '13 at 14:41
  • `std::basic_ostream` sounds like a better thing to overload. Then toss some traits classes to figure out how to get the right bit-width of `char*` from your `QString`. – Yakk - Adam Nevraumont Apr 29 '13 at 14:42
  • 1
    @Ilya I mean: there can be only a single operator << for QString and ostream. And there is no reason to restrict the library users to only one implementation. So it should not be included in the library but let to each user initiative to write this operator. – fjardon Apr 29 '13 at 14:42
  • @IlyaKobelevskiy no, I mean that `toAscii` and `toLatin1` or `toUtf8` or `toLocal8Bit` do very different things outside of a '7 bit clean' character string (a character string where only the lowest 7 bits are ever used) (and sometimes do different things even on 7 bit clean strings). – Yakk - Adam Nevraumont Apr 29 '13 at 14:43
  • Another thing to consider: locale. I'd be tempted to use utf8 for narrow `basic_ostream` and utf16 for wide `basic_ostream` and do proper locale conversion from either of those to the locale of the stream. I'm not an expert on C++ standard library locale functions, however I'd start looking at [codecvt](http://en.cppreference.com/w/cpp/locale/codecvt) and [basic_streambuf::getloc](http://en.cppreference.com/w/cpp/io/basic_streambuf/getloc) and research from there. – Yakk - Adam Nevraumont Apr 29 '13 at 14:50
  • Note that you can also use qPrintable(str). Saves some typing. – Frank Osterfeld Apr 29 '13 at 14:52

4 Answers4

13

If the << operator is included in the Qt library every client of the library will have to use the exact same implementation. But due to the nature of QString it is far from obvious this is what these clients want. Some people writing software interacting with legacy file in western europe may want to use Latin1() characters, US people may go with Ascii() and more modern software may want to use Utf8().

Having a single implementation in the library would restrict unacceptably what can be done with the whole library.

fjardon
  • 7,921
  • 22
  • 31
  • Thanks, I guess that makes sense - I take it as it is not the width of the bit that can't be figured out, but same bit width can be treated differently depending on the underlying text that QString represent. However, it is safe to provide own implementation for << knowing what character encoding maps to, right? – Ilya Kobelevskiy Apr 29 '13 at 15:06
  • Yes, if you know you will only deal with Ascii you can create your own operator. – fjardon Apr 29 '13 at 16:25
12

It's not necessary to implement such thing, as long as there exists a convenient solution like this one, involving QTextStream

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

QTextStream is quite powerfull...

maydin
  • 195
  • 1
  • 3
  • 15
BlueAutumn
  • 169
  • 1
  • 7
4

The accepted answer points out some valid reasons for why there is no operator<< function for QString.

One can easily overcome those reasons by providing some convenience functions and maintaining some state in an application specific 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;
}

Output:

test-string
test-string
test-string
Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

I don't think there is any particular reason for excluding (nor including) this in the Qt library. Only problem that could possibly appear here is a possibility that std::ostream object could modify the contents of the parameter passed to std::ostream::operator<< function.

However, in the reference it is clearly stated that this function will modify the parameter if string buffer is passed - there is nothing about the other types, so I guess (and the common-sense is telling me) that operator<< will not modify char* parameter. Also, on this page there is nothing about modifying the passed object.

Last thing: instead of using QString::toAscii().constData(), you could use QString::toStdString() or qPrintable(const QString&) macro.

Nemanja Boric
  • 21,627
  • 6
  • 67
  • 91