[Development] New feature to qstring | QString::toBool()

1,217 views
Skip to first unread message

Antonis Tsiapaliokas

unread,
Oct 25, 2011, 8:19:29 PM10/25/11
to devel...@qt-project.org
Hello

I have found this feature request to bugzilla, https://bugreports.qt.nokia.com/browse/QTBUG-21384 , and i have create a patch for this http://codereview.qt-project.org/#change,7394 . Since a qstring has the toDouble, toint, toDouble, toFload etc, i think that it could be great to add this feature to qstring. Also, please read the comment from the John Brooks, which i think that he is right. So what do you think? Is there any way to add this feature or it will to hackish? (if we assume that we want to support for all the ways that a string can represent a bool...)

Regards
Antonis Tsiapaliokas

Frans Klaver

unread,
Oct 25, 2011, 8:53:02 PM10/25/11
to devel...@qt-project.org, Antonis Tsiapaliokas
Hi,

On Tue, 25 Oct 2011 22:19:29 +0200, Antonis Tsiapaliokas
<kok...@gmail.com> wrote:

> Also, please read the comment from the John Brooks, which i think that

> he isright. So what do you think?

I would say he is right. He strongly hints at the possibility that bool is
too context dependent. And I agree with that.

This thing is tricky to tackle. QString was created to easily handle
localization. Chances are you are going to not only interpret true/false,
but also ja/(nee|nein|nej), oui/non, si/no and whatever may mean true or
yes (or OK?) in whatever language. What if a language introduces a new
word to mean true? You just don't have to handle natural language issues
with doubles, floats and integers, which is why that can be done by
QString hands down.

I think deciding on the meaning of a string is one of the things better
left to its user. Outside the string you know exactly what you expect. A
number, a word, what language the word is going to be in, which words are
going to mean 'true', which are 'false' and which should produce an error.

bool yes = (str.toInt() != 0);
bool yes = (str.compare(tr("true"), Qt::CaseInsensitive) == 0);
bool yes = (str.compare("true", Qt::CaseInsensitive) == 0);
bool yes = QVariant(str).toBool(); // tricky but might work

Based on the fact that you need a lot of information to correctly
interpret the string into a boolean value, I would say this can't really
cover a lot of common cases without being a hackish blob of code. It is
probably better to not include this in QString.

Cheers,
Frans
_______________________________________________
Development mailing list
Devel...@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development

Thiago Macieira

unread,
Oct 25, 2011, 9:01:43 PM10/25/11
to devel...@qt-project.org

QVariant has toBool just like it has toDouble and toInt, so I think it makes
sense to have it in QString and in QByteArray.

So I recommend:

1) document very well what is true and what isn't

2) make sure all three classes work the same way. If not, change them so that
they all have toBool() const and they all operate equally.

3) add unit tests

4) ensure that QVariant::toBool calls into QString::toBool and
QByteArray::toBool, as applicable. Note pending the commits by Jędrzej that
are refactoring the QVariant internals.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358

signature.asc

Frans Klaver

unread,
Oct 25, 2011, 9:33:04 PM10/25/11
to devel...@qt-project.org
Hi,

On Tue, 25 Oct 2011 23:01:43 +0200, Thiago Macieira <thi...@kde.org> wrote:

> QVariant has toBool just like it has toDouble and toInt, so I think it
> makes sense to have it in QString and in QByteArray.

It makes sense from an equal-API point of view. On the other hand,
QVariant has a significantly different task than QString does -- QString
is, AFAIK, not a union replacement like QVariant is. Does it make sense to
add QString::toBool() from a basic task perspective?


> 1) document very well what is true and what isn't

Restricting the use to e.g. English only, would not be really useful when
parsing (localized) user input, although I don't think this would happen a
lot. I only know of a few cases where an end-user is expected to
explicitly type yes or no into an input field, and those are command line
tools. Wouldn't that be pretty much the only use case?

I might have overlooked things. It's getting late anyway.


> 2) make sure all three classes work the same way. If not, change them so
> that they all have toBool() const and they all operate equally.
>
> 3) add unit tests
>
> 4) ensure that QVariant::toBool calls into QString::toBool and
> QByteArray::toBool, as applicable. Note pending the commits by Jędrzej
> that are refactoring the QVariant internals.

If QString::toBool() is added, would there also be a need for something
like static QString::boolean(bool value, char format = 't')?

Thiago Macieira

