[Development] Improving toInt, toLong, etc.

Thiago Macieira thiago.macieira at intel.com
Tue Feb 4 01:26:21 CET 2014


Em seg 03 fev 2014, às 15:29:06, Matthew Woehlke escreveu:
> Replying privately as this seems to have gotten off-topic for
> std-proposals; maybe it should be moved to a Qt forum? (Feel free to
> re-add list(s) as you feel appropriate.)

Sure. Adding Qt's dev list. I've begun the work, starting with making a 
template version of those functions. See:

https://codereview.qt-project.org/77277

> On 2014-02-03 14:53, Thiago Macieira wrote:
> If I were designing such an API from scratch, I'd probably these days go
> with something like the std::expected approach. Bonus points for
> implicitly converting to the value type.
> 
> Then you could write e.g.:
> 
> auto const result = s.toInt(); // Other params (e.g. base) elided
> if (result.isOkay())
>    use(result.value()); // '.value()' optional
> 
> - or -
> 
> // Can use value directly, as before
> use(s.toInt());
> 
> - or -
> 
> // Use default value on error
> use(s.toInt().value(default));

Sounds good, but should I then create a QExpected class? And how should I make 
it differ from QOptional?

Note that I will need to add QOptional because kdbus has "maybe types" and 
we'll need to differentiate. I could make it QDBusOptional, but I'd rather make 
it for all of Qt.

Since we won't have exceptions in our QOptional, I don't think we need two 
classes. One would suffice. And then we can add it to our containers too, but 
probably only for Qt 6 due to BIC issues (QVector on MSVC).

> Thus, if you don't care about the status, you can silently ignore it and
> use the returned result directly, as before. If you do care, it would be
> unusual to have used the value directly, so there was already a line
> assigning the result to a local, which could and still can be used
> directly, but now the local also holds the status.
> 
> 
> Consideration points:
> 
> - Should toInt() also take a default value?

Either it takes a default value or it returns a QOptional. Not both.

> - operator bool could be ambiguous for toBool (though I think Qt doesn't
> have this (currently)?), so I went with an explicit isOkay() to test the
> result. Should there be an operator bool -> isOkay() for toX, x != Bool?

We don't have toBool(). We'd probably name isOkay() instead isValid(). We 
should probably also adopt std::optional names and add an isEngaged().

> Do we need that for e.g. 'if (auto const result = s.toInt())'?
> Alternatively, the implicit conversion could be omitted and require the
> user to use .value().

In the above, result is a QOptional<int>. The question is what use you make of 
it.

> As an added benefit, isOkay() could take parameters or have alternate,
> similar methods (isComplete()?) to clarify what "okay" means (e.g. did
> it consume the entire input?). However it may be better to specify that
> as an input parameter. (Unrelated: it's sure nice in this context to
> have a flags class :-)...)

That makes it too complex for QOptional or QExpected. Instead, toIntegral() 
should have extra parameters.

The task I have is to add the endposition output parameter. If that pointer is 
non-null, it will indicate the position (index) of where the conversion ended, 
so you can resume the parsing. If it is null, we fall back to the current 
behaviour: fail if endposition != length().

That means the front-end function would be:

 template <typename T> QOptional<T> toIntegral(int base = 10, int *endpos = 0)
 // plus the enableif integral type

> > I was planning on doing some work on those functions this week anyway
> > (actually, I had planned for last week). They're missing the ability to
> > parse a number with more text at the end and return the end pointer.
> 
> In the above, if the return type is specific to the conversion, the end
> pointer could be an additional member of the return type, e.g. 'int
> end() const'. (For QString input, I don't think you would return a
> pointer? But maybe I am wrong, and anyway the return obviously can be
> whatever is most appropriate.)
> 
> Or, of course, you can add it as another pointer to out param :-).

As I said above, that is the plan because it changes the parsing itself. 
endpos == NULL implies that the parsing must consume the entire string, which 
is the current behaviour.

-- 
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



More information about the Development mailing list