unread,
Oct 26, 2011, 6:10:02 AM10/26/11
to devel...@qt-project.org
On Tuesday, 25 de October de 2011 23.33.04, Frans Klaver wrote:
> > 1) document very well what is true and what isn't
>
> Restricting the use to e.g. English only, would not be really useful when
> parsing (localized) user input, although I don't think this would happen a
> lot. I only know of a few cases where an end-user is expected to
> explicitly type yes or no into an input field, and those are command line
> tools. Wouldn't that be pretty much the only use case?
>
> I might have overlooked things. It's getting late anyway.

I agree with your argument, I just don't think it's applicable. QString is not
localised and has never promised to be. QString::number generates C-locale
numbers and toInt/toDouble parse C-locale; QDate::toString generates C-locale
dates (or should), etc. If you want localised information, you should use
QLocale.

> > 2) make sure all three classes work the same way. If not, change them so
> > that they all have toBool() const and they all operate equally.
> >
> > 3) add unit tests
> >
> > 4) ensure that QVariant::toBool calls into QString::toBool and
> > QByteArray::toBool, as applicable. Note pending the commits by Jędrzej
> > that are refactoring the QVariant internals.
>
> If QString::toBool() is added, would there also be a need for something
> like static QString::boolean(bool value, char format = 't')?

It's much easier to use the ternary operator and just select which option you
want to use.

signature.asc

jan-arve...@nokia.com

unread,
Oct 26, 2011, 6:31:37 AM10/26/11
to thi...@kde.org, devel...@qt-project.org
ext Thiago Macieira wrote on 2011-10-26:

> On Tuesday, 25 de October de 2011 23.33.04, Frans Klaver wrote:
>>> 1) document very well what is true and what isn't
>>
>> Restricting the use to e.g. English only, would not be really useful
>> when parsing (localized) user input, although I don't think this
>> would happen a lot. I only know of a few cases where an end-user is
>> expected to explicitly type yes or no into an input field, and those
>> are command line tools. Wouldn't that be pretty much the only use case?
>>
>> I might have overlooked things. It's getting late anyway.
>
> I agree with your argument, I just don't think it's applicable.
> QString is not localised and has never promised to be. QString::number
> generates C-locale numbers and toInt/toDouble parse C-locale;
> QDate::toString generates C-locale dates (or should), etc. If you want
> localised information, you should use QLocale.
>
>>> 2) make sure all three classes work the same way. If not, change
>>> them so that they all have toBool() const and they all operate equally.
>>>
>>> 3) add unit tests
>>>
>>> 4) ensure that QVariant::toBool calls into QString::toBool and
>>> QByteArray::toBool, as applicable. Note pending the commits by
>>> Jędrzej that are refactoring the QVariant internals.
>>
>> If QString::toBool() is added, would there also be a need for
>> something like static QString::boolean(bool value, char format = 't')?
>
> It's much easier to use the ternary operator and just select which
> option you want to use.
>
I think the same argumentation (there is another, simple way) can be used for debating whether we should add QString::toBool().

I think I'm opposed to adding these functions, just because I don't see how they add value:

Consider this code:

bool parseOk;
if (str.toBool(&parseOk)) {
if (parseOk)
enableSuperFastRenderer();
}

then this:

if (str == QLatin1String("true")) {
enableSuperFastRenderer();
}

which would you prefer?


regards,
Jan-Arve

Frans Klaver

unread,
Oct 26, 2011, 6:39:31 AM10/26/11
to devel...@qt-project.org
On Wed, Oct 26, 2011 at 8:31 AM, <jan-arve...@nokia.com> wrote:

> Consider this code:
>
> bool parseOk;
> if (str.toBool(&parseOk)) {
>    if (parseOk)
>        enableSuperFastRenderer();
> }

I think that in most, if not all cases, the parseOk argument would or
even should be omitted (just like with QVariant):

if (str.toBool()) {
enableSuperFastRenderer();
}

because the results will be exactly the same as your example.

> then this:
>
> if (str == QLatin1String("true")) {
>    enableSuperFastRenderer();
> }
>
> which would you prefer?

I ask you the same question.

Cheers,
Frans

Frans Klaver

unread,
Oct 26, 2011, 6:51:46 AM10/26/11
to devel...@qt-project.org
On Wed, Oct 26, 2011 at 8:10 AM, Thiago Macieira <thi...@kde.org> wrote:

> I agree with your argument, I just don't think it's applicable. QString is not
> localised and has never promised to be. QString::number generates C-locale
> numbers and toInt/toDouble parse C-locale; QDate::toString generates C-locale
> dates (or should), etc. If you want localised information, you should use
> QLocale.

Given that information and assuming that the results match QVariant,
I don't see any reason not to include QString::toBool(). The
assumption will obviously always be valid if QVariant uses
QString::toBool() for parsing.


>> If QString::toBool() is added, would there also be a need for something
>> like static QString::boolean(bool value, char format = 't')?
>
> It's much easier to use the ternary operator and just select which option you
> want to use.

Consider:

bool b = true;

QString str1 = b?"treu":"false";
if (str1.toBool()) {
// we never get here...
}

QString str2 = QString::boolean(b);
if (str2.toBool()) {
// we will get here
}

This example might be a bit far-fetched and I do agree that the
advantage, if any, would be fairly small. QString::boolean() would
always produce a value that is guaranteed to be correctly parsed by
QString::toBool(). The ternery operator not so much. Also the user
doesn't have to explicitly know about which values evaluate to true in
QString::toBool() to enter the correct value; from an API perspective
I think it would make sense to enable a black-box round-trip.

jan-arve...@nokia.com

unread,
Oct 26, 2011, 7:15:59 AM10/26/11
to frans...@gmail.com, devel...@qt-project.org
ext Frans Klaver wrote on 2011-10-26:

> On Wed, Oct 26, 2011 at 8:31 AM, <jan-arve...@nokia.com> wrote:
>
>> Consider this code:
>>
>> bool parseOk;
>> if (str.toBool(&parseOk)) {
>>    if (parseOk)
>>        enableSuperFastRenderer();
>> }
>
> I think that in most, if not all cases, the parseOk argument would or
> even should be omitted (just like with QVariant):
>
> if (str.toBool()) {
> enableSuperFastRenderer();
> }
>
> because the results will be exactly the same as your example.
>
>> then this:
>>
>> if (str == QLatin1String("true")) {
>>    enableSuperFastRenderer();
>> }
>>
>> which would you prefer?
>
> I ask you the same question.
>
Ok, so toBool() will return false if it fails.

Then you would need the not-so-nice code for checking for false:

bool parseOk;
if (!str.toBool(&parseOk)) {
if (parseOk)
disableSuperFastRenderer();
}


regards,
Jan-Arve

Andre Somers

unread,
Oct 26, 2011, 7:21:41 AM10/26/11
to devel...@qt-project.org
Op 26-10-2011 8:39, Frans Klaver schreef:

> On Wed, Oct 26, 2011 at 8:31 AM,<jan-arve...@nokia.com> wrote:
>
>> Consider this code:
>>
>> bool parseOk;
>> if (str.toBool(&parseOk)) {
>> if (parseOk)
>> enableSuperFastRenderer();
>> }
> I think that in most, if not all cases, the parseOk argument would or
> even should be omitted (just like with QVariant):
>
> if (str.toBool()) {
> enableSuperFastRenderer();
> }
>
> because the results will be exactly the same as your example.
>
>> then this:
>>
>> if (str == QLatin1String("true")) {
>> enableSuperFastRenderer();
>> }
>>
>> which would you prefer?
> I ask you the same question.
IMHO, there is a big difference between a string that correctly converts
to false, and one that can not be converted to a boolean. Do you really
wish to make that difference invisible? That would not only break
symetry with QString::toInt, it would lead to an IMHO useless method.

I agree with Jan Arve on this topic. You need to have verification that
a conversion succeeded.

André

Frans Klaver

unread,
Oct 26, 2011, 8:02:36 AM10/26/11
to devel...@qt-project.org
On Wed, Oct 26, 2011 at 9:21 AM, Andre Somers <an...@familiesomers.nl> wrote:

> IMHO, there is a big difference between a string that correctly converts
> to false, and one that can not be converted to a boolean. Do you really
> wish to make that difference invisible?

Certainly not.

> I agree with Jan Arve on this topic. You need to have verification that
> a conversion succeeded.

I do agree that you need to have the verification available, however,
I daresay in a lot of cases the need for it is not that big. I at
least don't care if or why a boolean conversion fails in a lot of
cases (with QVariant currently).

Then there's readability for slightly more complex situations.
Assuming that QString::toBool() acts like QVariant::toBool() and
returns true if the contents are "1", "true", or "y", false otherwise,
consider the following:

bool ok;
bool result = str.toBool(&ok);
if (ok) {
if (result)
enableSuperFastRenderer();
else
disableSuperFastRenderer();
} else {
doSomethingSmart();
}

against

if (str.compare("true", Qt::CaseInsensitive) == 0
|| str.compare("y", Qt::CaseInsensitive) == 0
|| str == "1" ) {
enableSuperFastRenderer();
} else if (str.compare("false", Qt::CaseInsensitive) == 0
|| str.compare("n", Qt::CaseInsensitive) == 0
|| str == "0") {
disableSuperFastRenderer();
} else {
doSomethingSmart();
}

If I had the choice, I'd take the first option over the second.

And honestly, what are the odds someone instead would write:

if (str == QLatin1String("true")) {
enableSuperFastRenderer();

} else {
disableSuperFastRenderer();
}

What would you do if you couldn't parse string. Make the assumption
you can, and enable the super fast renderer?

All at the risk of playing the devil's advocate, of course.

Cheers,
Frans

Thiago Macieira

unread,
Oct 26, 2011, 9:18:10 AM10/26/11
to devel...@qt-project.org
On Wednesday, 26 de October de 2011 07.15.59, jan-arve...@nokia.com
wrote:

> bool parseOk;
> if (!str.toBool(&parseOk)) {
> if (parseOk)
> disableSuperFastRenderer();
> }

bool parseOk
if (!str.toBool(&parseOk) && parseOk)
disableSuperFastRenderer();

Or you can accept that, if the user types crap instead of "false", it's false.

signature.asc

Andre Somers

unread,
Oct 26, 2011, 10:50:19 AM10/26/11
to devel...@qt-project.org
Op 26-10-2011 10:02, Frans Klaver schreef:

> On Wed, Oct 26, 2011 at 9:21 AM, Andre Somers<an...@familiesomers.nl> wrote:
>
>> IMHO, there is a big difference between a string that correctly converts
>> to false, and one that can not be converted to a boolean. Do you really
>> wish to make that difference invisible?
> Certainly not.
>
>> I agree with Jan Arve on this topic. You need to have verification that
>> a conversion succeeded.
> I do agree that you need to have the verification available, however,
> I daresay in a lot of cases the need for it is not that big. I at
> least don't care if or why a boolean conversion fails in a lot of
> cases (with QVariant currently).
OK, you might be right about that.

>
> Then there's readability for slightly more complex situations.
> Assuming that QString::toBool() acts like QVariant::toBool() and
> returns true if the contents are "1", "true", or "y", false otherwise,
> consider the following:
>
> bool ok;
> bool result = str.toBool(&ok);
> if (ok) {
> if (result)
> enableSuperFastRenderer();
> else
> disableSuperFastRenderer();
> } else {
> doSomethingSmart();
> }
Note that the verification flag would be optional anyway. If you return
false if ok is false, then you can easily choose if you need
verification or not. It just needs to be clearly documented. However, if
you think that it would be good for readability, wouldn't it then make
sense to have a way to do this in a localized way as well? The various
true & false strings could conceivably be in QLocale? Otherwise, you
still end up in the same situation if your application needs
localization (and most do, I think).

>
> What would you do if you couldn't parse string. Make the assumption
> you can, and enable the super fast renderer?

I *might* want to bail out and warn the user, but it depends on the
situation, of course.

André

Frans Klaver

unread,
Oct 26, 2011, 11:01:52 AM10/26/11
to devel...@qt-project.org
On Wed, Oct 26, 2011 at 12:50 PM, Andre Somers <an...@familiesomers.nl> wrote:

> Note that the verification flag would be optional anyway. If you return
> false if ok is false, then you can easily choose if you need
> verification or not. It just needs to be clearly documented.

As always.

> However, if
> you think that it would be good for readability, wouldn't it then make
> sense to have a way to do this in a localized way as well? The various
> true & false strings could conceivably be in QLocale? Otherwise, you
> still end up in the same situation if your application needs
> localization (and most do, I think).

The localized way should be done the same way as one would handle
localized numbers (like properly handling 1,234.56 and 1.234,56).


>> What would you do if you couldn't parse string. Make the assumption
>> you can, and enable the super fast renderer?
> I *might* want to bail out and warn the user, but it depends on the
> situation, of course.

Of course. I would think however that in these cases you shouldn't
really be explicitly relying on QString::toBool(), but that is a
completely different discussion altogether.

Giuseppe D'Angelo

unread,
Oct 26, 2011, 6:44:09 PM10/26/11
to Antonis Tsiapaliokas, devel...@qt-project.org
2011/10/25 Antonis Tsiapaliokas <kok...@gmail.com>:

> So what do you think? Is there any way to add this feature or it will to
> hackish? (if we assume that we want to support for all the ways that a
> string can represent a bool...)

I think we should then really discuss about what should be considered
to be "true" (and what to be "false", so we also figure out if a "bool
*ok" parameter is actually needed or not). In my humble opinion, a
case insensitive comparison against the string "true" is too generic
and weak (not to mention English-only). If that's a way of checking
some user input I think it's simply a bad idea to have it inside
QString.

For instance, Perl thinks that empty string and the literal "0" are
false, and any other string is true. In Python and JS only the empty
strings are false. Should Qt do something similar?

--
Giuseppe D'Angelo

Christoph Feck

unread,
Oct 26, 2011, 9:27:13 PM10/26/11
to devel...@qt-project.org
On Tuesday 25 October 2011 22:53:02 Frans Klaver wrote:
> Hi,
>
> On Tue, 25 Oct 2011 22:19:29 +0200, Antonis Tsiapaliokas
>
> <kok...@gmail.com> wrote:
> > Also, please read the comment from the John Brooks, which i think
> > that he isright. So what do you think?
>
> I would say he is right. He strongly hints at the possibility that
> bool is too context dependent. And I agree with that.
>
> This thing is tricky to tackle. QString was created to easily
> handle localization. Chances are you are going to not only
> interpret true/false, but also ja/(nee|nein|nej), oui/non, si/no
> and whatever may mean true or yes (or OK?) in whatever language.
> What if a language introduces a new word to mean true? You just
> don't have to handle natural language issues with doubles, floats
> and integers, which is why that can be done by QString hands down.

As far as I remember, POSIX locales offer strings or regexps for YES
and NO, so it might be possible to add something to QLocale to access
those strings.

--
Christoph Feck
http://kdepepo.wordpress.com/
KDE Quality Team

Andreas Aardal Hanssen

unread,
Oct 27, 2011, 6:13:25 PM10/27/11
to devel...@qt-project.org
2011/10/26 Christoph Feck <chri...@maxiom.de>

> As far as I remember, POSIX locales offer strings or regexps for YES
> and NO, so it might be possible to add something to QLocale to access
> those strings.

By auto-converting a QString to a bool we'll be adding ambiguity to Qt
APIs. If there's no intuitive way to convert a QString to a boolean,
then QString IMO should not provide that as a function... I find it
especially disturbing that translatability and locale is considered.
Literal interpretation of a string needs to be completely unambiguous,
just like QString("123").toInt() is.

If we add QString::toBool(), I think we are adding future bugs to
applications that make use of this function. We'll find code that
calls toBool() on all kinds of strings with hard-to-read outcomes.

QString(QChar::Null).toBool()
QString("0").toBool()
QString("null").toBool()
QString("nil").toBool()
QString().toBool()
QString("false").toBool()
QString("no").toBool()
QString("not").toBool()
QString("!").toBool()
QString("negative").toBool()

Do any of these examples have any _intuitive_, unambiguous return values?

I vote -1 on this feature. Just write:

if (value == "true")
{
}

or

if (value.compare("true", Qt::CaseInsensitive) == 0)
{
}

or write a grammar and a proper parser :-).

--
Andreas Aardal Hanssen

Andre Somers

unread,
Oct 27, 2011, 7:25:28 PM10/27/11
to devel...@qt-project.org
Op 27-10-2011 20:13, Andreas Aardal Hanssen schreef:

> 2011/10/26 Christoph Feck<chri...@maxiom.de>
>> As far as I remember, POSIX locales offer strings or regexps for YES
>> and NO, so it might be possible to add something to QLocale to access
>> those strings.
> By auto-converting a QString to a bool we'll be adding ambiguity to Qt
> APIs. If there's no intuitive way to convert a QString to a boolean,
> then QString IMO should not provide that as a function... I find it
> especially disturbing that translatability and locale is considered.
> Literal interpretation of a string needs to be completely unambiguous,
> just like QString("123").toInt() is.
QString("1,234").toDouble() also isn't all that clear either, only the
QLocale version of those is localized.
With a US locale, that would result in 1234.0 (more than a thousand),
while in the Netherlands, it would be 1.234 (one and a bit).

*If* QString::toBool is introduced, there needs to be a properly
localized or at least localizable version in QLocale as well, I think.

André

Thiago Macieira

unread,
Oct 27, 2011, 8:19:51 PM10/27/11
to devel...@qt-project.org
On Thursday, 27 de October de 2011 21:25:28 Andre Somers wrote:
> QString("1,234").toDouble() also isn't all that clear either, only the
> QLocale version of those is localized.
> With a US locale, that would result in 1234.0 (more than a thousand),
> while in the Netherlands, it would be 1.234 (one and a bit).

Right: that needs to be fixed: QString should operate ONLY on the C locale. If
you need anything with other locales, it should be clearly marked (like "%L1"
in arg()) or you should use QLocale.

The same goes for QDate and QTime. Does anyone volunteer to do this change?

>
> If QString::toBool is introduced, there needs to be a properly

> localized or at least localizable version in QLocale as well, I think.
>
> André

signature.asc
Reply all
Reply to author
Forward
0 new messages