Re: [Development] Views in APIs

2020-05-15 Thread Matthew Woehlke

On 15/05/2020 06.39, Edward Welbourne wrote:

Thiago Macieira (15 May 2020 02:30) replied

On Thursday, 14 May 2020 12:34:54 PDT Matthew Woehlke wrote:

On 14/05/2020 14.58, Thiago Macieira wrote:

Which is:
b) misspelling "iteratable"


Be that as it may, that ship has sailed:

https://www.google.com/search?q=iteratable

Even Google thinks so, and if you insist otherwise, 12k results instead
of 2M.


The majority of the results in the first and second pages are about a company
called Iterable.


...but also on those pages are references to the Java and Javascript 
concepts. Then...



It remains that "iterable" is the standard form in python's extensive
documentation and is the form I am used to.


...there's Python. Lisp seems to be the least obscure language using 
"iteratable". Even Wiktionary¹ gives "iterable" as the "correct" 
spelling, and doesn't even have an entry for "iteratable".


(¹ https://en.wiktionary.org/wiki/iterable)

I'm *not* arguing that you (Thiago) aren't, pedantically, correct. I'm 
just pointing out that, as Edward notes, you're fighting the tide.


--
Matthew
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs

2020-05-15 Thread Edward Welbourne
On 14/05/2020 14.58, Thiago Macieira wrote:
>>> Which is:
>>> b) misspelling "iteratable"

On Thursday, 14 May 2020 12:34:54 PDT Matthew Woehlke wrote:
>> Be that as it may, that ship has sailed:
>>
>>https://www.google.com/search?q=iteratable
>>
>> Even Google thinks so, and if you insist otherwise, 12k results instead
>> of 2M.

Thiago Macieira (15 May 2020 02:30) replied
> The majority of the results in the first and second pages are about a company
> called Iterable.

That'll be because a company's marketing department works hard to get
its pages at the top of Google's search results.  It remains that
"iterable" is the standard form in python's extensive documentation and
is the form I am used to.

English evolves according to the way it's mostly used, regardless of
anyone's attempts to impose rules.  Feel free to resist (that, also, is
part of the evolutionary process), but remember that you may be trying
to stop the tide.

Eddy.
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs

2020-05-14 Thread Thiago Macieira
On Thursday, 14 May 2020 12:34:54 PDT Matthew Woehlke wrote:
> On 14/05/2020 14.58, Thiago Macieira wrote:
> > Which is:
> > b) misspelling "iteratable"
> 
> Be that as it may, that ship has sailed:
> 
>https://www.google.com/search?q=iteratable
> 
> Even Google thinks so, and if you insist otherwise, 12k results instead
> of 2M.

The majority of the results in the first and second pages are about a company 
called Iterable.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel System Software Products



___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs

2020-05-14 Thread Jean-Michaël Celerier
> To have type-erased containers, we need to go back to something like
java.lang.Collection.

C++20 offers coroutines which allows the same things without java-like type
hierarchies though
(and with much more flexibility as you don't even need to have an actual
container existing somewhere - your function's stack
can serve as one just fine :p).

see e.g. https://godbolt.org/z/cEv7Gp - in simple cases it optimizes as
well as as a std::vector.

Well, for Qt 7 maybe :-)


On Thu, May 14, 2020 at 9:00 PM Thiago Macieira 
wrote:

> On Thursday, 14 May 2020 02:33:43 PDT Marc Mutz via Development wrote:
> > On 2020-05-14 02:15, Thiago Macieira wrote:
> > > On quarta-feira, 13 de maio de 2020 01:41:26 PDT Иван Комиссаров wrote:
> > >> std::span Project::productsSpan() const & { return
> > >> d->products; }
> > >> std::span Project::productsSpan() const && = delete;
> > >
> > > Now implement either or both of these functions if internally you have
> > > a
> > > QSet.
> >
> > Now implement QHash roleNames() when
> > internally you have a std::pmr::unordered_map > std::pmr::string>, with all the data allocated from one
> > std::pmr::monotonic_buffer_resource.
> >
> > This does both ways.
>
> No, it doesn't. In both you created a copy on demand.
>
> But you can only *return* said copy if the return type is an owning
> container.
> std::span and the views are not.
>
> > And: you can also have views over associated data structures, they just
> > can't have inline functions because they need to type-erase the
> > container. For an extreme example, consider QAssociativeIterable.
>
> Which is:
> a) a horrible API
> b) misspelling "iteratable"
>
> To have type-erased containers, we need to go back to something like
> java.lang.Collection.
>
> --
> Thiago Macieira - thiago.macieira (AT) intel.com
>   Software Architect - Intel System Software Products
>
>
>
> ___
> Development mailing list
> Development@qt-project.org
> https://lists.qt-project.org/listinfo/development
>
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs

2020-05-14 Thread Matthew Woehlke

On 14/05/2020 14.58, Thiago Macieira wrote:

Which is:
b) misspelling "iteratable"


Be that as it may, that ship has sailed:

  https://www.google.com/search?q=iteratable

Even Google thinks so, and if you insist otherwise, 12k results instead 
of 2M.


--
Matthew
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs (was: Re: QString and related changes for Qt 6)

2020-05-14 Thread Thiago Macieira
On Thursday, 14 May 2020 04:20:43 PDT Иван Комиссаров wrote:
> I don’t see the problem here. Ranges library operates on views only, so
> there *should be* (I am just not aware of it’s name) the type that
> corresponds to the «forward access iterator» (well, in case of QSet, that
> would be bidirectional but not random access iterator) range.
> 
> If there’s no such view, it’s quite easy to implement it - it’s simply a
> pair of iterators.

You're missing the point. I want you to implement it without changing your 
return type.

Or, in different words: choose one return type for your non-inline function 
that you can be sure to support for the next 7 years, regardless of internal 
modifications to your data store.

> The disadvantage here is that such a view doesn’t gives the same flexibility
> as std::span does. i.e. it is still not possible to replace QSet with
> std::unordered_set, so we don’t have much gain compared to returning QSet /
> const QSet &.
> 
> So, as I said, I do not see the problem. Can we always return views? Yes. Do
> they gives us benefits in every case? No.

Should we do it? Almost never.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel System Software Products



___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs

2020-05-14 Thread Thiago Macieira
On Thursday, 14 May 2020 02:33:43 PDT Marc Mutz via Development wrote:
> On 2020-05-14 02:15, Thiago Macieira wrote:
> > On quarta-feira, 13 de maio de 2020 01:41:26 PDT Иван Комиссаров wrote:
> >> std::span Project::productsSpan() const & { return
> >> d->products; }
> >> std::span Project::productsSpan() const && = delete;
> > 
> > Now implement either or both of these functions if internally you have
> > a
> > QSet.
> 
> Now implement QHash roleNames() when
> internally you have a std::pmr::unordered_map std::pmr::string>, with all the data allocated from one
> std::pmr::monotonic_buffer_resource.
> 
> This does both ways.

No, it doesn't. In both you created a copy on demand.

But you can only *return* said copy if the return type is an owning container. 
std::span and the views are not.

> And: you can also have views over associated data structures, they just
> can't have inline functions because they need to type-erase the
> container. For an extreme example, consider QAssociativeIterable.

Which is:
a) a horrible API
b) misspelling "iteratable"

To have type-erased containers, we need to go back to something like 
java.lang.Collection.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel System Software Products



___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs

2020-05-14 Thread André Pönitz
On Thu, May 14, 2020 at 11:46:29AM +0200, Marc Mutz via Development wrote:
> > Please stop with this crusade of yours to end all CoW, get rid of
> > QList, etc. It is misguided and harmful to the ecosystem at large.
> 
> You are entitled to your opinions just as I am. The difference is that I put
> time (much more than KDAB pays me for, esp. when it comes to my "crusade")
> where my mouth is.

The problem here is not what personal or company time you invest yourself.
You can spent as much of that as you wish or are allowed to.

The problem is the effort these activities cause for others, especially
for those that do not share your opinions, and are still forced to adapt
their code to your preferences.

Andre'
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs (was: Re: QString and related changes for Qt 6)

2020-05-14 Thread Иван Комиссаров
I don’t see the problem here. Ranges library operates on views only, so there 
*should be* (I am just not aware of it’s name) the type that corresponds to the 
«forward access iterator» (well, in case of QSet, that would be bidirectional 
but not random access iterator) range.

If there’s no such view, it’s quite easy to implement it - it’s simply a pair 
of iterators.

The disadvantage here is that such a view doesn’t gives the same flexibility as 
std::span does. i.e. it is still not possible to replace QSet with 
std::unordered_set, so we don’t have much gain compared to returning QSet / 
const QSet &.

So, as I said, I do not see the problem. Can we always return views? Yes. Do 
they gives us benefits in every case? No.

Ivan

> 14 мая 2020 г., в 02:15, Thiago Macieira  
> написал(а):
> 
> On quarta-feira, 13 de maio de 2020 01:41:26 PDT Иван Комиссаров wrote:
>> std::span Project::productsSpan() const & { return d->products; }
>> std::span Project::productsSpan() const && = delete;
> 
> Now implement either or both of these functions if internally you have a 
> QSet.
> 
> -- 
> Thiago Macieira - thiago.macieira (AT) intel.com
>  Software Architect - Intel System Software Products
> 
> 
> 
> ___
> Development mailing list
> Development@qt-project.org
> https://lists.qt-project.org/listinfo/development

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs

2020-05-14 Thread Marc Mutz via Development

On 2020-05-13 17:27, Matthew Woehlke wrote:

On 12/05/2020 12.59, Marc Mutz via Development wrote:
AsidE: If you think that CoW is still a thing today: no. SSO is a 
thing these days, and it seems that QString will not have it in Qt 6, 
either. NOI favours SSO, QString-everywhere cements the naïve CoW 
world of the 1990s for yet another decade.


I am really, *really* sick of this.

Okay, for "most" *strings*, you may have a point.


I thought this thread was about strings. Did I miss something?


However, CoW is
*absolutely* still a useful tool for a lot of other applications, and
will continue to be so;


*Optional* *explicit* sharing, as per shared_ptr is a thing, 
yes. But that's completely different from the broken Qt "implicit 
sharing" that we have now. Have you read the 22year-old Sutter articles? 
After having read the second, have you checked Qt's implementation for 
the pitfalls mentioned therein? Continue discussing after you did.



the combination of implicit value semantics
and "cheap" copies (an atomic increment may be relatively expensive,
but so are memory allocations, especially for large data structures)
is not going away any time soon.

Please stop with this crusade of yours to end all CoW, get rid of
QList, etc. It is misguided and harmful to the ecosystem at large.


You are entitled to your opinions just as I am. The difference is that I 
put time (much more than KDAB pays me for, esp. when it comes to my 
"crusade") where my mouth is.


Thanks,
Marc
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs

2020-05-14 Thread Marc Mutz via Development

On 2020-05-14 02:15, Thiago Macieira wrote:

On quarta-feira, 13 de maio de 2020 01:41:26 PDT Иван Комиссаров wrote:
std::span Project::productsSpan() const & { return 
d->products; }

std::span Project::productsSpan() const && = delete;


Now implement either or both of these functions if internally you have 
a

QSet.


Now implement QHash roleNames() when 
internally you have a std::pmr::unordered_mapstd::pmr::string>, with all the data allocated from one 
std::pmr::monotonic_buffer_resource.


This does both ways.

And: you can also have views over associated data structures, they just 
can't have inline functions because they need to type-erase the 
container. For an extreme example, consider QAssociativeIterable.


Thanks,
Marc
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs (was: Re: QString and related changes for Qt 6)

2020-05-13 Thread Thiago Macieira
On quarta-feira, 13 de maio de 2020 01:41:26 PDT Иван Комиссаров wrote:
> std::span Project::productsSpan() const & { return d->products; }
> std::span Project::productsSpan() const && = delete;

Now implement either or both of these functions if internally you have a 
QSet.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel System Software Products



___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs

2020-05-13 Thread Matthew Woehlke

On 13/05/2020 03.04, Lars Knoll wrote:

I don’t see a need to take a QStringView in those cases. With the
exception of some low level APIs, Qt’s APIs should be safe to use. An
overload taking a QStringView would either need to copy the data (in
which case we could just as well only offer the QString version), or
it holds an ‘unsecured’ pointer to the data, and lifetime is out of
control of the class.

The second option is something I’m only willing to accept in a very
limited number of cases, and the API naming should make it clear that
this is what’s happening.


I don't see a need for that.

An API that might retain a copy of a string should take a QString. An 
API that needs to *look at* a string, but will not *directly*¹ copy that 
data, should take a QStringView. If this isn't completely transparent to 
the user of the API, we're doing something wrong.


(¹ An API that must always make a deep copy, e.g. by storing a modified 
version of an input string, isn't making a "direct" copy.)


That said, you can run into issues if the implementation of the API changes.


You might call CoW naive, but I do believe that the fact that Qt does
use containers that own their data in most of our APIs is what makes
Qt significantly simpler and safer to use than many other APIs.


No question. On of the projects I work with uses std::shared_ptr all 
over the place, because large data structures get passed around a lot. 
One of the developers is absolutely fanatical about avoiding deep 
copies, although I personally have not seen hard data whether this is 
merited (but my suspicion is that it is).


Shared ownership is a pain point, because users have to be careful to 
make a copy (which, due to polymorphism, is already "hard") if they need 
to change data and aren't sure if anyone else is using the data. 
Unfortunately, all this was designed before I became involved, or I 
would have insisted on Qt-style CoW value-like semantics, which would 
have made the whole mess *much* safer and easier to use.


Qt did something right. Let's please not throw that away because it 
"isn't fashionable".


--
Matthew
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs

2020-05-13 Thread Matthew Woehlke

On 12/05/2020 12.59, Marc Mutz via Development wrote:
AsidE: If you think that CoW is still a thing today: no. SSO is a thing 
these days, and it seems that QString will not have it in Qt 6, either. 
NOI favours SSO, QString-everywhere cements the naïve CoW world of the 
1990s for yet another decade.


I am really, *really* sick of this.

Okay, for "most" *strings*, you may have a point. However, CoW is 
*absolutely* still a useful tool for a lot of other applications, and 
will continue to be so; the combination of implicit value semantics and 
"cheap" copies (an atomic increment may be relatively expensive, but so 
are memory allocations, especially for large data structures) is not 
going away any time soon.


Please stop with this crusade of yours to end all CoW, get rid of QList, 
etc. It is misguided and harmful to the ecosystem at large.


--
Matthew
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs

2020-05-13 Thread Marc Mutz via Development

On 2020-05-13 09:56, Philippe wrote:

On Tue, 12 May 2020 18:59:35 +0200
Marc Mutz via Development  wrote:


QString-everywhere cements the naïve CoW world of the
1990s for yet another decade.


CoW naive? Really not, this method is at the heart of many strategic
technologies.
eg.:

* virtual memory used by most of operating system
* some databases
* principle behind any immutable data structure


The keyword being 'immutable'. QString is not immutable.

I'm all for going more immer-style, but you can't possibly claim that's 
what's happening in Qt 6. Immer is modern, the crude CoW implementations 
used in Qt (incl. 6) _are_ naïve.

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs

2020-05-13 Thread Ville Voutilainen
On Wed, 13 May 2020 at 12:46, Marc Mutz via Development
 wrote:
> In the not so hypothetical case that Qt is used to visualize results of
> some business calculations, chances are that thrid-party libraries will
> use std::string or std::u16string, and not QString, requiring the use of
> QString::fromStdString() to pass these to a QString API. Had the API
> taken QStringView, no extra code would have been necessary.

Wait, what? How can QStringView view a std::string?
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs

2020-05-13 Thread Marc Mutz via Development

On 2020-05-13 11:31, Marco Bubke wrote:

auto view3 = myObject.getCopy()[42].getView(); // not safe, copy is
destroyed

AFAIK you can say that a rvalue should not return a reference by using
ref-qualified member functions.

View getView() const & { return v;}


Qt is so many years behind the mainstream... This is a big problem in 
ranges-v3, do you really believe no-one works on this?


https://github.com/isocpp/CppCoreGuidelines/blob/master/docs/Lifetime.pdf
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs (was: Re: QString and related changes for Qt 6)

2020-05-13 Thread Иван Комиссаров
Nope, that would not be C++ if it wasn’t broken:

class C1
{
public:
std::string_view getMember() const & { return member; }
std::string member;
};

std::string_view m = C1().getMember(); // compiles!

You have to delete the method explicitly:

std::string_view getMember() const && = delete;

Now compilation fails:

call to deleted member function 'getMember'
std::string_view m = C1().getMember();
 ~^

> 13 мая 2020 г., в 11:31, Marco Bubke  написал(а):
> 
>  
> auto view3 = myObject.getCopy()[42].getView(); // not safe, copy is destroyed
>  
> AFAIK you can say that a rvalue should not return a reference by using 
> ref-qualified member functions.
>  
> View getView() const & { return v;}

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs (was: Re: QString and related changes for Qt 6)

2020-05-13 Thread Ville Voutilainen
On Wed, 13 May 2020 at 12:37, Marco Bubke  wrote:
> auto view3 = myObject.getCopy()[42].getView(); // not safe, copy is destroyed
> AFAIK you can say that a rvalue should not return a reference by using 
> ref-qualified member functions.
> View getView() const & { return v;}


However,

whatever_function(myObject.getCopy()[42].getView()); // never dangles,
so always safe

Disabling reference returns for rvalues prevents such forwarding cases
from working, and you need
to declare a separate lvalue to make your code work.
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs

2020-05-13 Thread Marc Mutz via Development

On 2020-05-13 09:04, Lars Knoll wrote:

On 12 May 2020, at 18:59, Marc Mutz  wrote:

[...]

Most other classes:
* Only take and return QString


This is wrong. By taking a QString in the API of non-string-related 
APIs, you expose QString as an implementation detail of the class. 
Think QRegion, which, before I added begin()/end(), had a SSO-like 
internal container (1 QRect or QVector) which forced most users 
to code around the owning-container API like this:


I don’t think you can compare those cases. QString is the container
our users use in 99% of the cases to hold a string. And this won’t
change (and I don’t think we should advocate any changes here).

So then, an API taking and returning a QString is the most logical,
easiest and most convenient to use.


There are two independent issues here: taking and returning.

For taking I don't see how "taking QString is most logical, easiest, 
most convenient" follows. It's simply not true that 99% of the cases to 
hold a string use QString. In the common case of applications which are 
not localized, all the nice QString APIs are fed with const char* 
literals, causing QString creation and destruction in user code. Even if 
you change all these to const char16_t* and a QString that doesn't 
allocate in this case, you still have all these complex (in the 
QTypeInfo sense) QString objects created and destroyed at the call site. 
This bloats user code. If all those shiny QString APIs would take 
QStringView instead, the construction and destruction of which is 
trivial (in the C++ sense), the compiler can remove all those calls and 
the QString construction (if any) happens centrally inside the library 
function (O(1) instead of O(N), N = #callers).


In the not so hypothetical case that Qt is used to visualize results of 
some business calculations, chances are that thrid-party libraries will 
use std::string or std::u16string, and not QString, requiring the use of 
QString::fromStdString() to pass these to a QString API. Had the API 
taken QStringView, no extra code would have been necessary.


So, I have shown that taking QString is neither the most convenient, nor 
the most easy, choice, as it requires users with other string types as 
data sources to jump through hoops to pass their data. Only if you 
employ a very narrow focus where both efficiency and the existence of 
3rd-party code are all ignored, can you still maintain that a function 
taking an owning container is more convenient and easier than one taking 
a view. The only logic in such an API that _I_ can find, however, is 
"MUST ... NOT ... BREAK ... COW logic", which has been proven as flawed 
over twenty years ago:


http://www.gotw.ca/gotw/043.htm
http://www.gotw.ca/gotw/044.htm
http://www.gotw.ca/gotw/045.htm

(and CoW isn't even correctly implemented in Qt, ever since unsharable 
data was removed).


In case the internal storage _is_ QString, then providing a QString&& 
overload to avoid the copy is a good idea, if you're willing to impart 
the details of the implementation that way.


Second, returning.

You talk about QString getting an SSO buffer, maybe. Then returning a 
QString will become even more expensive. It already got more expensive, 
since instead of sizeof(void*) it's now two or three (didn't check) 
words, but adding SSO will not make it better. And if we don't get SSO, 
classes can decide to store u16string instead, which _has_ SSO already. 
So, efficiency wins here, too.



  if (r.rectCount() == 1) {
 use(r.boundingRect());
  } else {
 const auto rects = r.rects();
 for (const QRect  : rects)
use(rect);
  }

If rects() had been a view (today, we'd use gsl/std::spanQRect>), all users could just do


I don’t get that argument. The region is a list of rectangles today,
so you could simply add a rects() method that returns them and the
code below would work.


I think you should take a look at QRegionPrivate::begin() (in Qt 6 or Qt 
5). And in Qt 5's version of QRegion::rects().



  for (const QRect  : r.rects())
 use(rect);

This is objectively a better API, for two reasons: a) the user doesn't 
need to care about some weird idiosyncrasies of the class to avoid 
performance penalties and b) the class author is now free to extend 
the SSO buffer from one to, say, four, without changing the API, not 
even those affected by Hyrum.


It _seems_ your solution is to fold views into owning containers, and 
while that may seem to work, it's dangerous:


Assume QRegion::rects() returned a QVector-acting-as-view. Then this 
would silently fail:


   QRegion region();
   for (const QRect  : region().rects())
   use(rect);

because, clearly, QVector is an owning container, so we don't care 
that the QRegion went out of scope. Whereas with a view, it will be 
immediately obvious (to a tool like Clazy, at least) that this can't 
work.


The above example is rather weirdly constructed.

But anyhow, those data lifetime issues when using views as return
values 

Re: [Development] Views in APIs (was: Re: QString and related changes for Qt 6)

2020-05-13 Thread Marco Bubke

auto view3 = myObject.getCopy()[42].getView(); // not safe, copy is destroyed

AFAIK you can say that a rvalue should not return a reference by using 
ref-qualified member functions.

View getView() const & { return v;}
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs (was: Re: QString and related changes for Qt 6)

2020-05-13 Thread Иван Комиссаров
Btw, I actually have an argument for returning a view=)

The ongoing c++20 ranges have exactly the same problem with the lifetime 
issues. For instance, this won’t compile:

auto results = std::vector{1, 2, 3, 4, 5, 6}
 | std::views::filter([](int n){ return n % 2 == 0; })
 | std::views::transform([](int n){ return n * 2; });

But this will:
std::vector numbers = {1, 2, 3, 4, 5, 6};
auto results = numbers 
 | std::views::filter([](int n){ return n % 2 == 0; })
 | std::views::transform([](int n){ return n * 2; });

So, we’re returning back to the products and range-for-loop example:

const auto products = project->productsList();
auto results = products | std::views::transform(…);

==OR==

auto results = project->productsSpan() | std::views::transform(...);

To me, second looks much more intuitive than the first one.
And yes, it is possible to disable the && overload for a method that returns a 
view so the chained calls won’t compile 
(doesn’t solve all the other issues, though and is a bit verbose):

std::span Project::productsSpan() const & { return d->products; }
std::span Project::productsSpan() const && = delete;

auto results = createProject().products() | std::views::transform(…); // 
compile error, no need for Clazy!

Ivan

> 13 мая 2020 г., в 10:14, Иван Комиссаров  написал(а):
> 
> 
> 
>> 13 мая 2020 г., в 09:04, Lars Knoll > > написал(а):
>> 
>> The above example is rather weirdly constructed. 
>> 
>> But anyhow, those data lifetime issues when using views as return values 
>> extensively are a lot less obvious to spot when a human reads the code. APIs 
>> should be safe to use wherever possible, so that our users don’t have to 
>> worry about those things. This will lead to fewer bugs in the resulting code 
>> and faster development times. Trading that for some saved CPU cycles is in 
>> almost all cases (and yes there are exceptions in low level classes) a very 
>> bad deal.
> 
> Well, I can’t say that returning COW container is an easy thing to do. It’s a 
> trade-off between «safety» and «some CPU cycles». And I’d say it’s much 
> better if app crashes compared to the case where I have spent ages in 
> profiler fixing performance bugs introduced by the developers who doesn’t 
> really know how COW works (e.g. use operator[] instead of .at(), hidden 
> detaches)
> 
> There's already a «-Wclazy-range-loop» warning in Clazy about detaching COWs:
> 
> From Qbs code (which is written by the developers who are supposed to know 
> COW problems): 
> 
> 1. for (const QString : rhs.split(QLatin1Char(' '))) // attempt to detach
> 
> 2. QList ProjectData::products() const { return d->products; }
> for (const ProductData  : project.products()) // oops, deep copy
> 
> And I can’t say that creating a variable on the stack before every for-loop 
> is an easier way for users (note, qAsConst doesn’t work for temporaries and 
> it should not).
> 
> The point is - there’s already a check in Clazy that does the similar check - 
> on can add a check for using a views from temporary.
> 
> And the lifetime issues only come into play when mixing views and non-views 
> approach:
> 
> Object myObject;
> auto view1 = myObject.getView()[42].getView(); // safe!
> auto view2 = myObject.getReference()[42].getView(); // safe!
> auto view3 = myObject.getCopy()[42].getView(); // not safe, copy is destroyed
> 
>> You can just as well argue the other way round. Returning a view requires 
>> the class to store the data in continuous memory. It can’t create it on the 
>> fly if asked.
> 
> How often is such a use-case, when you realize that you need to change the 
> simple getter to a container?
> 
> Why cannot you simply add a method with a new name in that case?
> 
> Am not really advocating for returning views, but it’s not that black and 
> white as you described, that’s a trade-off.
> What I am advocating for is that functions should take views where possible - 
> this is perfectly safe (you can pass temporaries into a view) and leads to 
> much easier code in some cases (users can pass unicode literals, 
> std::wstring, QVector and so on).
> 
> Ivan

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs (was: Re: QString and related changes for Qt 6)

2020-05-13 Thread Иван Комиссаров


> 13 мая 2020 г., в 09:04, Lars Knoll  написал(а):
> 
> The above example is rather weirdly constructed. 
> 
> But anyhow, those data lifetime issues when using views as return values 
> extensively are a lot less obvious to spot when a human reads the code. APIs 
> should be safe to use wherever possible, so that our users don’t have to 
> worry about those things. This will lead to fewer bugs in the resulting code 
> and faster development times. Trading that for some saved CPU cycles is in 
> almost all cases (and yes there are exceptions in low level classes) a very 
> bad deal.

Well, I can’t say that returning COW container is an easy thing to do. It’s a 
trade-off between «safety» and «some CPU cycles». And I’d say it’s much better 
if app crashes compared to the case where I have spent ages in profiler fixing 
performance bugs introduced by the developers who doesn’t really know how COW 
works (e.g. use operator[] instead of .at(), hidden detaches)

There's already a «-Wclazy-range-loop» warning in Clazy about detaching COWs:

From Qbs code (which is written by the developers who are supposed to know COW 
problems): 

1. for (const QString : rhs.split(QLatin1Char(' '))) // attempt to detach

2. QList ProjectData::products() const { return d->products; }
for (const ProductData  : project.products()) // oops, deep copy

And I can’t say that creating a variable on the stack before every for-loop is 
an easier way for users (note, qAsConst doesn’t work for temporaries and it 
should not).

The point is - there’s already a check in Clazy that does the similar check - 
on can add a check for using a views from temporary.

And the lifetime issues only come into play when mixing views and non-views 
approach:

Object myObject;
auto view1 = myObject.getView()[42].getView(); // safe!
auto view2 = myObject.getReference()[42].getView(); // safe!
auto view3 = myObject.getCopy()[42].getView(); // not safe, copy is destroyed

> You can just as well argue the other way round. Returning a view requires the 
> class to store the data in continuous memory. It can’t create it on the fly 
> if asked.

How often is such a use-case, when you realize that you need to change the 
simple getter to a container?

Why cannot you simply add a method with a new name in that case?

Am not really advocating for returning views, but it’s not that black and white 
as you described, that’s a trade-off.
What I am advocating for is that functions should take views where possible - 
this is perfectly safe (you can pass temporaries into a view) and leads to much 
easier code in some cases (users can pass unicode literals, std::wstring, 
QVector and so on).

Ivan___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs (was: Re: QString and related changes for Qt 6)

2020-05-13 Thread Philippe
On Tue, 12 May 2020 18:59:35 +0200
Marc Mutz via Development  wrote:

> QString-everywhere cements the naïve CoW world of the 
> 1990s for yet another decade.

CoW naive? Really not, this method is at the heart of many strategic 
technologies.
eg.:

* virtual memory used by most of operating system
* some databases
* principle behind any immutable data structure

Philippe

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views in APIs (was: Re: QString and related changes for Qt 6)

2020-05-13 Thread Lars Knoll

> On 12 May 2020, at 18:59, Marc Mutz  wrote:
> 
> Hi Lars,
> 
> Let me pick important points one per email here:
> 
> On 2020-05-12 09:49, Lars Knoll wrote:
> [...]
>> For String related classes:
>> * All methods not taking ownership of the passed arguments take a
>> QStringView
> 
> Almost (see below).
> 
>> * If the method stores a pointer to the passed data it should take a
>> QString to not surprise users.
> 
> ... in addition ... (though see below).

I don’t see a need to take a QStringView in those cases. With the exception of 
some low level APIs, Qt’s APIs should be safe to use. An overload taking a 
QStringView would either need to copy the data (in which case we could just as 
well only offer the QString version), or it holds an ‘unsecured’ pointer to the 
data, and lifetime is out of control of the class.

The second option is something I’m only willing to accept in a very limited 
number of cases, and the API naming should make it clear that this is what’s 
happening.

>> Exceptions can be done where it makes
>> sense, but then the method naming has to give clear indications that
>> this happens (like e.g. fromRawData())
>> * Return a QString in QString itself and when doing conversions,
>> return QStringView from QStringView
>> * No QStringRef!
>> * QLatin1String for backwards compatibility, can be disabled with a
>> macro (similar to QT_NO_CAST_FROM_ASCII)
>> * Remove or deprecate overloads taking a (const Char *, length) pair.
>> Replace them with QStringView
> 
> +1 to the above
> 
>> Most other classes:
>> * Only take and return QString
> 
> This is wrong. By taking a QString in the API of non-string-related APIs, you 
> expose QString as an implementation detail of the class. Think QRegion, 
> which, before I added begin()/end(), had a SSO-like internal container (1 
> QRect or QVector) which forced most users to code around the 
> owning-container API like this:

I don’t think you can compare those cases. QString is the container our users 
use in 99% of the cases to hold a string. And this won’t change (and I don’t 
think we should advocate any changes here).

So then, an API taking and returning a QString is the most logical, easiest and 
most convenient to use. 

> 
>   if (r.rectCount() == 1) {
>  use(r.boundingRect());
>   } else {
>  const auto rects = r.rects();
>  for (const QRect  : rects)
> use(rect);
>   }
> 
> If rects() had been a view (today, we'd use gsl/std::span), all 
> users could just do

I don’t get that argument. The region is a list of rectangles today, so you 
could simply add a rects() method that returns them and the code below would 
work.
> 
>   for (const QRect  : r.rects())
>  use(rect);
> 
> This is objectively a better API, for two reasons: a) the user doesn't need 
> to care about some weird idiosyncrasies of the class to avoid performance 
> penalties and b) the class author is now free to extend the SSO buffer from 
> one to, say, four, without changing the API, not even those affected by Hyrum.
> 
> It _seems_ your solution is to fold views into owning containers, and while 
> that may seem to work, it's dangerous:
> 
> Assume QRegion::rects() returned a QVector-acting-as-view. Then this would 
> silently fail:
> 
>QRegion region();
>for (const QRect  : region().rects())
>use(rect);
> 
> because, clearly, QVector is an owning container, so we don't care that the 
> QRegion went out of scope. Whereas with a view, it will be immediately 
> obvious (to a tool like Clazy, at least) that this can't work.

The above example is rather weirdly constructed. 

But anyhow, those data lifetime issues when using views as return values 
extensively are a lot less obvious to spot when a human reads the code. APIs 
should be safe to use wherever possible, so that our users don’t have to worry 
about those things. This will lead to fewer bugs in the resulting code and 
faster development times. Trading that for some saved CPU cycles is in almost 
all cases (and yes there are exceptions in low level classes) a very bad deal.
> 
> So, I'd argue for the complete opposite here: we would increase encapsulation 
> of our APIs if they stopped trafficking in owning container types. I call 
> this the NOI pattern (Non-Owning Interface). By not having to serve QString 
> everywhere, we'll be much more free to use alternative storage types in the 
> implementation (e.g. QVarLengthArray, or - the horror! - 
> std::pmr::u16string). Handling-wise, QStringView makes all these choices 
> equal, so the implementation of a class can use whatever is objectively 
> optimal instead of being bound to QString.

You can just as well argue the other way round. Returning a view requires the 
class to store the data in continuous memory. It can’t create it on the fly if 
asked.
> 
> AsidE: If you think that CoW is still a thing today: no. SSO is a thing these 
> days, and it seems that QString will not have it in Qt 6, either. NOI favours 
> SSO, 

[Development] Views in APIs (was: Re: QString and related changes for Qt 6)

2020-05-12 Thread Marc Mutz via Development

Hi Lars,

Let me pick important points one per email here:

On 2020-05-12 09:49, Lars Knoll wrote:
[...]

For String related classes:

* All methods not taking ownership of the passed arguments take a
QStringView


Almost (see below).


* If the method stores a pointer to the passed data it should take a
QString to not surprise users.


... in addition ... (though see below).


Exceptions can be done where it makes
sense, but then the method naming has to give clear indications that
this happens (like e.g. fromRawData())
* Return a QString in QString itself and when doing conversions,
return QStringView from QStringView
* No QStringRef!
* QLatin1String for backwards compatibility, can be disabled with a
macro (similar to QT_NO_CAST_FROM_ASCII)
* Remove or deprecate overloads taking a (const Char *, length) pair.
Replace them with QStringView


+1 to the above


Most other classes:

* Only take and return QString


This is wrong. By taking a QString in the API of non-string-related 
APIs, you expose QString as an implementation detail of the class. Think 
QRegion, which, before I added begin()/end(), had a SSO-like internal 
container (1 QRect or QVector) which forced most users to code 
around the owning-container API like this:


   if (r.rectCount() == 1) {
  use(r.boundingRect());
   } else {
  const auto rects = r.rects();
  for (const QRect  : rects)
 use(rect);
   }

If rects() had been a view (today, we'd use gsl/std::span), 
all users could just do


   for (const QRect  : r.rects())
  use(rect);

This is objectively a better API, for two reasons: a) the user doesn't 
need to care about some weird idiosyncrasies of the class to avoid 
performance penalties and b) the class author is now free to extend the 
SSO buffer from one to, say, four, without changing the API, not even 
those affected by Hyrum.


It _seems_ your solution is to fold views into owning containers, and 
while that may seem to work, it's dangerous:


Assume QRegion::rects() returned a QVector-acting-as-view. Then this 
would silently fail:


QRegion region();
for (const QRect  : region().rects())
use(rect);

because, clearly, QVector is an owning container, so we don't care that 
the QRegion went out of scope. Whereas with a view, it will be 
immediately obvious (to a tool like Clazy, at least) that this can't 
work.


So, I'd argue for the complete opposite here: we would increase 
encapsulation of our APIs if they stopped trafficking in owning 
container types. I call this the NOI pattern (Non-Owning Interface). By 
not having to serve QString everywhere, we'll be much more free to use 
alternative storage types in the implementation (e.g. 
QVarLengthArray, or - the horror! - std::pmr::u16string). 
Handling-wise, QStringView makes all these choices equal, so the 
implementation of a class can use whatever is objectively optimal 
instead of being bound to QString.


AsidE: If you think that CoW is still a thing today: no. SSO is a thing 
these days, and it seems that QString will not have it in Qt 6, either. 
NOI favours SSO, QString-everywhere cements the naïve CoW world of the 
1990s for yet another decade.


Learn from QRegion!

I have spoken on many conferences (at least QtWS, Meeting C++, emBO++) 
on this, if anyone wants to learn more.


Thanks,
Marc
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-12 Thread Joerg Bornemann
On 6/12/19 10:28 AM, Mutz, Marc via Development wrote:
> On 2019-06-12 09:20, Ulf Hermann wrote:
>>>     I don't think that (non-)COW is a problem in the scenario under
>>>     discussion.
>>
>> Having the thing COW makes the porting simpler at the cost of suboptimal
>> performance. If we wrote a COW container as a drop-in replacement for
>> QMap or QHash with equivalent behavior we could just s/QMap/QFlatMap/g
>> in Qt code and the issue would largely be solved.
> 
> As I said earlier: there's no alternative to thinking. There's no one 
> container that fits all use-cases. QFlatMap isn't it, either. It has 
> linear insertion behaviour, and it invalidates iterators on remove. You 
> need to analyse each use of QMap before replacing it with a QFlatMap (or 
> an unsorted vector, or a C array with the key as an index, or...).
> 
> Get the idea out of your collective heads that we just need QFlatMap and 
> everything will be solved. For some code, yes. Just like QMap is the 
> correct container for some code already. But s/QMap/QFlatMap/ is just as 
> wrong as using QMap just because you need an associative container was 
> in the first place.

I have to agree with Marc here. *Every* replacement must be checked 
manually whether the simple s/QMap/QFlatMap/ suffices or a more involved 
change is necessary.

I believe many cases would be easily portable, but there will still be 
spots left where a raw sorted vector is the right approach - or another 
abstraction.


Joerg
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-12 Thread Mutz, Marc via Development

On 2019-06-12 09:20, Ulf Hermann wrote:

I don't think that (non-)COW is a problem in the scenario under
discussion.


Having the thing COW makes the porting simpler at the cost of 
suboptimal

performance. If we wrote a COW container as a drop-in replacement for
QMap or QHash with equivalent behavior we could just s/QMap/QFlatMap/g
in Qt code and the issue would largely be solved.


As I said earlier: there's no alternative to thinking. There's no one 
container that fits all use-cases. QFlatMap isn't it, either. It has 
linear insertion behaviour, and it invalidates iterators on remove. You 
need to analyse each use of QMap before replacing it with a QFlatMap (or 
an unsorted vector, or a C array with the key as an index, or...).


Get the idea out of your collective heads that we just need QFlatMap and 
everything will be solved. For some code, yes. Just like QMap is the 
correct container for some code already. But s/QMap/QFlatMap/ is just as 
wrong as using QMap just because you need an associative container was 
in the first place.


Thanks,
Marc
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-12 Thread Ulf Hermann
> I don't think that (non-)COW is a problem in the scenario under
> discussion.

Having the thing COW makes the porting simpler at the cost of suboptimal 
performance. If we wrote a COW container as a drop-in replacement for 
QMap or QHash with equivalent behavior we could just s/QMap/QFlatMap/g 
in Qt code and the issue would largely be solved.

Ulf
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-11 Thread Konstantin Shegunov
On Tue, Jun 11, 2019 at 4:04 PM Giuseppe D'Angelo 
wrote:

> Well, one difference is that we don't _already_ have an implementation
> of flat (unordered) maps to be replaced by a 3rd party library, and we
> are finding lots of cases where this would be useful...
>

Fair point. We don't already have an implementation that solves systems,
but I leave that to rest, it's not that important for this thread. But to
play devil's advocate for a second - taking the stance that QVector, QList
and friends should go away, isn't it better to *ask* that such a container
goes into the STL and use that instead of boost? Or even just wait for it
to materialize in the STL (eventually), i.e. basically do nothing?

On Tue, Jun 11, 2019 at 10:02 PM André Pönitz  wrote:

> I don't think that (non-)COW is a problem in the scenario under discussion.
>

It may, if eventually it's to be exposed as public class, that's why I
brought it up. Otherwise I personally don't have any objection to (or
argument against) a non-shared container.
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-11 Thread André Pönitz
On Tue, Jun 11, 2019 at 11:42:32AM +0300, Konstantin Shegunov wrote:
> On Tue, Jun 11, 2019 at 11:31 AM Ulf Hermann  wrote:
> 
> > I imagine that a vector which automatically sorts itself on the first
> > lookup after any changes if it's larger than X items could be a drop-in
> > replacement for most of the places where I misuse QHash or QMap. X could
> > be a template parameter or found by some heuristic.
> >
> 
> I though about this as well. There's one caveat though. It can't be
> (easily) made COW (if we require it).
> [...]
> Do I miss something?

I don't think that (non-)COW is a problem in the scenario under discussion.

Andre'

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-11 Thread Giuseppe D'Angelo via Development

Il 11/06/19 13:49, Konstantin Shegunov ha scritto:
I find that unlikely to happen. Otherwise it'd raise a question in my 
mind why this[1] couldn't go in.


[1]: https://codereview.qt-project.org/c/qt/qtbase/+/261715


Well, one difference is that we don't _already_ have an implementation 
of flat (unordered) maps to be replaced by a 3rd party library, and we 
are finding lots of cases where this would be useful...


Anyhow, if anyone wants to spend a few days on a QFlatMap / QFlatHash, 
be my guest.


My 2 c,
--
Giuseppe D'Angelo | giuseppe.dang...@kdab.com | Senior Software Engineer
KDAB (France) S.A.S., a KDAB Group company
Tel. France +33 (0)4 90 84 08 53, http://www.kdab.com
KDAB - The Qt, C++ and OpenGL Experts



smime.p7s
Description: Firma crittografica S/MIME
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-11 Thread Konstantin Shegunov
On Tue, Jun 11, 2019 at 12:03 PM Ulf Hermann  wrote:

> 3) Also sort the data on copying. Then you can still share the result.
>

You mean at the point of the shallow-copy (i.e. ref-count increment)? If
so, yes, that could work too, I think.

On Tue, Jun 11, 2019 at 12:46 PM Giuseppe D'Angelo via Development <
development@qt-project.org> wrote:

> It's fun to write containers and everything, but this stuff already
>
exists, and it's ready to be used (under liberal licenses):
> boost::container::flat_map, absl::flat_hash_map, and so on. Maybe the
> only thing missing is a flat unordered container that doesn't use
> hashing at all (just a vector of elements compared with op== for
> detecting duplicates, for very small workloads).
>
> Anyhow, given all of this isn't meant for public APIs, let's just use
> them and move on?
>

I find that unlikely to happen. Otherwise it'd raise a question in my mind
why this[1] couldn't go in.

[1]: https://codereview.qt-project.org/c/qt/qtbase/+/261715
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-11 Thread Giuseppe D'Angelo via Development

On 11/06/2019 10:28, Ulf Hermann wrote:


So, not having read the discussion about the equivalent container in
std, I'll make a naive suggestion here:

What about finding a QSortedVector that works for 90% of our internal
cases and adding that as private API (for now). The remaining 10% will
need custom solutions or keep using QHash/QMap, but replacing the 90%
will give us most of the possible efficiency gains already.

I imagine that a vector which automatically sorts itself on the first
lookup after any changes if it's larger than X items could be a drop-in
replacement for most of the places where I misuse QHash or QMap. X could
be a template parameter or found by some heuristic.


It's fun to write containers and everything, but this stuff already 
exists, and it's ready to be used (under liberal licenses): 
boost::container::flat_map, absl::flat_hash_map, and so on. Maybe the 
only thing missing is a flat unordered container that doesn't use 
hashing at all (just a vector of elements compared with op== for 
detecting duplicates, for very small workloads).


Anyhow, given all of this isn't meant for public APIs, let's just use 
them and move on?


My 2 c,
--
Giuseppe D'Angelo | giuseppe.dang...@kdab.com | Senior Software Engineer
KDAB (France) S.A.S., a KDAB Group company
Tel. France +33 (0)4 90 84 08 53, http://www.kdab.com
KDAB - The Qt, C++ and OpenGL Experts




smime.p7s
Description: S/MIME Cryptographic Signature
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-11 Thread Ulf Hermann
> I though about this as well. There's one caveat though. It can't be 
> (easily) made COW (if we require it). If your lookup is non-mutable 
> (i.e. `constFind` or w/e it's named), it'd mean that you have to mutate 
> the data in a const method. This implies doing it (thread-)safely is 
> going to get rather clumsy as there are 2 possibilities I see:
> 1) Detach in the `const` lookup if the data's dirty (i.e. not sorted) 
> and then sort it, and then do the lookup.
> 2) Lock the data block, sort it and then do the lookup.

3) Also sort the data on copying. Then you can still share the result. 
The "sorted" flag will always be set in the other thread and you can do 
an actually const lookup. If the sorted flag is not set on lookup you 
indeed need to detach (or do linear lookup).
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-11 Thread Konstantin Shegunov
On Tue, Jun 11, 2019 at 11:31 AM Ulf Hermann  wrote:

> I imagine that a vector which automatically sorts itself on the first
> lookup after any changes if it's larger than X items could be a drop-in
> replacement for most of the places where I misuse QHash or QMap. X could
> be a template parameter or found by some heuristic.
>

I though about this as well. There's one caveat though. It can't be
(easily) made COW (if we require it). If your lookup is non-mutable (i.e.
`constFind` or w/e it's named), it'd mean that you have to mutate the data
in a const method. This implies doing it (thread-)safely is going to get
rather clumsy as there are 2 possibilities I see:
1) Detach in the `const` lookup if the data's dirty (i.e. not sorted) and
then sort it, and then do the lookup.
2) Lock the data block, sort it and then do the lookup.

Do I miss something?
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-07 Thread Mutz, Marc via Development

On 2019-05-17 10:18, Giuseppe D'Angelo via Development wrote:

QHash ones are bidirectional


Nope.

(Go look yourself, it's too hilarious for spoilers)
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread André Pönitz
Иван Комиссаров wrote:
> I think, your point is wrong. Despite the fact Qt is a GUI toolkit, it should 
> perform well.
> Take a look at Qt Item Views. They really sucks in terms of performance.
> QAbstractItemModel can have any number of rows/columns (that fits in MAX_INT),
>  but which view can really handle that? None of them!
> I had to use a model with 3kk rows in it.


"3kk" doesn't parse as number for me, but assuming that's 3 * 1024 * 1024
the problem must have been somewhere else as the following shows
10 million entries in a standard QTreeView:


#include 
#include 
#include 


struct Model : QAbstractItemModel
{
QModelIndex index(int row, int column, const QModelIndex &) const
{
return createIndex(row, column);
}

QModelIndex parent(const QModelIndex &) const { return {}; }

int rowCount(const QModelIndex &) const { return 10 * 1000 * 1000; }

int columnCount(const QModelIndex &) const { return 1; }

QVariant data(const QModelIndex , int role) const
{
if (index.isValid() && role == Qt::DisplayRole)
return index.row();
return {};
}
};

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Model m;
QTreeView v;
v.setUniformRowHeights(true);
v.setModel();
v.show();
return a.exec();
}



Andre'
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Mutz, Marc via Development

On 2019-06-06 15:49, Lars Knoll wrote:
On 6 Jun 2019, at 15:36, Mutz, Marc via Development 
 wrote:


On 2019-06-06 15:14, Konstantin Tokarev wrote:
[...]

There is a principle of single level of abstraction [1], and inline
implementation
of flat map can be viewed of violation of such principle. If flat map
implementations
were kept speparately, it would indeed make code easier to read and 
maintain.

[1] http://principles-wiki.net/principles:single_level_of_abstraction


The code factors the setting and lookup into functions already. A 
function is an abstraction. If you're concerned about a function that 
calls find_if and then uses the result, how do you rate this one: 
https://code.woboq.org/qt5/qtbase/src/widgets/kernel/qgesturemanager.cpp.html#_ZN15QGestureManager26filterEventThroughContextsERK9QMultiMapIP7QObjectN2Qt11GestureTypeEEP6QEvent


It's using _all_ the nice abstractions!

Puts some stuff into perspective, doesn't it?


Yes, the code in QGestureManager sucks. Basically because it abuses
our data structures in a really bad way.

But let’s not use the worst example you can find in Qt’s code base as
a comparison. Unmaintainable code in one place doesn’t justify doing
whatever you want in other places.


IMO, the code sucks because it conflates algorithms and data structures. 
Wirth's book, however, is called Algorihms + Data Structures = 
Programmes, not Data Structures = Programmes. Yet, that is exactly what 
I feel is asked of me here: to hide the algorithms in a data structure. 
But the end consequence of this is ... qgesturemanager.cpp.

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Lars Knoll
> On 6 Jun 2019, at 15:36, Mutz, Marc via Development 
>  wrote:
> 
> On 2019-06-06 15:14, Konstantin Tokarev wrote:
> [...]
>> There is a principle of single level of abstraction [1], and inline
>> implementation
>> of flat map can be viewed of violation of such principle. If flat map
>> implementations
>> were kept speparately, it would indeed make code easier to read and maintain.
>> [1] http://principles-wiki.net/principles:single_level_of_abstraction
> 
> The code factors the setting and lookup into functions already. A function is 
> an abstraction. If you're concerned about a function that calls find_if and 
> then uses the result, how do you rate this one: 
> https://code.woboq.org/qt5/qtbase/src/widgets/kernel/qgesturemanager.cpp.html#_ZN15QGestureManager26filterEventThroughContextsERK9QMultiMapIP7QObjectN2Qt11GestureTypeEEP6QEvent
> 
> It's using _all_ the nice abstractions!
> 
> Puts some stuff into perspective, doesn't it?

Yes, the code in QGestureManager sucks. Basically because it abuses our data 
structures in a really bad way.

But let’s not use the worst example you can find in Qt’s code base as a 
comparison. Unmaintainable code in one place doesn’t justify doing whatever you 
want in other places.

Cheers,
Lars


___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Mutz, Marc via Development

On 2019-06-06 15:14, Konstantin Tokarev wrote:
[...]

There is a principle of single level of abstraction [1], and inline
implementation
of flat map can be viewed of violation of such principle. If flat map
implementations
were kept speparately, it would indeed make code easier to read and 
maintain.


[1] http://principles-wiki.net/principles:single_level_of_abstraction


The code factors the setting and lookup into functions already. A 
function is an abstraction. If you're concerned about a function that 
calls find_if and then uses the result, how do you rate this one: 
https://code.woboq.org/qt5/qtbase/src/widgets/kernel/qgesturemanager.cpp.html#_ZN15QGestureManager26filterEventThroughContextsERK9QMultiMapIP7QObjectN2Qt11GestureTypeEEP6QEvent


It's using _all_ the nice abstractions!

Puts some stuff into perspective, doesn't it?
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Konstantin Tokarev


06.06.2019, 15:43, "Elvis Stansvik" :
> Den tors 6 juni 2019 kl 13:56 skrev Elvis Stansvik :
>>  Den tors 6 juni 2019 kl 13:40 skrev Mutz, Marc via Development
>>  :
>>  >
>>  > On 2019-06-06 12:24, Lars Knoll wrote:
>>  > >> On 6 Jun 2019, at 11:08, Simon Hausmann 
>>  > >> wrote:
>>  > >>
>>  > >> Am 06.06.19 um 10:42 schrieb Mutz, Marc via Development:
>>  > [...]
>>  > >>> I have the feeling that some participants of these discussions
>>  > >>> thought
>>  > >>> they joined an adulation club for Qt API lovers instead.
>>  > >>
>>  > >> I don't quite understand what you're trying to say with adulation
>>  > >> club
>>  > >> for Qt API lovers. Could you explain this, please? Am I supposed to
>>  > >> feel
>>  > >> insulted or offended?
>>  > >
>>  > > Not sure what to say to this neither.
>>  > >
>>  > > Let’s remember that a large part of Qt’s success has been due to
>>  > > its API. Making programming easy and fun has been at the core of what
>>  > > we’re doing and it has to stay that way, or we’re really loosing
>>  > > the core of what made and makes Qt successful.
>>  > >
>>  > > Many of our users strongly feel (and IMO rightfully so) that STL is a
>>  > > difficult API that’s maybe very powerful for the things it does, but
>>  > > at the same time hard to use and where it’s very easy to get things
>>  > > wrong. Qt solved a lot of that pain.
>>  > >
>>  > > Yes, our classes might not be quite as performant in all cases, but
>>  > > they do get the job done. And they do help our users to write code
>>  > > they feel comfortable maintaining, something that is in most cases
>>  > > much more important to them than another few percent of performance.
>>  >
>>  > You are equating Qt users and Qt implementers. You can maintain the Qt
>>  > API, but use more efficient data structures in the implementation. You
>>  > seem to be implying that these two things cannot be separated.
>>  >
>>  > None of the changes where I replaced QMap changes the public API at all
>>  > (except adding an overload because we can). No user is affected by this
>>  > in any way, except that they have a few pages of memory more free than
>>  > before.
>>  >
>>  > Please explain to me how any of those changes makes _users_ of Qt have
>>  > to revert to the STL?
>>  >
>>  > And please explain to me how it can possibly be worthwhile to generate
>>  > 8KiB of code _just_ to not have to use lower_bound? Which argument could
>>  > *possibly* be made against a lower_bound? Esp. seeing as many attempts
>>  > to write one by hand have failed. I remember a bug about shortcuts being
>>  > mapped to the wrong key, because the hand-rolled binary search was
>>  > unstable.
>>  >
>>  > I'm sorry, but we have a lot of code that is less readable than any of
>>  > the changes I uploaded. It just cannot be an argument to say that it's
>>  > unreadable because it uses an STL algorithm. This sentiment has caused
>>  > so very, very many quadratic loops because people get the impression
>>  > that std::remove_if is toxic, and in each one the solution was to use
>>  > remove_if, because the hand-rolled alternative would be totally
>>  > unreadable.
>>  >
>>  > I'm sad to see that Qt devs think so lowly of themselves as to be unable
>>  > to understand a piece of code that uses an STL algorithm. Really. I'm
>>  > out of words.
>>
>>  Since you've repeated this a few times now: I don't think anyone has
>>  suggested that they cannot understand the STL code. What they have
>>  said is that the find it _less_ readable/maintainable, not
>>  _un_readable. Someone jump in and correct me if I understood them
>>  wrong, in which case I join Marc in the shocked camp :)
>
> Also, Qt developers will of course have to work out what policies you
> want to have for the implementation of Qt, but my take as a user is
> that I don't have the expectation that Qt is always optimal, just
> because it is a library. I trust that Qt developers always make
> case-by-case judgement between 1) API for the user, 2) Size/speed of
> the code, 3) Maintainability of the code. The case-by-case because
> there are some parts which quite obviously won't be called often, or
> classes which won't have many instances.
>
> For example in the QDrag patch, where you made an ad-hoc inline
> implementation of a mapping on top of a vector (roughly doubling the
> LoC), instead of using a datatype that expresses what it is (QMap), in
> order to save 4KiB and some allocations, I guess it's to be expected
> that some people disagree with the priorities and give you a -1. I
> would say I'm on the fence on that particular one. But perhaps the
> best course of action is, as was suggested earlier, to make a helper
> datatype for small mappings? Maybe everyone would be happy then? If
> such optimizations become common, and the pattern repeated at say 20
> places, the code is undoubtedly going to become more brittle and
> harder to maintain.

There is a principle of single level of abstraction [1], and 

Re: [Development] Views

2019-06-06 Thread Lars Knoll
> On 6 Jun 2019, at 14:49, Mutz, Marc via Development 
>  wrote:
> 
> On 2019-06-06 14:04, Lars Knoll wrote:
>>> On 6 Jun 2019, at 13:39, Mutz, Marc via Development 
>>>  wrote:
> [...]
>>> You are equating Qt users and Qt implementers. You can maintain the Qt API, 
>>> but use more efficient data structures in the implementation. You seem to 
>>> be implying that these two things cannot be separated.
>> The comment above was aimed at our APIs and towards our users, not
>> about how we implement things internally.
> 
> Ok, clash of context. This subthread was about the exact change in QtWayland, 
> though, and that's internal implementation.
> 
>>> None of the changes where I replaced QMap changes the public API at all 
>>> (except adding an overload because we can). No user is affected by this in 
>>> any way, except that they have a few pages of memory more free than before.
>>> Please explain to me how any of those changes makes _users_ of Qt have to 
>>> revert to the STL?
>>> And please explain to me how it can possibly be worthwhile to generate 8KiB 
>>> of code _just_ to not have to use lower_bound? Which argument could 
>>> *possibly* be made against a lower_bound? Esp. seeing as many attempts to 
>>> write one by hand have failed. I remember a bug about shortcuts being 
>>> mapped to the wrong key, because the hand-rolled binary search was unstable.
>> You have in general been advocating lately to remove/deprecate lots of
>> Qt API in favour of STL. This is what I referred to, not
>> implementation details in our code.
> 
> Ok, noted.
> 
>> Removing the usage of a QMap for a mapping of 5 values is the right
>> thing to do. Whether we need lower_bound() for that and a sorted list,
>> or simply an unsorted vector where we iterate until we find the right
>> value doesn’t matter too much in this case. Performance wise both
>> would probably be equivalent :)
>>> I'm sorry, but we have a lot of code that is less readable than any of the 
>>> changes I uploaded. It just cannot be an argument to say that it's 
>>> unreadable because it uses an STL algorithm. This sentiment has caused so 
>>> very, very many quadratic loops because people get the impression that 
>>> std::remove_if is toxic, and in each one the solution was to use remove_if, 
>>> because the hand-rolled alternative would be totally unreadable.
>> Nobody here said that. I also believe those changes that you proposed
>> got approved to the largest degree.
> 
> This is not the impression I get from 
> https://codereview.qt-project.org/c/qt/qtwayland/+/264069, or 
> https://codereview.qt-project.org/c/qt/qtbase/+/264129 vs. 
> https://codereview.qt-project.org/c/qt/qtbase/+/264161
> 
>> If you read what I said earlier, I also said that in most cases better
>> data structures and algorithms will lead to more readable code. I am
>> not opposed to using those in Qt, quite the opposite.
> 
> Good.
> 
>>> I'm sad to see that Qt devs think so lowly of themselves as to be unable to 
>>> understand a piece of code that uses an STL algorithm. Really. I'm out of 
>>> words.
>> Nobody ever said that as far as I can tell. What people said is that
>> there are cases, where a loop is just as efficient and easier to read
>> (e.g. when searching for an entry). And in that case it’s fine to
>> simply use that. So please stop turning the meaning of what people
>> said around like that.
> 
> I was a poignant remark, yes, but that's _exactly_ the feedback I get from 
> the reviews I quoted above: Dropping QMap is acceptable when the API is 
> unchanged (as with the array replacing the map), but totally not acceptable 
> (b/c/o unreadable) if it contains lower_bound or find_if. To the point that 
> the 'better' choice is to replace QMap with QHash - because they have the 
> same API. I'd ROTFL if I wasn't crying.

The discussion showed that replacing QMap with QHash gives you most of the 
improvement that you wanted.

I can understand that maintainers don’t like if the change adds ~40 lines that 
can’t be shared, and complicate the code. We are spending a lot of time 
maintaining our code base, and simplifying our lives there is extremely 
important as we have limited man-power available. This is especially true if 
similar changes are being done in many places in our code base.

With respect to that I can see why people argue for using either a QHash (where 
the change is a one liner), or ask you to consider providing a (maybe internal) 
special class that can be used as a drop in replacement.

Cheers,
Lars

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Mutz, Marc via Development

On 2019-06-06 14:04, Lars Knoll wrote:
On 6 Jun 2019, at 13:39, Mutz, Marc via Development 
 wrote:

[...]
You are equating Qt users and Qt implementers. You can maintain the Qt 
API, but use more efficient data structures in the implementation. You 
seem to be implying that these two things cannot be separated.


The comment above was aimed at our APIs and towards our users, not
about how we implement things internally.


Ok, clash of context. This subthread was about the exact change in 
QtWayland, though, and that's internal implementation.


None of the changes where I replaced QMap changes the public API at 
all (except adding an overload because we can). No user is affected by 
this in any way, except that they have a few pages of memory more free 
than before.


Please explain to me how any of those changes makes _users_ of Qt have 
to revert to the STL?


And please explain to me how it can possibly be worthwhile to generate 
8KiB of code _just_ to not have to use lower_bound? Which argument 
could *possibly* be made against a lower_bound? Esp. seeing as many 
attempts to write one by hand have failed. I remember a bug about 
shortcuts being mapped to the wrong key, because the hand-rolled 
binary search was unstable.


You have in general been advocating lately to remove/deprecate lots of
Qt API in favour of STL. This is what I referred to, not
implementation details in our code.


Ok, noted.


Removing the usage of a QMap for a mapping of 5 values is the right
thing to do. Whether we need lower_bound() for that and a sorted list,
or simply an unsorted vector where we iterate until we find the right
value doesn’t matter too much in this case. Performance wise both
would probably be equivalent :)


I'm sorry, but we have a lot of code that is less readable than any of 
the changes I uploaded. It just cannot be an argument to say that it's 
unreadable because it uses an STL algorithm. This sentiment has caused 
so very, very many quadratic loops because people get the impression 
that std::remove_if is toxic, and in each one the solution was to use 
remove_if, because the hand-rolled alternative would be totally 
unreadable.


Nobody here said that. I also believe those changes that you proposed
got approved to the largest degree.


This is not the impression I get from 
https://codereview.qt-project.org/c/qt/qtwayland/+/264069, or 
https://codereview.qt-project.org/c/qt/qtbase/+/264129 vs. 
https://codereview.qt-project.org/c/qt/qtbase/+/264161



If you read what I said earlier, I also said that in most cases better
data structures and algorithms will lead to more readable code. I am
not opposed to using those in Qt, quite the opposite.


Good.

I'm sad to see that Qt devs think so lowly of themselves as to be 
unable to understand a piece of code that uses an STL algorithm. 
Really. I'm out of words.


Nobody ever said that as far as I can tell. What people said is that
there are cases, where a loop is just as efficient and easier to read
(e.g. when searching for an entry). And in that case it’s fine to
simply use that. So please stop turning the meaning of what people
said around like that.


I was a poignant remark, yes, but that's _exactly_ the feedback I get 
from the reviews I quoted above: Dropping QMap is acceptable when the 
API is unchanged (as with the array replacing the map), but totally not 
acceptable (b/c/o unreadable) if it contains lower_bound or find_if. To 
the point that the 'better' choice is to replace QMap with QHash - 
because they have the same API. I'd ROTFL if I wasn't crying.


Thanks,
Marc
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Elvis Stansvik
Den tors 6 juni 2019 kl 13:56 skrev Elvis Stansvik :
>
> Den tors 6 juni 2019 kl 13:40 skrev Mutz, Marc via Development
> :
> >
> > On 2019-06-06 12:24, Lars Knoll wrote:
> > >> On 6 Jun 2019, at 11:08, Simon Hausmann 
> > >> wrote:
> > >>
> > >> Am 06.06.19 um 10:42 schrieb Mutz, Marc via Development:
> > [...]
> > >>> I have the feeling that some participants of these discussions
> > >>> thought
> > >>> they joined an adulation club for Qt API lovers instead.
> > >>
> > >> I don't quite understand what you're trying to say with adulation
> > >> club
> > >> for Qt API lovers. Could you explain this, please? Am I supposed to
> > >> feel
> > >> insulted or offended?
> > >
> > >  Not sure what to say to this neither.
> > >
> > > Let’s remember that a large part of Qt’s success has been due to
> > > its API. Making programming easy and fun has been at the core of what
> > > we’re doing and it has to stay that way, or we’re really loosing
> > > the core of what made and makes Qt successful.
> > >
> > > Many of our users strongly feel (and IMO rightfully so) that STL is a
> > > difficult API that’s maybe very powerful for the things it does, but
> > > at the same time hard to use and where it’s very easy to get things
> > > wrong. Qt solved a lot of that pain.
> > >
> > > Yes, our classes might not be quite as performant in all cases, but
> > > they do get the job done. And they do help our users to write code
> > > they feel comfortable maintaining, something that is in most cases
> > > much more important to them than another few percent of performance.
> >
> > You are equating Qt users and Qt implementers. You can maintain the Qt
> > API, but use more efficient data structures in the implementation. You
> > seem to be implying that these two things cannot be separated.
> >
> > None of the changes where I replaced QMap changes the public API at all
> > (except adding an overload because we can). No user is affected by this
> > in any way, except that they have a few pages of memory more free than
> > before.
> >
> > Please explain to me how any of those changes makes _users_ of Qt have
> > to revert to the STL?
> >
> > And please explain to me how it can possibly be worthwhile to generate
> > 8KiB of code _just_ to not have to use lower_bound? Which argument could
> > *possibly* be made against a lower_bound? Esp. seeing as many attempts
> > to write one by hand have failed. I remember a bug about shortcuts being
> > mapped to the wrong key, because the hand-rolled binary search was
> > unstable.
> >
> > I'm sorry, but we have a lot of code that is less readable than any of
> > the changes I uploaded. It just cannot be an argument to say that it's
> > unreadable because it uses an STL algorithm. This sentiment has caused
> > so very, very many quadratic loops because people get the impression
> > that std::remove_if is toxic, and in each one the solution was to use
> > remove_if, because the hand-rolled alternative would be totally
> > unreadable.
> >
> > I'm sad to see that Qt devs think so lowly of themselves as to be unable
> > to understand a piece of code that uses an STL algorithm. Really. I'm
> > out of words.
>
> Since you've repeated this a few times now: I don't think anyone has
> suggested that they cannot understand the STL code. What they have
> said is that the find it _less_ readable/maintainable, not
> _un_readable. Someone jump in and correct me if I understood them
> wrong, in which case I join Marc in the shocked camp :)

Also, Qt developers will of course have to work out what policies you
want to have for the implementation of Qt, but my take as a user is
that I don't have the expectation that Qt is always optimal, just
because it is a library. I trust that Qt developers always make
case-by-case judgement between 1) API for the user, 2) Size/speed of
the code, 3) Maintainability of the code. The case-by-case because
there are some parts which quite obviously won't be called often, or
classes which won't have many instances.

For example in the QDrag patch, where you made an ad-hoc inline
implementation of a mapping on top of a vector (roughly doubling the
LoC), instead of using a datatype that expresses what it is (QMap), in
order to save 4KiB and some allocations, I guess it's to be expected
that some people disagree with the priorities and give you a -1. I
would say I'm on the fence on that particular one. But perhaps the
best course of action is, as was suggested earlier, to make a helper
datatype for small mappings? Maybe everyone would be happy then? If
such optimizations become common, and the pattern repeated at say 20
places, the code is undoubtedly going to become more brittle and
harder to maintain.

Elvis

>
> Elvis
>
> >
> > Thanks,
> > Marc
> > ___
> > Development mailing list
> > Development@qt-project.org
> > https://lists.qt-project.org/listinfo/development
___
Development mailing list

Re: [Development] Views

2019-06-06 Thread Christian Kandeler
On Thu, 06 Jun 2019 13:46:12 +0200
"Mutz, Marc via Development"  wrote:

> On 2019-06-06 12:24, Ola Røer Thorsen wrote:
> > tor. 6. jun. 2019 kl. 10:21 skrev Vitaly Fanaskov
> > :
> > 
> >> Qt is GUI framework. Not only, yes, but this is the main purpose.
> >> +/-
> >> 10MB is almost nothing for GUI apps. Slightly faster
> >> lookup/insertions,
> >> cache line, proper alignment... Well, nice to have, but when an app
> >> spends most of the time on rendering something, it doesn't matter.
> >> Highly unlikely will it be a bottle neck.
> > 
> > I'm still supporting Qt Quick-applications running on devices with a
> > total of only 128 MB RAM, so I disagree that +/- 10MB is irrelevant
> > for Qt. The performance could definitely be better too.
> 
> 
> I'm sorry. I tried. But you'll have to upgrade your hardware, because 
> the people that develop the product you base your work on are unable to 
> read code that uses std::lower_bound.
> 

Could you please stop trolling? It's getting quite annoying.


Thanks,
Christian
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Lars Knoll
> On 6 Jun 2019, at 13:39, Mutz, Marc via Development 
>  wrote:
> 
> On 2019-06-06 12:24, Lars Knoll wrote:
>>> On 6 Jun 2019, at 11:08, Simon Hausmann 
>>> wrote:
>>> Am 06.06.19 um 10:42 schrieb Mutz, Marc via Development:
> [...]
 I have the feeling that some participants of these discussions
 thought
 they joined an adulation club for Qt API lovers instead.
>>> I don't quite understand what you're trying to say with adulation
>>> club
>>> for Qt API lovers. Could you explain this, please? Am I supposed to
>>> feel
>>> insulted or offended?
>> Not sure what to say to this neither.
>> Let’s remember that a large part of Qt’s success has been due to
>> its API. Making programming easy and fun has been at the core of what
>> we’re doing and it has to stay that way, or we’re really loosing
>> the core of what made and makes Qt successful.
>> Many of our users strongly feel (and IMO rightfully so) that STL is a
>> difficult API that’s maybe very powerful for the things it does, but
>> at the same time hard to use and where it’s very easy to get things
>> wrong. Qt solved a lot of that pain.
>> Yes, our classes might not be quite as performant in all cases, but
>> they do get the job done. And they do help our users to write code
>> they feel comfortable maintaining, something that is in most cases
>> much more important to them than another few percent of performance.
> 
> You are equating Qt users and Qt implementers. You can maintain the Qt API, 
> but use more efficient data structures in the implementation. You seem to be 
> implying that these two things cannot be separated.

The comment above was aimed at our APIs and towards our users, not about how we 
implement things internally.
> 
> None of the changes where I replaced QMap changes the public API at all 
> (except adding an overload because we can). No user is affected by this in 
> any way, except that they have a few pages of memory more free than before.
> 
> Please explain to me how any of those changes makes _users_ of Qt have to 
> revert to the STL?
> 
> And please explain to me how it can possibly be worthwhile to generate 8KiB 
> of code _just_ to not have to use lower_bound? Which argument could 
> *possibly* be made against a lower_bound? Esp. seeing as many attempts to 
> write one by hand have failed. I remember a bug about shortcuts being mapped 
> to the wrong key, because the hand-rolled binary search was unstable.

You have in general been advocating lately to remove/deprecate lots of Qt API 
in favour of STL. This is what I referred to, not implementation details in our 
code.

Removing the usage of a QMap for a mapping of 5 values is the right thing to 
do. Whether we need lower_bound() for that and a sorted list, or simply an 
unsorted vector where we iterate until we find the right value doesn’t matter 
too much in this case. Performance wise both would probably be equivalent :)
> 
> I'm sorry, but we have a lot of code that is less readable than any of the 
> changes I uploaded. It just cannot be an argument to say that it's unreadable 
> because it uses an STL algorithm. This sentiment has caused so very, very 
> many quadratic loops because people get the impression that std::remove_if is 
> toxic, and in each one the solution was to use remove_if, because the 
> hand-rolled alternative would be totally unreadable.

Nobody here said that. I also believe those changes that you proposed got 
approved to the largest degree.

If you read what I said earlier, I also said that in most cases better data 
structures and algorithms will lead to more readable code. I am not opposed to 
using those in Qt, quite the opposite.

> 
> I'm sad to see that Qt devs think so lowly of themselves as to be unable to 
> understand a piece of code that uses an STL algorithm. Really. I'm out of 
> words.

Nobody ever said that as far as I can tell. What people said is that there are 
cases, where a loop is just as efficient and easier to read (e.g. when 
searching for an entry). And in that case it’s fine to simply use that. So 
please stop turning the meaning of what people said around like that.

Lars

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Elvis Stansvik
Den tors 6 juni 2019 kl 13:40 skrev Mutz, Marc via Development
:
>
> On 2019-06-06 12:24, Lars Knoll wrote:
> >> On 6 Jun 2019, at 11:08, Simon Hausmann 
> >> wrote:
> >>
> >> Am 06.06.19 um 10:42 schrieb Mutz, Marc via Development:
> [...]
> >>> I have the feeling that some participants of these discussions
> >>> thought
> >>> they joined an adulation club for Qt API lovers instead.
> >>
> >> I don't quite understand what you're trying to say with adulation
> >> club
> >> for Qt API lovers. Could you explain this, please? Am I supposed to
> >> feel
> >> insulted or offended?
> >
> >  Not sure what to say to this neither.
> >
> > Let’s remember that a large part of Qt’s success has been due to
> > its API. Making programming easy and fun has been at the core of what
> > we’re doing and it has to stay that way, or we’re really loosing
> > the core of what made and makes Qt successful.
> >
> > Many of our users strongly feel (and IMO rightfully so) that STL is a
> > difficult API that’s maybe very powerful for the things it does, but
> > at the same time hard to use and where it’s very easy to get things
> > wrong. Qt solved a lot of that pain.
> >
> > Yes, our classes might not be quite as performant in all cases, but
> > they do get the job done. And they do help our users to write code
> > they feel comfortable maintaining, something that is in most cases
> > much more important to them than another few percent of performance.
>
> You are equating Qt users and Qt implementers. You can maintain the Qt
> API, but use more efficient data structures in the implementation. You
> seem to be implying that these two things cannot be separated.
>
> None of the changes where I replaced QMap changes the public API at all
> (except adding an overload because we can). No user is affected by this
> in any way, except that they have a few pages of memory more free than
> before.
>
> Please explain to me how any of those changes makes _users_ of Qt have
> to revert to the STL?
>
> And please explain to me how it can possibly be worthwhile to generate
> 8KiB of code _just_ to not have to use lower_bound? Which argument could
> *possibly* be made against a lower_bound? Esp. seeing as many attempts
> to write one by hand have failed. I remember a bug about shortcuts being
> mapped to the wrong key, because the hand-rolled binary search was
> unstable.
>
> I'm sorry, but we have a lot of code that is less readable than any of
> the changes I uploaded. It just cannot be an argument to say that it's
> unreadable because it uses an STL algorithm. This sentiment has caused
> so very, very many quadratic loops because people get the impression
> that std::remove_if is toxic, and in each one the solution was to use
> remove_if, because the hand-rolled alternative would be totally
> unreadable.
>
> I'm sad to see that Qt devs think so lowly of themselves as to be unable
> to understand a piece of code that uses an STL algorithm. Really. I'm
> out of words.

Since you've repeated this a few times now: I don't think anyone has
suggested that they cannot understand the STL code. What they have
said is that the find it _less_ readable/maintainable, not
_un_readable. Someone jump in and correct me if I understood them
wrong, in which case I join Marc in the shocked camp :)

Elvis

>
> Thanks,
> Marc
> ___
> Development mailing list
> Development@qt-project.org
> https://lists.qt-project.org/listinfo/development
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Mutz, Marc via Development

On 2019-06-06 12:24, Ola Røer Thorsen wrote:

tor. 6. jun. 2019 kl. 10:21 skrev Vitaly Fanaskov
:


Qt is GUI framework. Not only, yes, but this is the main purpose.
+/-
10MB is almost nothing for GUI apps. Slightly faster
lookup/insertions,
cache line, proper alignment... Well, nice to have, but when an app
spends most of the time on rendering something, it doesn't matter.
Highly unlikely will it be a bottle neck.


I'm still supporting Qt Quick-applications running on devices with a
total of only 128 MB RAM, so I disagree that +/- 10MB is irrelevant
for Qt. The performance could definitely be better too.



I'm sorry. I tried. But you'll have to upgrade your hardware, because 
the people that develop the product you base your work on are unable to 
read code that uses std::lower_bound.



SCNR. I _am_ in shock.

@Ola: Please, if you have a support contract, file bug reports.
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Mutz, Marc via Development

On 2019-06-06 12:24, Lars Knoll wrote:

On 6 Jun 2019, at 11:08, Simon Hausmann 
wrote:

Am 06.06.19 um 10:42 schrieb Mutz, Marc via Development:

[...]

I have the feeling that some participants of these discussions
thought
they joined an adulation club for Qt API lovers instead.


I don't quite understand what you're trying to say with adulation
club
for Qt API lovers. Could you explain this, please? Am I supposed to
feel
insulted or offended?


 Not sure what to say to this neither.

Let’s remember that a large part of Qt’s success has been due to
its API. Making programming easy and fun has been at the core of what
we’re doing and it has to stay that way, or we’re really loosing
the core of what made and makes Qt successful.

Many of our users strongly feel (and IMO rightfully so) that STL is a
difficult API that’s maybe very powerful for the things it does, but
at the same time hard to use and where it’s very easy to get things
wrong. Qt solved a lot of that pain.

Yes, our classes might not be quite as performant in all cases, but
they do get the job done. And they do help our users to write code
they feel comfortable maintaining, something that is in most cases
much more important to them than another few percent of performance.


You are equating Qt users and Qt implementers. You can maintain the Qt 
API, but use more efficient data structures in the implementation. You 
seem to be implying that these two things cannot be separated.


None of the changes where I replaced QMap changes the public API at all 
(except adding an overload because we can). No user is affected by this 
in any way, except that they have a few pages of memory more free than 
before.


Please explain to me how any of those changes makes _users_ of Qt have 
to revert to the STL?


And please explain to me how it can possibly be worthwhile to generate 
8KiB of code _just_ to not have to use lower_bound? Which argument could 
*possibly* be made against a lower_bound? Esp. seeing as many attempts 
to write one by hand have failed. I remember a bug about shortcuts being 
mapped to the wrong key, because the hand-rolled binary search was 
unstable.


I'm sorry, but we have a lot of code that is less readable than any of 
the changes I uploaded. It just cannot be an argument to say that it's 
unreadable because it uses an STL algorithm. This sentiment has caused 
so very, very many quadratic loops because people get the impression 
that std::remove_if is toxic, and in each one the solution was to use 
remove_if, because the hand-rolled alternative would be totally 
unreadable.


I'm sad to see that Qt devs think so lowly of themselves as to be unable 
to understand a piece of code that uses an STL algorithm. Really. I'm 
out of words.


Thanks,
Marc
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Ola Røer Thorsen
tor. 6. jun. 2019 kl. 10:21 skrev Vitaly Fanaskov :

> Qt is GUI framework. Not only, yes, but this is the main purpose. +/-
> 10MB is almost nothing for GUI apps. Slightly faster lookup/insertions,
> cache line, proper alignment... Well, nice to have, but when an app
> spends most of the time on rendering something, it doesn't matter.
> Highly unlikely will it be a bottle neck.
>

I'm still supporting Qt Quick-applications running on devices with a total
of only 128 MB RAM, so I disagree that +/- 10MB is irrelevant for Qt. The
performance could definitely be better too.

Cheers,
Ola
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Lars Knoll


On 6 Jun 2019, at 11:08, Simon Hausmann 
mailto:simon.hausm...@qt.io>> wrote:


Am 06.06.19 um 10:42 schrieb Mutz, Marc via Development:
On 2019-06-06 09:47, Simon Hausmann wrote:
[...]
However I don't find your arguments that find_if/lower_bound is not
harder to read convincing. I continue to agree with Joerg and Tor Arne
and feel that the API of the associative containers results in code that
is more compact, visually less noisy and consequently easier to read.
[...]

Well, yes, put that way, sure, it's more (source) code, and more noisy.

*But* it's not "hard to read" in the sense that you stare at it and
can't figure out what the hell the code is doing. For that, you need
to go to qgesturemanager.cpp (which, incidentally uses all the nice Qt
container APIs to make an unreadable mess of things). Algorithms need
some getting used to, but if people would stop fighting the urge to
bash everything looking even remotely STL-ish as unreadable, they
would find that it's quite ok.

The question I have, after all this talk about readability, however,
is this:

Do you guys _actually_ think that readability of Qt code trumps
_everything_?


For me the answer is "no". I believe that for the majority of Qt code we
should strike for a compromise - as opposed to "trumping everything" -
and certainly use more low-level code in areas that we know are
particularly performance sensitive. That includes for example the
software rasterize, the inside of QString or the text shaping.

I fully agree here. Readability doesn’t trump everything and I don’t think 
anybody ever claimed that. But _maintainability_ of our code base does matter, 
especially given that we do not have an unlimited amount of developers working 
on Qt.



I'd rather agree with our Chief Maintainer who said, on
https://codereview.qt-project.org/c/qt/qtbase/+/114327:

IMO, we should use whatever is most efficient for our internal data
structures.

I stand by that comment. But please remember that this still means that our 
internal code has to be maintainable. It doesn’t help us if someone writes a 
super efficient implementation that nobody understands or can work with.

In my experience, more efficient data structures will in many cases lead to 
better and more readable code. If they don’t, one should re-evaluate whether 
the change is the correct thing to do and also weight in ease of maintenance.

IMO, that hits the nail on the head: we have an obligation to our
users to use the most efficient data structure (and, by extension,
looping construct) we possibly can, and can't just pop in the first
data structure that comes to mind.

IMNSHO, you can optimize for readability in your own app and see
whether you sustain in the market. In a library, used on millions of
machines every day, spending 8KiB (or 4KiB, or just 1KiB) just to use
a slightly less noisy code version is - sorry - selfish. If you
contribute to Qt, you should be putting yourself in the service of
it's users.


Yes, we have an obligation to our users and we have an obligation to the
rest of the community that's developing Qt. I strongly suspect that you
are in fact in agreement with me that the code that we have in code must
strike that compromise so that others in the project continue to feel
comfortable to read, understand and modify the code and yet we can
deliver a product to our users that's competitive in terms of
performance (run-time, code size, etc.).

What we appear to disagree on is the exact line of complexity / style /
noise. We also don't have to see eye to eye on this, I think. I think
that simply leaves us with the established decision making process,
where with our changes we have to appeal to the approvers in the project
and rely on the lazy concensus here. In the context of that, I note your
strong objection to Joerg's statement while I agree with Joerg.

As said above, I don’t think better performance has to conflict with 
readability of the code. If it does, maybe think whether you could solve this 
differently.


I have the feeling that some participants of these discussions thought
they joined an adulation club for Qt API lovers instead.


I don't quite understand what you're trying to say with adulation club
for Qt API lovers. Could you explain this, please? Am I supposed to feel
insulted or offended?

Not sure what to say to this neither.

Let’s remember that a large part of Qt’s success has been due to its API. 
Making programming easy and fun has been at the core of what we’re doing and it 
has to stay that way, or we’re really loosing the core of what made and makes 
Qt successful.

Many of our users strongly feel (and IMO rightfully so) that STL is a difficult 
API that’s maybe very powerful for the things it does, but at the same time 
hard to use and where it’s very easy to get things wrong. Qt solved a lot of 
that pain.

Yes, our classes might not be quite as performant in all cases, but they do get 
the job done. And they do help our users to write code 

Re: [Development] Views

2019-06-06 Thread Tor Arne Vestbø
On 6 Jun 2019, at 10:42, Mutz, Marc via Development 
 wrote:
> 
> *But* it's not "hard to read" in the sense that you stare at it and can't 
> figure out what the hell the code is doing.

You can insult my intelligence and CS credentials all you want, I’m still going 
to claim that the STL-code in [1] is harder to read, and obscures what the 
function is doing by putting the algorithm in your face first.

> Do you guys _actually_ think that readability of Qt code trumps _everything_?

Obviously not, and you know that’s not the case. It’s a balance, just like 
everything else.

> IMO, that hits the nail on the head: we have an obligation to our users to 
> use the most efficient data structure (and, by extension, looping construct) 
> we possibly can, and can't just pop in the first data structure that comes to 
> mind.
> 
> IMNSHO, you can optimize for readability in your own app and see whether you 
> sustain in the market. In a library, used on millions of machines every day, 
> spending 8KiB (or 4KiB, or just 1KiB) just to use a slightly less noisy code 
> version is - sorry - selfish. If you contribute to Qt, you should be putting 
> yourself in the service of it's users.

The service to our users is to make Qt the best toolkit it can be across a wide 
set of facets and for a wide set of users and use-cases.

One of those facets is the ability to quickly fix bugs and improve on the code 
easily, so that Qt can move forward. Readable and well abstracted code helps in 
that.

In some cases performance matters, and in some cases binary size matters. 
Obviously we should avoid using the wrong algorithm or data structure in 
performance critical code, and avoid bloating the binaries for low end targets 
where we can, but doing so needs to be balanced with the other considerations, 
so that we know the tradeoff is worth it. 

> I have the feeling that some participants of these discussions thought they 
> joined an adulation club for Qt API lovers instead.

Please consider whether statements like this, and ones you’ve made in follow-up 
emails, are in line with the project’s code of conduct. If that doesn’t concern 
you, I’m also pretty sure that leaving out this kind of language will increase 
the support for your case 

Tor Arne 

[1] https://codereview.qt-project.org/c/qt/qtwayland/+/264069
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Mutz, Marc via Development

On 2019-06-06 11:08, Simon Hausmann wrote:

Am 06.06.19 um 10:42 schrieb Mutz, Marc via Development:

[...]

Do you guys _actually_ think that readability of Qt code trumps
_everything_?



For me the answer is "no". I believe that for the majority of Qt code 
we

should strike for a compromise - as opposed to "trumping everything" -
and certainly use more low-level code in areas that we know are
particularly performance sensitive. That includes for example the
software rasterize, the inside of QString or the text shaping.


These are areas where we need offensive _optimisation_, yes, I agree.

[...]
Yes, we have an obligation to our users and we have an obligation to 
the

rest of the community that's developing Qt. I strongly suspect that you
are in fact in agreement with me that the code that we have in code 
must

strike that compromise so that others in the project continue to feel
comfortable to read, understand and modify the code and yet we can
deliver a product to our users that's competitive in terms of
performance (run-time, code size, etc.).


Indeed, we agree here.


What we appear to disagree on is the exact line of complexity / style /
noise.


To put it poignantly: We disagree on our judgement of the ability of Qt 
devs to learn the STL. I think they can, you think they can't.



We also don't have to see eye to eye on this, I think. I think
that simply leaves us with the established decision making process,
where with our changes we have to appeal to the approvers in the 
project
and rely on the lazy concensus here. In the context of that, I note 
your

strong objection to Joerg's statement while I agree with Joerg.


As I note Lars' approval of the change from QVector to std::vector, even 
though it sprinkled int/size_t casts all over the place.


You appeal to the status quo. Replacing a QMap with a QHash for a 
five-entry data stucture is not a change, it's churn. I'd like to 
educate people in how to make simple data structures do what they need 
from them, without resorting to complex data stuctures. Does his appeal 
to reviewers? Probably less so. Is it necessary? Yes, I think so.



I have the feeling that some participants of these discussions thought
they joined an adulation club for Qt API lovers instead.



I don't quite understand what you're trying to say with adulation club
for Qt API lovers. Could you explain this, please? Am I supposed to 
feel

insulted or offended?


You can mentally replace it with "fan club": Some people act as if Qt's 
API is superior to all other APIs. Well, it's not. It has weaknesses 
too, it's ugly, too (QGradientStop::first?!), and people should rise 
above this and see it for what it is: An API with a certain set of 
principles, not always honoured, also ageing sometimes. It's use should 
be justified the same was as the use of the STL is: what's better (for 
any sense of of the word). It's not bad just because it's not Qt.


Thanks,
Marc
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Vitaly Fanaskov
Well, my point was: there always should be a trade off. I've never wrote 
that Qt should be slow. I just wanted to point out that understanding of 
performance might be different for different sort of libraries (and for 
different cases).

I hope, you filed a ticket or fixed this problem yourself. This looks 
like a corner case.

On 6/6/19 11:09 AM, Иван Комиссаров wrote:
> I think, your point is wrong. Despite the fact Qt is a GUI toolkit, it should 
> perform well.
> Take a look at Qt Item Views. They really sucks in terms of performance.
> QAbstractItemModel can have any number of rows/columns (that fits in 
> MAX_INT), but which view can really handle that? None of them!
> I had to use a model with 3kk rows in it. Guess what I used to display it? 
> Custom item view.
> AFAIK Qt item views still use vectors internally and simply changing the 
> internal container to an std::deque can (needs profiling, though) improve 
> performance since it stores data in chunks. Imagine prepending a row to a 
> table with 3kk rows... well, good luck reallocating a vector in QHeaderView.
>
> Иван Комиссаров
>
> 6 июня 2019 г., в 10:17, Vitaly Fanaskov  написал(а):
>
>>> As a library implementer, you are simply not _allowed_ the freedom to
>>> use a convenient tool over the most efficient one. That is, to put it
>>> mildly, a disservice to users and a disgrace to the profession of
>>> programmers.
>> Well, optimization is probably good, but not always, I would say. If
>> your app takes 0.001% less memory and works 0.001% faster then before in
>> some certain configurations... Well, it's probably worthless, unless
>> you've improved google search engine or something like that.
>>
>> Qt is GUI framework. Not only, yes, but this is the main purpose. +/-
>> 10MB is almost nothing for GUI apps. Slightly faster lookup/insertions,
>> cache line, proper alignment... Well, nice to have, but when an app
>> spends most of the time on rendering something, it doesn't matter.
>> Highly unlikely will it be a bottle neck.
>>
>> The thing is, that we should keep in mind what kind of library Qt is.
>> And also on what devices it runs.
>>
>> I would rather have readable code than tiny bit optimized code, but much
>> less readable. Simple and readable code => easy to maintain => easy to
>> extend => easy to add new features. If you app is something for
>> high-frequency trading or should run on devices with super limited
>> resources, just don't use Qt containers. It's not appropriate tool for
>> these cases.
>>
>> I don't want to encourage people to write, for example, O(n^2) code
>> instead of O(n). But if you want to "improve" something which is working
>> more or less acceptable... Probably you should put your effort on
>> something else.
>>
>>> On 6/6/19 9:05 AM, Mutz, Marc via Development wrote:
 On 2019-06-06 08:24, Joerg Bornemann wrote:
> On 6/5/19 5:49 PM, Mutz, Marc via Development wrote:
>
> As a library implementer, you are simply not _allowed_ the freedom to
> use a convenient tool over the most efficient one. That is, to put it
> mildly, a disservice to users and a disgrace to the profession of
> programmers. 8KiB just to look up a pointer in a map of {string, int}?
> That's 1/4th of the icache size of many processors!
 [...]

 While I agree with this in general... every time we use a sorted vector
 as a dictionary replacement we're scattering implementation details all
 over the place, creating code that's much harder to read and easier to
 make mistakes in (*).

 Maybe it's time for a general purpose dictionary class based on a sorted
 vector?
>>> FTR: More of the same:
>>> https://codereview.qt-project.org/c/qt/qtbase/+/264128 and
>>> https://codereview.qt-project.org/c/qt/qtbase/+/264129
>>>
>>> I very strongly object to the notion that a find_if or lower_bound is
>>> harder to read. More code does _not_ equate to less readable, as Qt
>>> over and over has shown. There are different patterns involved than in
>>> using Qt containers, sure, and by all means, if find_if frightens you,
>>> then use a raw for loop, but this stuff is not rocket science. And
>>> depending on how you define 'mistakes', it's just as easy to make a
>>> mistake by forgetting qAsConst() on a Qt container than it is to, say,
>>> combine iterators from different containers.
>>>
>>> As for QSortedVector/QFlatMap. There's a reason there's none in the
>>> std, yet, and it has to do with when to sort. In one of the patches
>>> above, we don't need to sort at all, because there're only ever O(10)
>>> elements in there. Sorting, as performed by a QFlatMap would be
>>> overkill there. In another, we don't even store the key, as it's equal
>>> to the position of the element in the array. Sorting the key would be
>>> nonsense. Oftem, you populate the data structure once and then only
>>> perform lookups. In that case, a QFlatMap would waste time sorting
>>> while you don't need it. So, yes, by 

Re: [Development] Views

2019-06-06 Thread Robin Burchell
Hi Marc,

I agree with a lot of your points. Performance is important to me. I won't get 
bogged down in the specifics, because way too much energy has already been 
wasted on this (and related) threads I think, so I'll just say a few things.

On Thu, Jun 6, 2019, at 10:45 AM, Mutz, Marc via Development wrote:
> IMO, that hits the nail on the head: we have an obligation to our users 
> to use the most efficient data structure (and, by extension, looping 
> construct) we possibly can, and can't just pop in the first data 
> structure that comes to mind.

The thing is, loops are easy to use. Containers are easy to use. You might know 
the STL like the back of your hand - I will be the first to admit that I don't. 
I write loops, I don't use find_if. I commit many other sins like this on a 
daily basis. The same is true I'm sure of many other pieces of the STL, or 
indeed, any other software.

However, to make myself feel a little less awful, I will add that I am sure 
that I'm not alone here, and I think that is why some people have been pushing 
back a bit on the point of abstraction.

Using the specific example of QMap: It's one thing to know not to use a QMap 
for a small container; it's another issue altogether to have an easily usable 
alternative that can be used in place of it, especially if the container is 
supposed to be exposed to another component, for example. It's simply less 
reading/writing/cognitive effort to bang out container usage than the 
alternative. That is generally the purpose of abstractions, after all.

> IMNSHO, you can optimize for readability in your own app and see whether 
> you sustain in the market. In a library, used on millions of machines 
> every day, spending 8KiB (or 4KiB, or just 1KiB) just to use a slightly 
> less noisy code version is - sorry - selfish. If you contribute to Qt, 
> you should be putting yourself in the service of it's users.

Again, I'll emphasize that I don't disagree with the point that you are making. 
I just think that you may want to consider that various enablers can make your 
life easier in that you have to write a lot less grumpy size-reducing patches, 
and a lot less mails arguing your point. That is one of the points of Qt, after 
all:  that you make it easier for other people to write better code faster.

> I have the feeling that some participants of these discussions thought 
> they joined an adulation club for Qt API lovers instead.

I don't agree with this kind of attack, though, even if it was not directed at 
any one individual by name. Let's (_everyone_) please keep the mailing list a 
pleasant place to read (and write).

-- 
  Robin Burchell
  ro...@crimson.no

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Иван Комиссаров
I think, your point is wrong. Despite the fact Qt is a GUI toolkit, it should 
perform well.
Take a look at Qt Item Views. They really sucks in terms of performance.
QAbstractItemModel can have any number of rows/columns (that fits in MAX_INT), 
but which view can really handle that? None of them!
I had to use a model with 3kk rows in it. Guess what I used to display it? 
Custom item view.
AFAIK Qt item views still use vectors internally and simply changing the 
internal container to an std::deque can (needs profiling, though) improve 
performance since it stores data in chunks. Imagine prepending a row to a table 
with 3kk rows... well, good luck reallocating a vector in QHeaderView.

Иван Комиссаров

6 июня 2019 г., в 10:17, Vitaly Fanaskov  написал(а):

>> As a library implementer, you are simply not _allowed_ the freedom to
>> use a convenient tool over the most efficient one. That is, to put it
>> mildly, a disservice to users and a disgrace to the profession of
>> programmers.
> Well, optimization is probably good, but not always, I would say. If 
> your app takes 0.001% less memory and works 0.001% faster then before in 
> some certain configurations... Well, it's probably worthless, unless 
> you've improved google search engine or something like that.
> 
> Qt is GUI framework. Not only, yes, but this is the main purpose. +/- 
> 10MB is almost nothing for GUI apps. Slightly faster lookup/insertions, 
> cache line, proper alignment... Well, nice to have, but when an app 
> spends most of the time on rendering something, it doesn't matter. 
> Highly unlikely will it be a bottle neck.
> 
> The thing is, that we should keep in mind what kind of library Qt is. 
> And also on what devices it runs.
> 
> I would rather have readable code than tiny bit optimized code, but much 
> less readable. Simple and readable code => easy to maintain => easy to 
> extend => easy to add new features. If you app is something for 
> high-frequency trading or should run on devices with super limited 
> resources, just don't use Qt containers. It's not appropriate tool for 
> these cases.
> 
> I don't want to encourage people to write, for example, O(n^2) code 
> instead of O(n). But if you want to "improve" something which is working 
> more or less acceptable... Probably you should put your effort on 
> something else.
> 
>> On 6/6/19 9:05 AM, Mutz, Marc via Development wrote:
>>> On 2019-06-06 08:24, Joerg Bornemann wrote:
 On 6/5/19 5:49 PM, Mutz, Marc via Development wrote:
 
 As a library implementer, you are simply not _allowed_ the freedom to
 use a convenient tool over the most efficient one. That is, to put it
 mildly, a disservice to users and a disgrace to the profession of
 programmers. 8KiB just to look up a pointer in a map of {string, int}?
 That's 1/4th of the icache size of many processors!
>>> [...]
>>> 
>>> While I agree with this in general... every time we use a sorted vector
>>> as a dictionary replacement we're scattering implementation details all
>>> over the place, creating code that's much harder to read and easier to
>>> make mistakes in (*).
>>> 
>>> Maybe it's time for a general purpose dictionary class based on a sorted
>>> vector?
>> 
>> FTR: More of the same: 
>> https://codereview.qt-project.org/c/qt/qtbase/+/264128 and 
>> https://codereview.qt-project.org/c/qt/qtbase/+/264129
>> 
>> I very strongly object to the notion that a find_if or lower_bound is 
>> harder to read. More code does _not_ equate to less readable, as Qt 
>> over and over has shown. There are different patterns involved than in 
>> using Qt containers, sure, and by all means, if find_if frightens you, 
>> then use a raw for loop, but this stuff is not rocket science. And 
>> depending on how you define 'mistakes', it's just as easy to make a 
>> mistake by forgetting qAsConst() on a Qt container than it is to, say, 
>> combine iterators from different containers.
>> 
>> As for QSortedVector/QFlatMap. There's a reason there's none in the 
>> std, yet, and it has to do with when to sort. In one of the patches 
>> above, we don't need to sort at all, because there're only ever O(10) 
>> elements in there. Sorting, as performed by a QFlatMap would be 
>> overkill there. In another, we don't even store the key, as it's equal 
>> to the position of the element in the array. Sorting the key would be 
>> nonsense. Oftem, you populate the data structure once and then only 
>> perform lookups. In that case, a QFlatMap would waste time sorting 
>> while you don't need it. So, yes, by all means, let's have a QFlatMap, 
>> but it would just be another over-complicated container that people 
>> misuse. Let's, as a community, learn how to use a raw vector (or 
>> array) first, then introduce convenience.
>> 
>> Don't pick a container by it's API. Pick it by how you use it. No-one 
>> would use a RB tree for O(10) items if he had to implement it himself. 
>> You wouldn't even implement one for O(1M) 

Re: [Development] Views

2019-06-06 Thread Simon Hausmann

Am 06.06.19 um 10:42 schrieb Mutz, Marc via Development:
> On 2019-06-06 09:47, Simon Hausmann wrote:
> [...]
>> However I don't find your arguments that find_if/lower_bound is not
>> harder to read convincing. I continue to agree with Joerg and Tor Arne
>> and feel that the API of the associative containers results in code that
>> is more compact, visually less noisy and consequently easier to read.
> [...]
>
> Well, yes, put that way, sure, it's more (source) code, and more noisy.
>
> *But* it's not "hard to read" in the sense that you stare at it and 
> can't figure out what the hell the code is doing. For that, you need 
> to go to qgesturemanager.cpp (which, incidentally uses all the nice Qt 
> container APIs to make an unreadable mess of things). Algorithms need 
> some getting used to, but if people would stop fighting the urge to 
> bash everything looking even remotely STL-ish as unreadable, they 
> would find that it's quite ok.
>
> The question I have, after all this talk about readability, however, 
> is this:
>
> Do you guys _actually_ think that readability of Qt code trumps 
> _everything_? 


For me the answer is "no". I believe that for the majority of Qt code we 
should strike for a compromise - as opposed to "trumping everything" - 
and certainly use more low-level code in areas that we know are 
particularly performance sensitive. That includes for example the 
software rasterize, the inside of QString or the text shaping.



> I'd rather agree with our Chief Maintainer who said, on 
> https://codereview.qt-project.org/c/qt/qtbase/+/114327:
>
>> IMO, we should use whatever is most efficient for our internal data 
>> structures.
>
> IMO, that hits the nail on the head: we have an obligation to our 
> users to use the most efficient data structure (and, by extension, 
> looping construct) we possibly can, and can't just pop in the first 
> data structure that comes to mind.
>
> IMNSHO, you can optimize for readability in your own app and see 
> whether you sustain in the market. In a library, used on millions of 
> machines every day, spending 8KiB (or 4KiB, or just 1KiB) just to use 
> a slightly less noisy code version is - sorry - selfish. If you 
> contribute to Qt, you should be putting yourself in the service of 
> it's users.
>

Yes, we have an obligation to our users and we have an obligation to the 
rest of the community that's developing Qt. I strongly suspect that you 
are in fact in agreement with me that the code that we have in code must 
strike that compromise so that others in the project continue to feel 
comfortable to read, understand and modify the code and yet we can 
deliver a product to our users that's competitive in terms of 
performance (run-time, code size, etc.).

What we appear to disagree on is the exact line of complexity / style / 
noise. We also don't have to see eye to eye on this, I think. I think 
that simply leaves us with the established decision making process, 
where with our changes we have to appeal to the approvers in the project 
and rely on the lazy concensus here. In the context of that, I note your 
strong objection to Joerg's statement while I agree with Joerg.


> I have the feeling that some participants of these discussions thought 
> they joined an adulation club for Qt API lovers instead.
>

I don't quite understand what you're trying to say with adulation club 
for Qt API lovers. Could you explain this, please? Am I supposed to feel 
insulted or offended?



Simon

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Mutz, Marc via Development

On 2019-06-06 10:17, Vitaly Fanaskov wrote:

As a library implementer, you are simply not _allowed_ the freedom to
use a convenient tool over the most efficient one. That is, to put it
mildly, a disservice to users and a disgrace to the profession of
programmers.

Well, optimization is probably good, but not always, I would say. If
your app takes 0.001% less memory and works 0.001% faster then before 
in

some certain configurations... Well, it's probably worthless, unless
you've improved google search engine or something like that.


Nice try: The change in question reduced the text size of QtWayland by 
_0.6%_, not 0.001%. Off by almost three orders of magnitude, sorry. I 
don't think it's a problem to make QtWayland 10% smaller by the applying 
similar changes across it. In fact, I don't think it's a problem to make 
all of Qt 10% smaller in the same way. It just takes longer.


It's simply wrong to say that executable size and speed don't matter. Qt 
is targeting embedded devices, not just the desktop. You often have only 
a limited amount of memory on these and Qt supports cutting features out 
to make it smaller so it fits. If Qt contributors were not so 
laissez-faire with their coding habits, users could use more features on 
any given hardware. Even if all of Qt fits, this change makes two pages 
more RAM available for the OS to do it's thing (cache I/O, e.g.).


As a library programmer, you have to empower your users to make their 
products work. You are _not_ at a liberty to force them to jump through 
hoops because you were too lazy to use the correct data structure, just 
because it would involve an STL algorithm call. If you don't want to be 
a library programmer, go write apps.


Thanks,
Marc
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Mutz, Marc via Development

On 2019-06-06 09:47, Simon Hausmann wrote:
[...]

However I don't find your arguments that find_if/lower_bound is not
harder to read convincing. I continue to agree with Joerg and Tor Arne
and feel that the API of the associative containers results in code 
that

is more compact, visually less noisy and consequently easier to read.

[...]

Well, yes, put that way, sure, it's more (source) code, and more noisy.

*But* it's not "hard to read" in the sense that you stare at it and 
can't figure out what the hell the code is doing. For that, you need to 
go to qgesturemanager.cpp (which, incidentally uses all the nice Qt 
container APIs to make an unreadable mess of things). Algorithms need 
some getting used to, but if people would stop fighting the urge to bash 
everything looking even remotely STL-ish as unreadable, they would find 
that it's quite ok.


The question I have, after all this talk about readability, however, is 
this:


Do you guys _actually_ think that readability of Qt code trumps 
_everything_? So much so that even the use of a find_if (which could be 
replaced by a raw for loop) or lower_bound (which could not; only 10% of 
Berkeley CS students managed to write it correctly in a 2h time limit) 
is unacceptable?


If that is so, who cleans up qstring.cpp from all the SIMD stuff?

I'd rather agree with our Chief Maintainer who said, on 
https://codereview.qt-project.org/c/qt/qtbase/+/114327:


IMO, we should use whatever is most efficient for our internal data 
structures.


IMO, that hits the nail on the head: we have an obligation to our users 
to use the most efficient data structure (and, by extension, looping 
construct) we possibly can, and can't just pop in the first data 
structure that comes to mind.


IMNSHO, you can optimize for readability in your own app and see whether 
you sustain in the market. In a library, used on millions of machines 
every day, spending 8KiB (or 4KiB, or just 1KiB) just to use a slightly 
less noisy code version is - sorry - selfish. If you contribute to Qt, 
you should be putting yourself in the service of it's users.


I have the feeling that some participants of these discussions thought 
they joined an adulation club for Qt API lovers instead.


Thanks,
Marc
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Vitaly Fanaskov
> As a library implementer, you are simply not _allowed_ the freedom to
> use a convenient tool over the most efficient one. That is, to put it
> mildly, a disservice to users and a disgrace to the profession of
> programmers.
Well, optimization is probably good, but not always, I would say. If 
your app takes 0.001% less memory and works 0.001% faster then before in 
some certain configurations... Well, it's probably worthless, unless 
you've improved google search engine or something like that.

Qt is GUI framework. Not only, yes, but this is the main purpose. +/- 
10MB is almost nothing for GUI apps. Slightly faster lookup/insertions, 
cache line, proper alignment... Well, nice to have, but when an app 
spends most of the time on rendering something, it doesn't matter. 
Highly unlikely will it be a bottle neck.

The thing is, that we should keep in mind what kind of library Qt is. 
And also on what devices it runs.

I would rather have readable code than tiny bit optimized code, but much 
less readable. Simple and readable code => easy to maintain => easy to 
extend => easy to add new features. If you app is something for 
high-frequency trading or should run on devices with super limited 
resources, just don't use Qt containers. It's not appropriate tool for 
these cases.

I don't want to encourage people to write, for example, O(n^2) code 
instead of O(n). But if you want to "improve" something which is working 
more or less acceptable... Probably you should put your effort on 
something else.

On 6/6/19 9:05 AM, Mutz, Marc via Development wrote:
> On 2019-06-06 08:24, Joerg Bornemann wrote:
>> On 6/5/19 5:49 PM, Mutz, Marc via Development wrote:
>>
>>> As a library implementer, you are simply not _allowed_ the freedom to
>>> use a convenient tool over the most efficient one. That is, to put it
>>> mildly, a disservice to users and a disgrace to the profession of
>>> programmers. 8KiB just to look up a pointer in a map of {string, int}?
>>> That's 1/4th of the icache size of many processors!
>> [...]
>>
>> While I agree with this in general... every time we use a sorted vector
>> as a dictionary replacement we're scattering implementation details all
>> over the place, creating code that's much harder to read and easier to
>> make mistakes in (*).
>>
>> Maybe it's time for a general purpose dictionary class based on a sorted
>> vector?
>
> FTR: More of the same: 
> https://codereview.qt-project.org/c/qt/qtbase/+/264128 and 
> https://codereview.qt-project.org/c/qt/qtbase/+/264129
>
> I very strongly object to the notion that a find_if or lower_bound is 
> harder to read. More code does _not_ equate to less readable, as Qt 
> over and over has shown. There are different patterns involved than in 
> using Qt containers, sure, and by all means, if find_if frightens you, 
> then use a raw for loop, but this stuff is not rocket science. And 
> depending on how you define 'mistakes', it's just as easy to make a 
> mistake by forgetting qAsConst() on a Qt container than it is to, say, 
> combine iterators from different containers.
>
> As for QSortedVector/QFlatMap. There's a reason there's none in the 
> std, yet, and it has to do with when to sort. In one of the patches 
> above, we don't need to sort at all, because there're only ever O(10) 
> elements in there. Sorting, as performed by a QFlatMap would be 
> overkill there. In another, we don't even store the key, as it's equal 
> to the position of the element in the array. Sorting the key would be 
> nonsense. Oftem, you populate the data structure once and then only 
> perform lookups. In that case, a QFlatMap would waste time sorting 
> while you don't need it. So, yes, by all means, let's have a QFlatMap, 
> but it would just be another over-complicated container that people 
> misuse. Let's, as a community, learn how to use a raw vector (or 
> array) first, then introduce convenience.
>
> Don't pick a container by it's API. Pick it by how you use it. No-one 
> would use a RB tree for O(10) items if he had to implement it himself. 
> You wouldn't even implement one for O(1M) elements if insertions in 
> the middle are very infrequent. You are CS engineers. What would Knuth 
> say if he caught you using a RB tree with a static maximum of 10 
> entries? There's a reason for this. It's horribly slow, and only used 
> because in very limited circumstances, evenry other container is 
> _even_ slower. It's a very, very, complex beast. Just because the 
> compiler writes it for you at nothing more than a mention of 
> QMap, doesn't mean it's less complex. And that complexity doesn't 
> go away just because you wrap it in a nice API: the compiler has a 
> hard time with it, and so does the CPU, as evidenced by the O(KiB) 
> savings involved in each replacement of a QMap with a vector. Let's 
> also not forget the memory overhead: a QMap uses at least 24 
> bytes of of storage per element. Plus allocation overhead. Some 
> platforms (Windows? At some point 

Re: [Development] Views

2019-06-06 Thread Philippe
I second your use of sorted vectors, especially for small ones.

However, a key to master code complexity is to be able to easily recognize 
abstractions.
This reduces cognitive load when dealing with code. Generally Qt shines here.

A potential QDictionnary would speak to a reader more directly than
'std::vector + std::lower_bound' etc.
simply because QDictionnary would be more of an abstraction.

Philippe

On Thu, 06 Jun 2019 09:05:31 +0200
"Mutz, Marc via Development"  wrote:

> On 2019-06-06 08:24, Joerg Bornemann wrote:
> > On 6/5/19 5:49 PM, Mutz, Marc via Development wrote:
> > 
> >> As a library implementer, you are simply not _allowed_ the freedom to
> >> use a convenient tool over the most efficient one. That is, to put it
> >> mildly, a disservice to users and a disgrace to the profession of
> >> programmers. 8KiB just to look up a pointer in a map of {string, int}?
> >> That's 1/4th of the icache size of many processors!
> > [...]
> > 
> > While I agree with this in general... every time we use a sorted vector
> > as a dictionary replacement we're scattering implementation details all
> > over the place, creating code that's much harder to read and easier to
> > make mistakes in (*).
> > 
> > Maybe it's time for a general purpose dictionary class based on a 
> > sorted
> > vector?
> 
> FTR: More of the same: 
> https://codereview.qt-project.org/c/qt/qtbase/+/264128 and 
> https://codereview.qt-project.org/c/qt/qtbase/+/264129
> 
> I very strongly object to the notion that a find_if or lower_bound is 
> harder to read. More code does _not_ equate to less readable, as Qt over 
> and over has shown. There are different patterns involved than in using 
> Qt containers, sure, and by all means, if find_if frightens you, then 
> use a raw for loop, but this stuff is not rocket science. And depending 
> on how you define 'mistakes', it's just as easy to make a mistake by 
> forgetting qAsConst() on a Qt container than it is to, say, combine 
> iterators from different containers.
> 
> As for QSortedVector/QFlatMap. There's a reason there's none in the std, 
> yet, and it has to do with when to sort. In one of the patches above, we 
> don't need to sort at all, because there're only ever O(10) elements in 
> there. Sorting, as performed by a QFlatMap would be overkill there. In 
> another, we don't even store the key, as it's equal to the position of 
> the element in the array. Sorting the key would be nonsense. Oftem, you 
> populate the data structure once and then only perform lookups. In that 
> case, a QFlatMap would waste time sorting while you don't need it. So, 
> yes, by all means, let's have a QFlatMap, but it would just be another 
> over-complicated container that people misuse. Let's, as a community, 
> learn how to use a raw vector (or array) first, then introduce 
> convenience.
> 
> Don't pick a container by it's API. Pick it by how you use it. No-one 
> would use a RB tree for O(10) items if he had to implement it himself. 
> You wouldn't even implement one for O(1M) elements if insertions in the 
> middle are very infrequent. You are CS engineers. What would Knuth say 
> if he caught you using a RB tree with a static maximum of 10 entries? 
> There's a reason for this. It's horribly slow, and only used because in 
> very limited circumstances, evenry other container is _even_ slower. 
> It's a very, very, complex beast. Just because the compiler writes it 
> for you at nothing more than a mention of QMap, doesn't mean it's 
> less complex. And that complexity doesn't go away just because you wrap 
> it in a nice API: the compiler has a hard time with it, and so does the 
> CPU, as evidenced by the O(KiB) savings involved in each replacement of 
> a QMap with a vector. Let's also not forget the memory overhead: a 
> QMap uses at least 24 bytes of of storage per element. Plus 
> allocation overhead. Some platforms (Windows? At some point at least?) 
> didn't hand out heap in less than 64 bytes. That's 64 bytes of memory 
> for 8 bytes of payload. A vector uses exactly 8. So a map uses anywhere 
> between 3x and 8x more memory.
> 
> Just ask yourself: if you didn't have QMap/std::map or the hashed 
> versions, what data structure would you use? If the answer _actually_ is 
> "a RB tree (because I really need to insert and remove and lookup 
> roughly the same number of times", then fine, go use QMap. If it 
> _actually_ is "a hash table", then consider QHash/unorderd_map. Or maybe 
> an Open Addressing hash table would be better? BTW: with vector, you can 
> even implement a Heap (std::make/push/pop_heap).
> 
> There's no replacement for thinking here. There's no data structure that 
> will work best in all cases.
> 
> Thanks,
> Marc
> ___
> Development mailing list
> Development@qt-project.org
> https://lists.qt-project.org/listinfo/development


___
Development mailing list

Re: [Development] Views

2019-06-06 Thread Simon Hausmann

Am 06.06.19 um 09:05 schrieb Mutz, Marc via Development:
> On 2019-06-06 08:24, Joerg Bornemann wrote:
>> On 6/5/19 5:49 PM, Mutz, Marc via Development wrote:
>>
>>> As a library implementer, you are simply not _allowed_ the freedom to
>>> use a convenient tool over the most efficient one. That is, to put it
>>> mildly, a disservice to users and a disgrace to the profession of
>>> programmers. 8KiB just to look up a pointer in a map of {string, int}?
>>> That's 1/4th of the icache size of many processors!
>> [...]
>>
>> While I agree with this in general... every time we use a sorted vector
>> as a dictionary replacement we're scattering implementation details all
>> over the place, creating code that's much harder to read and easier to
>> make mistakes in (*).
>>
>> Maybe it's time for a general purpose dictionary class based on a sorted
>> vector?
>
> FTR: More of the same: 
> https://codereview.qt-project.org/c/qt/qtbase/+/264128 and 
> https://codereview.qt-project.org/c/qt/qtbase/+/264129
>
> I very strongly object to the notion that a find_if or lower_bound is 
> harder to read. More code does _not_ equate to less readable, as Qt 
> over and over has shown. There are different patterns involved than in 
> using Qt containers, sure, and by all means, if find_if frightens you, 
> then use a raw for loop, but this stuff is not rocket science. And 
> depending on how you define 'mistakes', it's just as easy to make a 
> mistake by forgetting qAsConst() on a Qt container than it is to, say, 
> combine iterators from different containers.
>
> As for QSortedVector/QFlatMap. There's a reason there's none in the 
> std, yet, and it has to do with when to sort. In one of the patches 
> above, we don't need to sort at all, because there're only ever O(10) 
> elements in there. Sorting, as performed by a QFlatMap would be 
> overkill there. In another, we don't even store the key, as it's equal 
> to the position of the element in the array. Sorting the key would be 
> nonsense. Oftem, you populate the data structure once and then only 
> perform lookups. In that case, a QFlatMap would waste time sorting 
> while you don't need it. So, yes, by all means, let's have a QFlatMap, 
> but it would just be another over-complicated container that people 
> misuse. Let's, as a community, learn how to use a raw vector (or 
> array) first, then introduce convenience.
>
> Don't pick a container by it's API. Pick it by how you use it. No-one 
> would use a RB tree for O(10) items if he had to implement it himself. 
> You wouldn't even implement one for O(1M) elements if insertions in 
> the middle are very infrequent. You are CS engineers. What would Knuth 
> say if he caught you using a RB tree with a static maximum of 10 
> entries? There's a reason for this. It's horribly slow, and only used 
> because in very limited circumstances, evenry other container is 
> _even_ slower. It's a very, very, complex beast. Just because the 
> compiler writes it for you at nothing more than a mention of 
> QMap, doesn't mean it's less complex. And that complexity doesn't 
> go away just because you wrap it in a nice API: the compiler has a 
> hard time with it, and so does the CPU, as evidenced by the O(KiB) 
> savings involved in each replacement of a QMap with a vector. Let's 
> also not forget the memory overhead: a QMap uses at least 24 
> bytes of of storage per element. Plus allocation overhead. Some 
> platforms (Windows? At some point at least?) didn't hand out heap in 
> less than 64 bytes. That's 64 bytes of memory for 8 bytes of payload. 
> A vector uses exactly 8. So a map uses anywhere between 3x and 8x more 
> memory.
>
> Just ask yourself: if you didn't have QMap/std::map or the hashed 
> versions, what data structure would you use? If the answer _actually_ 
> is "a RB tree (because I really need to insert and remove and lookup 
> roughly the same number of times", then fine, go use QMap. If it 
> _actually_ is "a hash table", then consider QHash/unorderd_map. Or 
> maybe an Open Addressing hash table would be better? BTW: with vector, 
> you can even implement a Heap (std::make/push/pop_heap).
>
> There's no replacement for thinking here. There's no data structure 
> that will work best in all cases.
>

You present very good technical arguments against the use of an RB tree 
in situations where it degrades code size and performance, which is 
something that I feel the majority of participants in this discussion 
agree with.


However I don't find your arguments that find_if/lower_bound is not 
harder to read convincing. I continue to agree with Joerg and Tor Arne 
and feel that the API of the associative containers results in code that 
is more compact, visually less noisy and consequently easier to read.


Simon

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Mutz, Marc via Development

On 2019-06-06 08:24, Joerg Bornemann wrote:

On 6/5/19 5:49 PM, Mutz, Marc via Development wrote:


As a library implementer, you are simply not _allowed_ the freedom to
use a convenient tool over the most efficient one. That is, to put it
mildly, a disservice to users and a disgrace to the profession of
programmers. 8KiB just to look up a pointer in a map of {string, int}?
That's 1/4th of the icache size of many processors!

[...]

While I agree with this in general... every time we use a sorted vector
as a dictionary replacement we're scattering implementation details all
over the place, creating code that's much harder to read and easier to
make mistakes in (*).

Maybe it's time for a general purpose dictionary class based on a 
sorted

vector?


FTR: More of the same: 
https://codereview.qt-project.org/c/qt/qtbase/+/264128 and 
https://codereview.qt-project.org/c/qt/qtbase/+/264129


I very strongly object to the notion that a find_if or lower_bound is 
harder to read. More code does _not_ equate to less readable, as Qt over 
and over has shown. There are different patterns involved than in using 
Qt containers, sure, and by all means, if find_if frightens you, then 
use a raw for loop, but this stuff is not rocket science. And depending 
on how you define 'mistakes', it's just as easy to make a mistake by 
forgetting qAsConst() on a Qt container than it is to, say, combine 
iterators from different containers.


As for QSortedVector/QFlatMap. There's a reason there's none in the std, 
yet, and it has to do with when to sort. In one of the patches above, we 
don't need to sort at all, because there're only ever O(10) elements in 
there. Sorting, as performed by a QFlatMap would be overkill there. In 
another, we don't even store the key, as it's equal to the position of 
the element in the array. Sorting the key would be nonsense. Oftem, you 
populate the data structure once and then only perform lookups. In that 
case, a QFlatMap would waste time sorting while you don't need it. So, 
yes, by all means, let's have a QFlatMap, but it would just be another 
over-complicated container that people misuse. Let's, as a community, 
learn how to use a raw vector (or array) first, then introduce 
convenience.


Don't pick a container by it's API. Pick it by how you use it. No-one 
would use a RB tree for O(10) items if he had to implement it himself. 
You wouldn't even implement one for O(1M) elements if insertions in the 
middle are very infrequent. You are CS engineers. What would Knuth say 
if he caught you using a RB tree with a static maximum of 10 entries? 
There's a reason for this. It's horribly slow, and only used because in 
very limited circumstances, evenry other container is _even_ slower. 
It's a very, very, complex beast. Just because the compiler writes it 
for you at nothing more than a mention of QMap, doesn't mean it's 
less complex. And that complexity doesn't go away just because you wrap 
it in a nice API: the compiler has a hard time with it, and so does the 
CPU, as evidenced by the O(KiB) savings involved in each replacement of 
a QMap with a vector. Let's also not forget the memory overhead: a 
QMap uses at least 24 bytes of of storage per element. Plus 
allocation overhead. Some platforms (Windows? At some point at least?) 
didn't hand out heap in less than 64 bytes. That's 64 bytes of memory 
for 8 bytes of payload. A vector uses exactly 8. So a map uses anywhere 
between 3x and 8x more memory.


Just ask yourself: if you didn't have QMap/std::map or the hashed 
versions, what data structure would you use? If the answer _actually_ is 
"a RB tree (because I really need to insert and remove and lookup 
roughly the same number of times", then fine, go use QMap. If it 
_actually_ is "a hash table", then consider QHash/unorderd_map. Or maybe 
an Open Addressing hash table would be better? BTW: with vector, you can 
even implement a Heap (std::make/push/pop_heap).


There's no replacement for thinking here. There's no data structure that 
will work best in all cases.


Thanks,
Marc
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-06 Thread Joerg Bornemann
On 6/5/19 5:49 PM, Mutz, Marc via Development wrote:

> As a library implementer, you are simply not _allowed_ the freedom to 
> use a convenient tool over the most efficient one. That is, to put it 
> mildly, a disservice to users and a disgrace to the profession of 
> programmers. 8KiB just to look up a pointer in a map of {string, int}? 
> That's 1/4th of the icache size of many processors!
[...]

While I agree with this in general... every time we use a sorted vector 
as a dictionary replacement we're scattering implementation details all 
over the place, creating code that's much harder to read and easier to 
make mistakes in (*).

Maybe it's time for a general purpose dictionary class based on a sorted 
vector?


Cheers,

Joerg

*: No, that's not because I'm confusing familiarity with simplicity. The 
patch in question illustrates that very clearly.
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-06-05 Thread Mutz, Marc via Development

On 2019-05-16 20:18, Mutz, Marc wrote:
[...]

[1] Paraphrasing what Alex Stepanov teaches in his A9 courses: No C
programmer would _ever_ get the idea to use a self-rebalancing
red-black tree for something that holds a dozen elements. Because once
you understand what is required to implement one, you'd shy away from
the sheer complexity. Yet, in C++, just typing QMap makes the compiler
do all that stuff for you. Don't use a map or a hash just because you
can and the API is convenient. Use it when it makes sense, given what
data is expected to be stored. And you will invariably end up with
using vectors all over the place. According to Stepanov, developers
wishing to use a map should seek a face-to-face meeting with their
manager to explain why they need it :)


If you ever needed more convincing than an Alex Stepanov quote:

https://codereview.qt-project.org/c/qt/qtwayland/+/264069

I repeat here what I said in the commit message, only stronger:

As a library implementer, you are simply not _allowed_ the freedom to 
use a convenient tool over the most efficient one. That is, to put it 
mildly, a disservice to users and a disgrace to the profession of 
programmers. 8KiB just to look up a pointer in a map of {string, int}? 
That's 1/4th of the icache size of many processors!


And I'm not git-blaming to look up who wrote that QMap in the first 
place. Qt is *full* of this stuff and you all should really understand 
one thing: It's not about _your_ convenience. You are working for your 
_users_. And this isn't rocket science. Almost _twenty_ years ago, Scott 
Meyers wrote in Effective STL: "Prefer to use a sorted vector".


Is this code performance-critical? Probably not. But ... I mean ... 8 
fscking Kilobytes. That's two pages that don't need to be paged in. 
Multiply that by a 100 or so uses of QMap in a normal Qt application and 
you see where this is going.


Please, think of yours truly what you want, but keep your _users_ in 
mind. Users who need to strip down Qt so it fits on their devices 
because ... well, because you were too lazy to pick the right data 
structure.


Thanks,
Marc
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-21 Thread André Pönitz
On Tue, May 21, 2019 at 04:41:42PM +0300, Danila Malyutin wrote:
> Exhibit C:
> 
> foo().contains(x)
> 
> https://godbolt.org/z/KlIcFc

-std=c++2a

But yes, I am aware of that, and I am perfectly happy with the tendency  
to chose practically sensible approaches in Standard C++ for a while now.

But please don't spoil this debate with evidence that certain people consider
"container.contains(X)" a sensible API.

Andre'

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-21 Thread André Pönitz
On Tue, May 21, 2019 at 08:32:07AM +0200, Mutz, Marc via Development wrote:
> 
> By that line of reasoning, the change from
> 
>Q3Slider *sl = new Q3Slider(0, 100, 50, 10, 1, this);
> 
> to
> 
>Q4Slider *sl = new Q4Slider(this);
>sl->setRange(0, 100);
>sl->setValue(50);
>sl->setPatheStep(10);
>sl->setStep(1);
> 
> was also wrong. I now need to check that the calls on the slider are always
> on the same object.

Right, but in this case most of the 'sl' are vertically aligned,
which makes them easily comparible. While that repetition is indeed
a minor nuisance it is more than compensated by the advantage of
having a name for the individual parameter. So overall, the Qt 4
version is much better, despite of the repetition.

This is also not a counter-argument to the STL containedness problem
we were "discussing" as the overall benefit of the Qt 4 version
are *not* due to the repetition, in fact it's there *despite* of
the repetition.

> You are confusing familiarity with simplicity.

I think I can perfectly decide myself what I confuse.

> It's simple that in the STL I can search for a value or a predicate
> condition at the change of just an '_if'. Container::contains(), OTOH,
> is just familiar (from previous Qt versions or other languages).

It's not familiarity, it's the natural question:

  "Container: Do you contain element X?"

vs

  "World: If I were to check all handles starting at something that's
  (sometimes...) a handle to a kind of 'first' element of this container
  (ignoring that you might be unordered, and having an order is something 
  that isn't natural for it), and check all elements refered to by those
  handles whether they equal X, would the algorithm I use return me
  something else that that exceptional (non-)handle that (also...)
  signifies "didn't really find it"?

So no: it's completely the other way round: I *am* familiar with the
Standard Library way to check for containedness, but it's *not simple*
and I am very well aware of the reasons I do not like it: It is a
ridiculously complex and superfluous stanza that leaks implementation
details of the underlying containers (e.g. having some kind of order,
even when the container nominally unordered).

It's something that I do not want to see and nobody should be 
required to use in "normal" code.

> QVector::contains() is not overloaded on QLatin1String, e.g.
> Std::find(), OTOH, will transparently use the QLatin1String, avoiding the
> creation of a temporary QString. 

And then what? A GUI application waiting for the next key press that
will happen 100ms later will spent 1 cycles on a 1GHz core for the
"useless" conversion?  There's *quite* some room until this gets even
close to being noticable.

> If contains() turns out to be a performance bottleneck in profiling,
> the user can't do anything about it and needs to go to the universal
> mechanism (std::find).

And if it turns out to be a bottleneck, code can be changed.
This happens, but it does not happen often. E.g. all those "wrong"
usages of QList do not appear in any profile of a Qt Creator run.

> This does not make the API simple to use. Maybe for people coming from other
> languages. It introduces two different ways to do essentially the same
> thing, advocating the ways that only works in a particular corner-case and
> refusing to show the universal way
> (https://doc.qt.io/qt-5/qvector.html#indexOf). But eventually, these
> developers _will_ need to search by a predicate, too, and then they will
> fall back to a raw loop, sometime,

Uhuh... raw loops! And that when you can clutter your code with all
those non-sensical unordered.begin() and unordered.end() iterators.
What a loss of laughableness!

Andre'
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-21 Thread Danila Malyutin
Exhibit C:

foo().contains(x)

https://godbolt.org/z/KlIcFc

пн, 20 мая 2019 г. в 23:14, André Pönitz :

> On Fri, May 17, 2019 at 10:17:10AM +0200, Mutz, Marc via Development wrote:
> > [...] There is no readability difference between the use of a Qt
> container and
> > that of an STL container.
>
> Exhibit A:
>
>  foo().contains(x)
>
>
> Exhibit B:
>
>  {
>  ... container = foo();
>  std::find(container.begin(), container.end(), x) !=
> container.end();
>  }
>
>
> Andre'
>
>
> ___
> Development mailing list
> Development@qt-project.org
> https://lists.qt-project.org/listinfo/development
>
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-21 Thread Eike Ziller


> On 21. May 2019, at 08:32, Mutz, Marc via Development 
>  wrote:
> 
> On 2019-05-20 23:43, André Pönitz wrote:
>> On Mon, May 20, 2019 at 11:23:13PM +0200, Mutz, Marc via Development wrote:
>>> On 2019-05-20 23:21, André Pönitz wrote:
>>> > > > Exhibit A:
>>> > > >
>>> > > >  foo().contains(x)
>>> > > >
>>> > > >
>>> > > > Exhibit B:
>>> > > >
>>> > > >  {
>>> > > >  ... container = foo();
>>> > > >  std::find(container.begin(), container.end(), x) !=
>>> > > > container.end();
>>> > > >  }
>>> > >
>>> > > And now do the same thing [...]
>>> >
>>> > No, I won't.
>>> >
>>> > You were claiming something universally valid (\forall x "There is
>>> > no difference ...")
>>> I never said that there's no difference. I said there's no difference in
>>> readability. Don't confuse familiarity with simplicity (or readability).
>> Indeed, you claimed only "no difference in readability".
>> But I wouldn't agree that there is "no difference in readabilty" between
>> Exhibit A and B above.
>> In case B one e.g. would need to check whether all _four_ occurances of
>> 'container' are actually the same. An issue that does not exist in case A.
> 
> By that line of reasoning, the change from
> 
>   Q3Slider *sl = new Q3Slider(0, 100, 50, 10, 1, this);
> 
> to
> 
>   Q4Slider *sl = new Q4Slider(this);
>   sl->setRange(0, 100);
>   sl->setValue(50);
>   sl->setPatheStep(10);
>   sl->setStep(1);
> 
> was also wrong. I now need to check that the calls on the slider are always 
> on the same object.

Readability is a thing of many aspects, so you cannot take a single aspect and 
use that to compare completely different pieces of code that do completely 
different things.

You’ll have to stay at the specific example and explain why there is “no 
difference in readability” in _that_ example.

> You are confusing familiarity with simplicity.

You are mixing together readability and (some definition of) simplicity.

> It's simple that in the STL I can search for a value or a predicate condition 
> at the change of just an '_if'. Container::contains(), OTOH, is just familiar 
> (from previous Qt versions or other languages). It's neither simple in the 
> sense that it would be universal (as find/find_if is) nor is it efficient: 
> QVector::contains() is not overloaded on QLatin1String, e.g. 
> Std::find(), OTOH, will transparently use the QLatin1String, avoiding the 
> creation of a temporary QString. If contains() turns out to be a performance 
> bottleneck in profiling,

> the user can't do anything about it and needs to go to the universal 
> mechanism (std::find).

Good. Use the API that is most readable for the use case.

> This does not make the API simple to use. Maybe for people coming from other 
> languages. It introduces two different ways to do essentially the same thing, 
> advocating the ways that only works in a particular corner-case and refusing 
> to show the universal way (https://doc.qt.io/qt-5/qvector.html#indexOf). But 
> eventually, these developers _will_ need to search by a predicate, too, and 
> then they will fall back to a raw loop, sometime, in the case of removing, 
> introducing quadratic complexity. Had the Qt API and the docs not lied to 
> them by permanently showing contains() without mentioning that it's but a 
> short-cut for a corner-case, but shown them std::find or std::remove instead, 
> the developer would have been empowered.

That is a nice suggestion on how to improve the documentation. Which doesn’t 
have much to do with readability or simplicity of the API.

> As-is, Container::contains() dumbs the novice down by telling him a 
> fairy-tale that isn't applicable to actual professional work.

And yet std maps and sets will have Container::contains in C++20.

-- 
Eike Ziller
Principal Software Engineer

The Qt Company GmbH
Rudower Chaussee 13
D-12489 Berlin
eike.zil...@qt.io
http://qt.io
Geschäftsführer: Mika Pälsi,
Juha Varelius, Mika Harjuaho
Sitz der Gesellschaft: Berlin, Registergericht: Amtsgericht Charlottenburg, HRB 
144331 B

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-21 Thread Marco Bubke


On 20/05/2019 23:11, André Pönitz wrote:
> On Mon, May 20, 2019 at 08:44:47PM +, Marco Bubke wrote:
>> On May 20, 2019 22:16:11 André Pönitz  wrote:
>>
>>> On Fri, May 17, 2019 at 10:17:10AM +0200, Mutz, Marc via Development wrote:
 [...] There is no readability difference between the use of a Qt container 
 and
 that of an STL container.
>>>
>>> Exhibit A:
>>>
>>>  foo().contains(x)
>>>
>>>
>>> Exhibit B:
>>>
>>>  {
>>>  ... container = foo();
>>>  std::find(container.begin(), container.end(), x) != 
>>> container.end();
>>>  }
>>
>> AFAIK contains is now part of the STL.
> 
> Define "now"...
> 
>> But to show a pattern I see often with Qt container is the use of contains 
>> and
>> then access the element with a key again. I that case the STL with iterators
>> leads you to better performing code. Ranges hopefully make much of this code
>> even more readable and performant.
> 
> Performance is always a combination of "raw run-time performance" and "time to
> market".

Yes, it is an economic decision too but there is not only "time to 
market" but "stay in the market" too. So you have be careful with your 
investments but if you do not invest enough you will loose too.

> There's no point in saving 30 processor cycles a day, even for a million 
> users,
> if that takes one hour of developer time to implement in a desktop 
> application.
> 
> People who disagree wouldn't ever touch Java or JS or any interpreted 
> language.
> Or std::ostream for that matter.
> 
> You know as well as I do that e.g. QList is heavily used in e.g. the Qt 
> Creator
> code base, and that this is absolutely *no* performance problem. Sure, it's 
> not
> used in *really* time-critical parts, but for the 100%-\epsilon 
> non-exceptional
> stuff it's just "good enough".
> 

I would agree that we have not much performance problems because most 
containers use only few entries but I ran in some. What I want to say is 
that there are solutions to that problem. For example with ranges you 
get readability and performance in many cases but if you are not 
familiar with that patter it looks strange. Very often the first 
reaction is to reject something because it looks unfamiliar as 
unreadable. Yes it is as you encounter it the first time but maybe it 
will be more readable in the long run.

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-21 Thread Konstantin Shegunov
On Tue, May 21, 2019 at 9:34 AM Mutz, Marc via Development <
development@qt-project.org> wrote:

> [...]
> This does not make the API simple to use.


Actually it does. Simple, as "easily understood or done" and
self-explanatory, which isn't the case for the Q3Slider's constructor. Yes,
familiarity plays a role in that, but doesn't conflict with simplicity.


> It introduces two different ways to do essentially the
> same thing


So? The standard does that too. Before the lambda from c++11 we implemented
that idiom as a function object. We had the tools to do it and it worked
just as well. It can still be done instead of using the shorthand syntax.
I, personally, have found it rather curious that each new revision of the
language claims more expressiveness and simplicity, while the STL on the
other hand is restricted to the box of "universality"; in the end there's
nothing more universal than a naked C-style array.


> advocating the ways that only works in a particular
> corner-case and refusing to show the universal way
>

To paraphrase: You're confusing universality with simplicity.


> Had the Qt API and the docs not lied to them by
> permanently showing contains() without mentioning that it's but a
> short-cut for a corner-case, but shown them std::find or std::remove
> instead, the developer would have been empowered.


I object to the "corner-case" description, otherwise I'm with you
(partially). There should be some promotion in the docs of the iterators,
for example with regards to find-and-erase vs. remove() (e.g. QHash, QMap).
Especially whenever you actually need to get the value before removing.


> As-is, Container::contains() dumbs the novice down by telling him a
> fairy-tale
> that isn't applicable to actual professional work.
>

Actually it doesn't. I continue to claim that contains() is a convenient
shorthand when you are only interested whether something has something,
which if I had to pull a number off thin air probably constitutes ~5% up to
~10% of the cases where you search. This doesn't qualify for an edge-case,
and most certainly doesn't exclude professional work.
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-21 Thread Mutz, Marc via Development

On 2019-05-20 23:43, André Pönitz wrote:
On Mon, May 20, 2019 at 11:23:13PM +0200, Mutz, Marc via Development 
wrote:

On 2019-05-20 23:21, André Pönitz wrote:
> > > Exhibit A:
> > >
> > >  foo().contains(x)
> > >
> > >
> > > Exhibit B:
> > >
> > >  {
> > >  ... container = foo();
> > >  std::find(container.begin(), container.end(), x) !=
> > > container.end();
> > >  }
> >
> > And now do the same thing [...]
>
> No, I won't.
>
> You were claiming something universally valid (\forall x "There is
> no difference ...")

I never said that there's no difference. I said there's no difference 
in
readability. Don't confuse familiarity with simplicity (or 
readability).


Indeed, you claimed only "no difference in readability".

But I wouldn't agree that there is "no difference in readabilty" 
between

Exhibit A and B above.

In case B one e.g. would need to check whether all _four_ occurances of
'container' are actually the same. An issue that does not exist in case 
A.


By that line of reasoning, the change from

   Q3Slider *sl = new Q3Slider(0, 100, 50, 10, 1, this);

to

   Q4Slider *sl = new Q4Slider(this);
   sl->setRange(0, 100);
   sl->setValue(50);
   sl->setPatheStep(10);
   sl->setStep(1);

was also wrong. I now need to check that the calls on the slider are 
always on the same object.


You are confusing familiarity with simplicity. It's simple that in the 
STL I can search for a value or a predicate condition at the change of 
just an '_if'. Container::contains(), OTOH, is just familiar (from 
previous Qt versions or other languages). It's neither simple in the 
sense that it would be universal (as find/find_if is) nor is it 
efficient: QVector::contains() is not overloaded on 
QLatin1String, e.g. Std::find(), OTOH, will transparently use the 
QLatin1String, avoiding the creation of a temporary QString. If 
contains() turns out to be a performance bottleneck in profiling, the 
user can't do anything about it and needs to go to the universal 
mechanism (std::find).


This does not make the API simple to use. Maybe for people coming from 
other languages. It introduces two different ways to do essentially the 
same thing, advocating the ways that only works in a particular 
corner-case and refusing to show the universal way 
(https://doc.qt.io/qt-5/qvector.html#indexOf). But eventually, these 
developers _will_ need to search by a predicate, too, and then they will 
fall back to a raw loop, sometime, in the case of removing, introducing 
quadratic complexity. Had the Qt API and the docs not lied to them by 
permanently showing contains() without mentioning that it's but a 
short-cut for a corner-case, but shown them std::find or std::remove 
instead, the developer would have been empowered. As-is, 
Container::contains() dumbs the novice down by telling him a fairy-tale 
that isn't applicable to actual professional work.


Thanks,
Marc
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-21 Thread Mutz, Marc via Development

On 2019-05-20 23:14, Konstantin Shegunov wrote:

On Mon, May 20, 2019 at 11:32 PM Mutz, Marc via Development
 wrote:


All I'm saying is that there are tons of examples (QGradient) where
the
use of an owning container in the API is just a very bad idea and
limits
the implementor's freedom and/or performance. E.g. QGradient could
have
inline storage for two or three stops to avoid allocating memory for
the
most-common cases. I mean, QPainter is full of (QPoint *, int
nPoints)
APIs that surely were added just for performance. Ditto for QString,

btw. Nowadays, with views, we can have the same API, but have it
accept
many owning containers transparently. I'm not saying that there must
be
no owning containers in the API. But there is a lot of low-hanging
fruit
out there.


Okay, I can live with that, and I do see why it'd make sense in some
cases to iterate the data directly. But then as a container can have
many different iterables, it seems reasonable to consider adding a
couple of methods that return views and take it from there. Why the
push to remove the owning container(s) API? In time it may prove
you're right, so then we can migrate the getters to the view API and
eventually deprecate these methods. Or they could coexist, or w/e. The
point is why reach for the top if there's low-hanging fruit?


You need to have an idea where you'd like to go before you go there. The 
problem with co-existence is that you impose the lowest common 
demoninator of both methods on the class implementation. If you have a 
view, the impl needs to store the data, if you have an owning container 
API, it needs to store it (assuming CoW) in that exact container. So, 
yes, co-existence as a path to the goal of no raw containers in APIs, 
but not as the end state.

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-20 Thread Bernhard Lindner

> There is no readability difference between the use of a Qt container and 
> that of an STL container. Don't confuse familiarity with 
> simplicity. 

That is true. You can get familiar with both, STL and foot fungus over time. 
But both will
remain disturbing forever ;-)

I used STL from time to time. And I found that it does not matter how often I 
used it...
it still remains hard to read. 

I mean, "pop_back" vs. "removeLast"?! Seriously?! "pop back" sounds funny but 
it is not
easy to read!

I case intuitive naming does not matter for you...
Then compare this thread/answer: https://stackoverflow.com/a/18549053/1421332
With this thread/answer: https://stackoverflow.com/a/421615/1421332
And, LOL, do not skip the comment below the first answer!

Nothing more to say.

-- 
Best Regards, 
Bernhard Lindner

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-20 Thread André Pönitz
On Mon, May 20, 2019 at 11:23:13PM +0200, Mutz, Marc via Development wrote:
> On 2019-05-20 23:21, André Pönitz wrote:
> > > > Exhibit A:
> > > >
> > > >  foo().contains(x)
> > > >
> > > >
> > > > Exhibit B:
> > > >
> > > >  {
> > > >  ... container = foo();
> > > >  std::find(container.begin(), container.end(), x) !=
> > > > container.end();
> > > >  }
> > > 
> > > And now do the same thing [...]
> > 
> > No, I won't.
> > 
> > You were claiming something universally valid (\forall x "There is
> > no difference ...")
> 
> I never said that there's no difference. I said there's no difference in
> readability. Don't confuse familiarity with simplicity (or readability).

Indeed, you claimed only "no difference in readability". 

But I wouldn't agree that there is "no difference in readabilty" between
Exhibit A and B above.

In case B one e.g. would need to check whether all _four_ occurances of
'container' are actually the same. An issue that does not exist in case A.

Andre'
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-20 Thread Mutz, Marc via Development

On 2019-05-20 23:21, André Pönitz wrote:
On Mon, May 20, 2019 at 10:48:29PM +0200, Mutz, Marc via Development 
wrote:

On 2019-05-20 22:18, André Pönitz wrote:
> On Fri, May 17, 2019 at 10:17:10AM +0200, Mutz, Marc via Development
> wrote:
> > [...] There is no readability difference between the use of a Qt
> > container and
> > that of an STL container.
>
> Exhibit A:
>
>  foo().contains(x)
>
>
> Exhibit B:
>
>  {
>  ... container = foo();
>  std::find(container.begin(), container.end(), x) !=
> container.end();
>  }

And now do the same thing [...]


No, I won't.

You were claiming something universally valid (\forall x "There is
no difference ...")


I never said that there's no difference. I said there's no difference in 
readability. Don't confuse familiarity with simplicity (or readability).



and when presented a counterexample you jumped
to a "but \exists "There is no difference ..." line of "reasoning".

This is a completely different statement.

Andre'
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-20 Thread André Pönitz
On Mon, May 20, 2019 at 10:48:29PM +0200, Mutz, Marc via Development wrote:
> On 2019-05-20 22:18, André Pönitz wrote:
> > On Fri, May 17, 2019 at 10:17:10AM +0200, Mutz, Marc via Development
> > wrote:
> > > [...] There is no readability difference between the use of a Qt
> > > container and
> > > that of an STL container.
> > 
> > Exhibit A:
> > 
> >  foo().contains(x)
> > 
> > 
> > Exhibit B:
> > 
> >  {
> >  ... container = foo();
> >  std::find(container.begin(), container.end(), x) !=
> > container.end();
> >  }
> 
> And now do the same thing [...]

No, I won't.

You were claiming something universally valid (\forall x "There is
no difference ...") and when presented a counterexample you jumped
to a "but \exists "There is no difference ..." line of "reasoning".

This is a completely different statement.

Andre'
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-20 Thread Konstantin Shegunov
On Mon, May 20, 2019 at 11:32 PM Mutz, Marc via Development <
development@qt-project.org> wrote:

> All I'm saying is that there are tons of examples (QGradient) where the
> use of an owning container in the API is just a very bad idea and limits
> the implementor's freedom and/or performance. E.g. QGradient could have
> inline storage for two or three stops to avoid allocating memory for the
> most-common cases. I mean, QPainter is full of (QPoint *, int nPoints)
> APIs that surely were added just for performance. Ditto for QString,
> btw. Nowadays, with views, we can have the same API, but have it accept
> many owning containers transparently. I'm not saying that there must be
> no owning containers in the API. But there is a lot of low-hanging fruit
> out there.
>

Okay, I can live with that, and I do see why it'd make sense in some cases
to iterate the data directly. But then as a container can have many
different iterables, it seems reasonable to consider adding a couple of
methods that return views and take it from there. Why the push to remove
the owning container(s) API? In time it may prove you're right, so then we
can migrate the getters to the view API and eventually deprecate these
methods. Or they could coexist, or w/e. The point is why reach for the top
if there's low-hanging fruit?
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-20 Thread André Pönitz
On Mon, May 20, 2019 at 08:44:47PM +, Marco Bubke wrote:
> On May 20, 2019 22:16:11 André Pönitz  wrote:
> 
> > On Fri, May 17, 2019 at 10:17:10AM +0200, Mutz, Marc via Development wrote:
> >> [...] There is no readability difference between the use of a Qt container 
> >> and
> >> that of an STL container.
> >
> > Exhibit A:
> >
> > foo().contains(x)
> >
> >
> > Exhibit B:
> >
> > {
> > ... container = foo();
> > std::find(container.begin(), container.end(), x) != container.end();
> > }
> 
> AFAIK contains is now part of the STL.

Define "now"...

> But to show a pattern I see often with Qt container is the use of contains and
> then access the element with a key again. I that case the STL with iterators
> leads you to better performing code. Ranges hopefully make much of this code
> even more readable and performant.

Performance is always a combination of "raw run-time performance" and "time to
market".

There's no point in saving 30 processor cycles a day, even for a million users,
if that takes one hour of developer time to implement in a desktop application.

People who disagree wouldn't ever touch Java or JS or any interpreted language.
Or std::ostream for that matter.

You know as well as I do that e.g. QList is heavily used in e.g. the Qt Creator
code base, and that this is absolutely *no* performance problem. Sure, it's not
used in *really* time-critical parts, but for the 100%-\epsilon non-exceptional
stuff it's just "good enough".

Andre'
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-20 Thread Mutz, Marc via Development

On 2019-05-20 22:18, André Pönitz wrote:
On Fri, May 17, 2019 at 10:17:10AM +0200, Mutz, Marc via Development 
wrote:
[...] There is no readability difference between the use of a Qt 
container and

that of an STL container.


Exhibit A:

 foo().contains(x)


Exhibit B:

 {
 ... container = foo();
 std::find(container.begin(), container.end(), x) != 
container.end();

 }


And now do the same thing when you look for a given property's value: 
[name](auto ) { return e.name(); }


This is called Selective Perception.

Here's another one:

Exhibit A:

for (auto &[key, value] : map)
use(key, value);

Exhibit B:

for (auto it = map.cbegin(), end = map.cend(); it != end; ++it)
use(it.key(), it.value());

Thanks,
Marc
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-20 Thread Marco Bubke
On May 20, 2019 22:16:11 André Pönitz  wrote:

> On Fri, May 17, 2019 at 10:17:10AM +0200, Mutz, Marc via Development wrote:
>> [...] There is no readability difference between the use of a Qt container 
>> and
>> that of an STL container.
>
> Exhibit A:
>
> foo().contains(x)
>
>
> Exhibit B:
>
> {
> ... container = foo();
> std::find(container.begin(), container.end(), x) != container.end();
> }

AFAIK contains is now part of the STL. But to show a pattern I see often with 
Qt container is the use of contains and then access the element with a key 
again. I that case the STL with iterators leads you to better performing code. 
Ranges hopefully make much of this code even more readable and performant.
>
>
>
>
> ___
> Development mailing list
> Development@qt-project.org
> https://lists.qt-project.org/listinfo/development

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-20 Thread Mutz, Marc via Development

On 2019-05-20 12:48, Lars Knoll wrote:

So you should give people the option to implement their 5% code that’s
performance critical in a fast way and make it as easy as possible for
them to implement the remaining 95%.


I fully agree. The problem is that Qt as a library doesn't know where 
these 5% are in a given user's code, so Qt needs to assume of any of its 
functions that it may become the bottleneck in _some_ user's 
application. One might need to parse megabytes of JSON, the other might 
want to create 1000s of UUIDs per second. If Qt has ineffcient APIs, 
then the user cannot fix her performance problem, or needs to do so 
using a library other than Qt. Only by providing efficient APIs do we 
empower the user to fix her performance problem, while staying in Qt.


While it can be reasonably expected that users will only create O(100) 
widgets, any such limits simply cannot be assumed on any container.


I already cited the QRegion problem where there were multiple instances 
of


if (r.rectCount() == 1) {
   use(r.boundingRect());
} else {
   for (auto rect : r.rects())
   use(rect);
}

Nobody writes code like that unless it's needed. This all went away when 
QRegion became iterable. Now


for (auto rect : r)
use(r);

is maximally performant for all states of QRegion, the user code is 
simpler, and all cases are faster than the fastest case before.


All I'm saying is that there are tons of examples (QGradient) where the 
use of an owning container in the API is just a very bad idea and limits 
the implementor's freedom and/or performance. E.g. QGradient could have 
inline storage for two or three stops to avoid allocating memory for the 
most-common cases. I mean, QPainter is full of (QPoint *, int nPoints) 
APIs that surely were added just for performance. Ditto for QString, 
btw. Nowadays, with views, we can have the same API, but have it accept 
many owning containers transparently. I'm not saying that there must be 
no owning containers in the API. But there is a lot of low-hanging fruit 
out there.


Thanks,
Marc
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-20 Thread Иван Комиссаров
C++ standart is a software and like any software, it has bugs.
It’s good that «auto_ptr» bug was fixed among with auto a {42};

However, reading the dev list it seems that people claim that *everything* that 
is done by the Committee is a bug and there’s only the «Qt way» of doing things 
like it was back in Qt4 days.

If Qt wants to stay alive, it should adopt to the changes in C++ where 
reasonable. Sorry, I can’t buy an argument «we should always return a copy of a 
container because someday somewhere in KDE was a bug and the copy helped to 
solve it». Why we should force the way of doing things for the 1% case? Maybe 
we should force the way suitable for 99% cases and solve that 1% case in the 
other way? Like add a new function foo2 with new signature?

> 20 мая 2019 г., в 22:10, André Pönitz  написал(а):
> 
> At some time The Commitee decided to standardize auto_ptr, but not 
> {shared,unique,...}_ptr. People calling auto_ptr unusable for most
> practical purposed were chastised for not seeing the light. A while
> later The Committee changed their opinion...
> 
> Andre'
> ___
> Development mailing list
> Development@qt-project.org
> https://lists.qt-project.org/listinfo/development

What’s wrong with

qFind(foo(), x);

? I actually have a strong feeling that Ranges will solve that problem too 
adding something like std::find(Range, T value);

Having std::begin(), std::visit() and std::get() it doesn’t seem that bad idea 
to have a free functions for *everything*

If someone don’t like the std::vector::empty() method, he can use qIsEmpty(T) 
function.

Problem solved?

> 20 мая 2019 г., в 22:18, André Pönitz  написал(а):
> 
> 
> Exhibit A:
> 
> foo().contains(x)
> 
> 
> Exhibit B:
> 
> {
> ... container = foo();
> std::find(container.begin(), container.end(), x) != container.end();
> }
> 
> 
> Andre'
> 
> 
> ___
> Development mailing list
> Development@qt-project.org
> https://lists.qt-project.org/listinfo/development

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-20 Thread André Pönitz
On Fri, May 17, 2019 at 10:17:10AM +0200, Mutz, Marc via Development wrote:
> [...] There is no readability difference between the use of a Qt container and
> that of an STL container.

Exhibit A:

 foo().contains(x)


Exhibit B:

 {
 ... container = foo();
 std::find(container.begin(), container.end(), x) != container.end();
 }


Andre'


___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-20 Thread André Pönitz
On Fri, May 17, 2019 at 07:47:55AM +0200, Mutz, Marc via Development wrote:
> On 2019-05-16 23:41, Konstantin Shegunov wrote:
> > you end up where the STL is - so convoluted it's hardly worth making
> > anything with it.
> 
> Qt is a C++ library. If you don't like C++, either stay in QML or use Java.

"Qt is a C++ library, so you have to use all of C++, if you don't, you
cannot use Qt".

Does not make sense.

> No-one uses C++ unless they need the extra performance.

That's plainly wrong as well.

C++ can very well be used as a general purpose, convenient cross-platform
programming language that can be used in a way to get raw-metal performance
_when needed_. That's not true for the alternatives you mentioned, not does
that mean that one needs that performance in each and every line of code.

> It is not Qt's job to change the decisions made by the C++ standards
> committee. If you want to change the STL, submit a paper to WG21, not rant
> on a Qt mailing-list.

At some time The Commitee decided to standardize auto_ptr, but not 
{shared,unique,...}_ptr. People calling auto_ptr unusable for most
practical purposed were chastised for not seeing the light. A while
later The Committee changed their opinion...

> Thanks,

Not for that.

Andre'
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-20 Thread Lars Knoll
> On 17 May 2019, at 21:12, Giuseppe D'Angelo via Development 
>  wrote:
> 
> Il 17/05/19 16:46, Bernhard Lindner ha scritto:
>>> I've done this experiment for QMap / QHash / QSet, where keeping COW at
>>> the cost of an extra indirection (dptr -> [refcount + std:: class] ->
>>> actual data) is more acceptable since these classes jump all over the
>>> memory anyhow. Basically "it worked", still requiring a few changes
>>> though, e.g. std::unordered_map iterators are forward, QHash ones are
>>> bidirectional. If the SIC is acceptable, something to consider for Qt 6.
>> Are there any plans/discussions how to procede with that experiment?
> 
> It was worth a try after we discussed this possibility a couple of years ago 
> at QtCS. I don't know if it's still interesting to pursue.

I’ve tried the same thing and it seems possible to implement this in a more or 
less source compatible way. One problem with QMap/QHash is the insertMulti() 
functionality and the fact that hash and multi_hash are not two separate types. 
But that is something I would very much like to deprecate in Qt 5.15 already 
(by deprecating insertMulti()).

Cheers,
Lars

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-20 Thread Lars Knoll
> On 17 May 2019, at 07:47, Mutz, Marc via Development 
>  wrote:
> 
> On 2019-05-16 23:41, Konstantin Shegunov wrote:
>> you end up where the STL is - so convoluted it's hardly worth making
>> anything with it.
> 
> Qt is a C++ library. If you don't like C++, either stay in QML or use Java. 
> No-one uses C++ unless they need the extra performance.

That might be true for some people, but certainly not for everybody.

Qt has always had a somewhat different philosophy. Make C++ easy to use, no 
need to use Java. The fact is that 95% of the source code our users write will 
not be performance critical. You don’t want to make the pay the price of having 
a difficult to use API for those 95% of the code. 

That making expensive operations hard to use will lead to more performant code 
is something I don’t buy. A hard to use API will instead lead to programming 
mistakes and will simply lead to slower speed in implementing the features 
required.

So you should give people the option to implement their 5% code that’s 
performance critical in a fast way and make it as easy as possible for them to 
implement the remaining 95%.

> It is not Qt's job to change the decisions made by the C++ standards 
> committee. If you want to change the STL, submit a paper to WG21, not rant on 
> a Qt mailing-list.

It’s not. But it’s also not that we have to simply follow any decision the 
standards committee does. Design philosophies and priorities may differ and 
lead to different decisions.

Cheers,
Lars



___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-17 Thread Mutz, Marc via Development

On 2019-05-17 19:47, Scott Bloom wrote:
[...]

Im just going to throw out my 2 bits on this

Please don’t underestimate (and Im not hearing Thiago say this) the
pain, of breaking source compatibility.  Even on Major (5->6) version
changes.


[...]QCanvas[...]QWebKit[...]


When the Qt team, decides to make these changes, it hurts a lot of
developers, who have to justify to their company, I need to spend X
number of months figuring out a solution, to replicate code that was
already working fine...


These are real pain points, yes, because higher-level features, for 
which there are no replacements, have been remove from the core domain 
of Qt: UIs.


I fully agree with you on that one.


From a utopic point of view, Id be fine with, if every Qt container,
and class that has been "mostly" implemented in STL, or the native
language was thrown out.. But as I tell my employees, just because its
in the language now, doesn’t mean we should go through our 2.5 million
lines of code, and re-write every one to use modern C++...


I disagree here with you here, though. You have had nine years now for 
realising that QList is a bad container to use in your code


From 
https://marcmutz.wordpress.com/2010/07/29/sneak-preview-qlist-considered-harmful/ 
(2010):



Run, don’t walk, and fix your new API to not use QList,
or mark your new types as movable (details are in the
patch). Alas, both changes are binary incompatible, so
you can’t do them if you need your code to stay BC.
This might be one of the reasons why QPair and QVector
aren’t “fixed” yet: doing so would change the layout
of the QList instantiated with them :(.

But, at least for new code, there’s no excuse anymore:
Just apply the patch.


You've had anywhere between eight years to manually and now to 
automatically run clang-tidy on your code to port at least those 
variables that name QList to auto, isolating you from the fallout that a 
QList removal would have. If you still use QList in your code today, 
then, I'm sorry, it's your own fault. You follow the development list, 
so the same is true for Q_FOREACH, for you.


You can also use the Qt containers, but restrict yourself to the 
STL-compatible subset of the API. And then the transition is as easy as 
s/QVector/std::vector/. That has been possible since Qt 3.0.


So, this case differs greatly from the two instances of feature removal 
you mentioned above in that you had literally years of time to prepare a 
coding style that would all but isolate you from the exact type of 
container used. The STL containers exist in standard form since 1998, 
and since then you had time to port your own code away from Qt 
containers, further isolating you from one of the most 
code-churn-producing subsystems of Qt: containers. If you've been with 
Qt since Qt 3 or Qt 2, you know what I mean. And if you have not learned 
from Qt 2 -> Qt 3 or Qt 3 -> Qt 4 w.r.t. to containers, then - sorry - 
again: your own fault. Had you ported to STL, your code would stay 
unchanged.


I'm playing devil's advocate here. In reality, yes, I want the rebase of 
Qt onto modern C++, for a great many reasons, but I'm also always 
looking for a way how to do that without disruptive changes. But that 
requires that Qt users compile with deprecated warnings enabled and fix 
their code small steps at a time. There are not many libraries that keep 
SC for so long as Qt does. But very long is not forever, and change will 
come one way or another. The good news is that C++11 allows you to 
insulate your code in many ways (auto, unordered_*), and this is 
precisely why we can now take this step.



To replace out every container, that works today?  And in the process,
break probably billions of lines of existing Qt code, which would have
to be re-written using the new containers???  Please don’t  Even
for 6.0...  Some form of transition would be great.


Upon reading the recent mails in this thread, one could have noticed 
that this whole subthread started with an unrelated topic: _not_ making 
QList an alias to QVector. I'd prefer the discussion to pick up on that 
technical point, even though I appreciate that it's easier to just 
generally vent FUD in a bike-shedding frenzy than to seriously consider 
technical issues such as how we can remove QList with minimal 
disruption.


@all:
I will no longer reply to the Views subthread, because it has gone 
off-track, as usual. Please give your valued input on a way forward 
regarding QList removal (QList subthread).


Have a nice weekend,
Marc
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-17 Thread Scott Bloom
Fair enough.. 

But I will say.. all too often.. theory becomes practice
--

Please note that nobody said «we are removing Qt containers in Qt6». At least, 
I don’t have that information.

The discussion is mostly about a *theoretical* case when the implementation of 
a *theoretical* method in a *theoretical* class may *theoretically* change and 
how far we should go to support that *theoretical* change. Or should not =)

It’s been said that Qt6 will be mostly source-compatible with Qt5.

PS: there’s been a discussion about killing QList but it is not clear how to do 
so without breaking half of the world (i.e. no final decision so far) and this 
discussion started long time ago, so you've had (and still have plenty of) time 
to revisit usages of QList in your codebase and replace it with more 
appropriate container.

> 17 мая 2019 г., в 19:47, Scott Bloom  написал(а):
> 
> Maybe, line in the Qt3->4 transition timeframe, have a macro, to "Allow Qt 
> Containers", as well as code that does the autoconversion from Qt to STL, so 
> developer code builds when the flag is on.
> 
> Scott
> ___
> Development mailing list
> Development@qt-project.org
> https://lists.qt-project.org/listinfo/development

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-17 Thread Giuseppe D'Angelo via Development

Il 17/05/19 16:46, Bernhard Lindner ha scritto:

I've done this experiment for QMap / QHash / QSet, where keeping COW at
the cost of an extra indirection (dptr -> [refcount + std:: class] ->
actual data) is more acceptable since these classes jump all over the
memory anyhow. Basically "it worked", still requiring a few changes
though, e.g. std::unordered_map iterators are forward, QHash ones are
bidirectional. If the SIC is acceptable, something to consider for Qt 6.

Are there any plans/discussions how to procede with that experiment?


It was worth a try after we discussed this possibility a couple of years 
ago at QtCS. I don't know if it's still interesting to pursue.


Thanks,
--
Giuseppe D'Angelo | giuseppe.dang...@kdab.com | Senior Software Engineer
KDAB (France) S.A.S., a KDAB Group company
Tel. France +33 (0)4 90 84 08 53, http://www.kdab.com
KDAB - The Qt, C++ and OpenGL Experts



smime.p7s
Description: Firma crittografica S/MIME
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-17 Thread Иван Комиссаров
Please note that nobody said «we are removing Qt containers in Qt6». At least, 
I don’t have that information.

The discussion is mostly about a *theoretical* case when the implementation of 
a *theoretical* method in a *theoretical* class may *theoretically* change and 
how far we should go to support that *theoretical* change. Or should not =)

It’s been said that Qt6 will be mostly source-compatible with Qt5.

PS: there’s been a discussion about killing QList but it is not clear how to do 
so without breaking half of the world (i.e. no final decision so far) and this 
discussion started long time ago, so you've had (and still have plenty of) time 
to revisit usages of QList in your codebase and replace it with more 
appropriate container.

> 17 мая 2019 г., в 19:47, Scott Bloom  написал(а):
> 
> Maybe, line in the Qt3->4 transition timeframe, have a macro, to "Allow Qt 
> Containers", as well as code that does the autoconversion from Qt to STL, so 
> developer code builds when the flag is on.
> 
> Scott
> ___
> Development mailing list
> Development@qt-project.org
> https://lists.qt-project.org/listinfo/development

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-17 Thread Scott Bloom
On Friday, 17 May 2019 09:38:05 PDT Marco Bubke wrote:
> Thiago, you partially implying that BC is still needed but with 
> technologies like flatpak or snappy this will maybe not common use 
> case anymore. They provide even behaviour compatibility if you stay with the 
> same runtime.
> Something which is not provided by binary compability. I personally 
> think if the behaviour is changed it should not even compile anymore 
> so you can fix it easily.

Some level of compatibility is of course required, unless you're proposing we 
provide a certain level of bugfixing for ALL releases for a number of years. 
That is, if 6.2 isn't source-compatible with 6.1, then 6.1 needs to be 
supported for 3+ years with bugfixes for code that was ported to 6.1 but hasn't 
been ported further to 6.2.

If we're still keeping source compatibility but not binary, the problem is not 
as big as above. But it still exists if you're not in a position to recompile 
all modules (think third party's component).

--
Im just going to throw out my 2 bits on this

Please don’t underestimate (and Im not hearing Thiago say this) the pain, of 
breaking source compatibility.  Even on Major (5->6) version changes.

Qt lost a lot of momentum, but eventually gained it back, in the 3-4 
transition.  And it was more than just "the code didn’t compile" it was also, 
lost functionality that was take from 3, a hack added in 4.1 (missing in 4.0 
IIRC) and then fully replaced in 4.4.. And Im talking about the Graphics 
Scene/View...

We have a similar issue, even if it has been 2-3 years already, with the change 
in web viewer... I know of more than one project, including my product, that is 
stuck on an old version of Qt, simply because the new web view, is missing some 
functionality.  And building the old browser classes is a less than "wonderful" 
solution.

When the Qt team, decides to make these changes, it hurts a lot of developers, 
who have to justify to their company, I need to spend X number of months 
figuring out a solution, to replicate code that was already working fine...

From a utopic point of view, Id be fine with, if every Qt container, and class 
that has been "mostly" implemented in STL, or the native language was thrown 
out.. But as I tell my employees, just because its in the language now, doesn’t 
mean we should go through our 2.5 million lines of code, and re-write every one 
to use modern C++...

To replace out every container, that works today?  And in the process, break 
probably billions of lines of existing Qt code, which would have to be 
re-written using the new containers???  Please don’t  Even for 6.0...  Some 
form of transition would be great.

Maybe, line in the Qt3->4 transition timeframe, have a macro, to "Allow Qt 
Containers", as well as code that does the autoconversion from Qt to STL, so 
developer code builds when the flag is on.

Scott
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-17 Thread Thiago Macieira
On Friday, 17 May 2019 09:38:05 PDT Marco Bubke wrote:
> Thiago, you partially implying that BC is still needed but with technologies
> like flatpak or snappy this will maybe not common use case anymore. They
> provide even behaviour compatibility if you stay with the same runtime.
> Something which is not provided by binary compability. I personally think
> if the behaviour is changed it should not even compile anymore so you can
> fix it easily.

Some level of compatibility is of course required, unless you're proposing we 
provide a certain level of bugfixing for ALL releases for a number of years. 
That is, if 6.2 isn't source-compatible with 6.1, then 6.1 needs to be 
supported for 3+ years with bugfixes for code that was ported to 6.1 but 
hasn't been ported further to 6.2.

If we're still keeping source compatibility but not binary, the problem is not 
as big as above. But it still exists if you're not in a position to recompile 
all modules (think third party's component).

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel System Software Products



___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-17 Thread Marco Bubke
Thiago, you partially implying that BC is still needed but with technologies 
like flatpak or snappy this will maybe not common use case anymore. They 
provide even behaviour compatibility if you stay with the same runtime. 
Something which is not provided by binary compability. I personally think if 
the behaviour is changed it should not even compile anymore so you can fix it 
easily.

On May 17, 2019 17:08:28 Thiago Macieira  wrote:

> On Thursday, 16 May 2019 11:18:08 PDT Mutz, Marc via Development wrote:
>> > When you first design the class, sure. But 5 years later, you may have
>> > the
>> > data internally kept in a QMap or QHash, mapped to some other
>> > information. So
>> > your function that used to "return d->member;" now does
>> > "return d->member.keys();"
>>
>> Can you point out a Qt class where this was the case in the past?
>
> I'll have to look it up, but it has happened in the past and if not in Qt,
> then in one of the KDE libraries. The Library API Design Policy includes this
> particular point (don't return references) for a reason.
>
>> > Another case would be where you're keeping extra data in the internal
>> > structure and you need to filter that out before returning. Or the
>> > dual:
>> > augment with some implied data. The latter could be quite common if the
>> > class
>> > is not storing anything in the regular case, but synthesising it on
>> > demand for
>> > the benefit of the old API.
>>
>> This one is simple: Array of struct -> struct of arrays. Well-known
>> optimisation in the games industry.
>
> Sure, but if you returned a view of structs, how would you later make that
> view of structs work with your internally-stored struct of arrays?
>
>> > But only so long as each of those containers store lay the data out the
>> > same
>> > way in memory, which is not the case for my QMap example.
>>
>> You basically have a dichotomy: Either you have contiguous storage, in
>> which case you return pointers, or you have non-contiguous storage, in
>> which case you need some form of runtime-dispatch Iterator Pattern.
>
> Or you have a well-known storage pattern, in which case you don't return an
> array of pointers (which would need to be allocated anyway), but you return a
> means of finding those elements. That's what the containers do for you.
>
> So I don't have a problem returning a type that is cheap when you're designing
> the API, so long as you don't lock yourself into it if you later want to
> change. I don't see anything but actual containers here.
>
>> I don't think you'd ever come into a situation where you'd need to
>> switch from one to the other. If you think so, please provide an example
>> where this was necessary in the past.
>
> I'll look it up. Note that in hindsight all of those will look like bad
> design, but the point is that we didn't know any better when the design was
> first done.
>
>> > Two of your examples [QRegion, QGradient] basically return an internal
>> > structure, so I'm not seeing
>> > how they are relevant.
>>
>> How are they not relevant? Because the class basically _is_ a container?
>> Well, then see QAIM::roleNames(). Apart from the questionable design to
>> return a node-based associative container for the O(10) elements in
>> there, instead of a (view to a) sorted array of structs[1], it is a
>> prime example of how the API requires a particular implementation. I
>> don't remember whether it returns a QMap or a QHash, but either way, one
>> might want to return the other, down the road - or even depending on the
>> number of elements in the container, like QRegion does.
>
> I meant they are not good examples because they always return something that
> currently is stored in the d pointer. So there's no problem in changing them
> to return a view to that storage, since that storage does not go out of scope
> at function exit.
>
>> For an example of where roleNames() goes horribly wrong, see
>> QQmlListModel. Is has the data stored elsewhere and re-constructs a
>> QHash each time it's called. With a runtime iterator, it could probably
>> produce the values on the fly, and with a sorted array of {role, name}
>> it would allocate one block of memory per call, not O(n).
>
> I don't understand what you meant here. Are you advocating that the return
> type should have been different? What type would have helped?
>
> Or are you saying that if we had different tools internally, the
> implementation of QQmlListModel::roleNames could have been better?
>
> Either way, this is a very good example for why the return type mustn't be a
> reference or a non-owning container: the two sources for the function are not
> compatible with the return type.
>
>> > How would you implement this one with a view-based return?
>>
>> Glad you asked:
>>
>>  static constexpr QGradientStop defaultStops[] = {{0,
>> QColorLiterals::black}, {1, QColorLiterals::white}};
>>  return SomeView{std::begin(defaultStops), std::end(defaultStops)};
>>
>> Instead of the simple 

Re: [Development] Views

2019-05-17 Thread zoltan . lutor
My not (that) complex mobile app (game) used almost entirely QML/Javascript - 
but when I needed mutual exclusion/atomicity I have not figured out anything 
but going back to good, old C++...

And as mentioned below, wide variety of containers/datatypes, algorithms, etc...

So yes, perforrmance is one driver but not the only one...

Br,

Zoltan

Ps: if I happened to miss some QML/Javascript magic the helps solving mutual 
exclusion/atomicity, let me  know... ;)

On Friday, May 17, 2019, Philippe wrote:
> > No-one uses C++ unless they need the extra performance.
> 
> This is mostly right, though wide portability can be another reason.
> 
> This being said, that does not mean that every line of a C++ application
> needs to be optimized with CPU cycles in mind.
> In my experience, only restricted portions need to be optimized (desktop
> application developer here).
> 
> This is why I use Qt containers when I need convenience, and specialized
> containers when I need speed. And in that last case, that depend on the
> context (eg. there are a variery of map implementations, each one with some
> advantages).
> 
> If we had a magic stick to switch all Qt containers to the STL library
> containers, that would not prevent the need to use dedicated
> containers when speed really matters. Hence, I am fine with today Qt
> containers.
> 
> And today, I can quote an example of an important container that Qt
> provides but that C++20 does not (correct me if I am wrong):
> QVarLengthArray (even if, here again, they are faster implementations
> when one (rarely) need move semantics support).
> 
> Philippe
> 
> On Fri, 17 May 2019 07:47:55 +0200
> "Mutz, Marc via Development"  wrote:
> 
> > On 2019-05-16 23:41, Konstantin Shegunov wrote:
> > > you end up where the STL is - so convoluted it's hardly worth making
> > > anything with it.
> > 
> > Qt is a C++ library. If you don't like C++, either stay in QML or use 
> > Java. No-one uses C++ unless they need the extra performance.
> > 
> > It is not Qt's job to change the decisions made by the C++ standards 
> > committee. If you want to change the STL, submit a paper to WG21, not 
> > rant on a Qt mailing-list.
> > 
> > Thanks,
> > Marc
> > ___
> > Development mailing list
> > Development@qt-project.org
> > https://lists.qt-project.org/listinfo/development
> 
> 
> ___
> Development mailing list
> Development@qt-project.org
> https://lists.qt-project.org/listinfo/development
>
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-17 Thread Thiago Macieira
On Thursday, 16 May 2019 11:18:08 PDT Mutz, Marc via Development wrote:
> > When you first design the class, sure. But 5 years later, you may have
> > the
> > data internally kept in a QMap or QHash, mapped to some other
> > information. So
> > your function that used to "return d->member;" now does
> > "return d->member.keys();"
> 
> Can you point out a Qt class where this was the case in the past?

I'll have to look it up, but it has happened in the past and if not in Qt, 
then in one of the KDE libraries. The Library API Design Policy includes this 
particular point (don't return references) for a reason.

> > Another case would be where you're keeping extra data in the internal
> > structure and you need to filter that out before returning. Or the
> > dual:
> > augment with some implied data. The latter could be quite common if the
> > class
> > is not storing anything in the regular case, but synthesising it on
> > demand for
> > the benefit of the old API.
> 
> This one is simple: Array of struct -> struct of arrays. Well-known
> optimisation in the games industry.

Sure, but if you returned a view of structs, how would you later make that 
view of structs work with your internally-stored struct of arrays?

> > But only so long as each of those containers store lay the data out the
> > same
> > way in memory, which is not the case for my QMap example.
> 
> You basically have a dichotomy: Either you have contiguous storage, in
> which case you return pointers, or you have non-contiguous storage, in
> which case you need some form of runtime-dispatch Iterator Pattern.

Or you have a well-known storage pattern, in which case you don't return an 
array of pointers (which would need to be allocated anyway), but you return a 
means of finding those elements. That's what the containers do for you.

So I don't have a problem returning a type that is cheap when you're designing 
the API, so long as you don't lock yourself into it if you later want to 
change. I don't see anything but actual containers here.

> I don't think you'd ever come into a situation where you'd need to
> switch from one to the other. If you think so, please provide an example
> where this was necessary in the past.

I'll look it up. Note that in hindsight all of those will look like bad 
design, but the point is that we didn't know any better when the design was 
first done.

> > Two of your examples [QRegion, QGradient] basically return an internal
> > structure, so I'm not seeing
> > how they are relevant.
> 
> How are they not relevant? Because the class basically _is_ a container?
> Well, then see QAIM::roleNames(). Apart from the questionable design to
> return a node-based associative container for the O(10) elements in
> there, instead of a (view to a) sorted array of structs[1], it is a
> prime example of how the API requires a particular implementation. I
> don't remember whether it returns a QMap or a QHash, but either way, one
> might want to return the other, down the road - or even depending on the
> number of elements in the container, like QRegion does.

I meant they are not good examples because they always return something that 
currently is stored in the d pointer. So there's no problem in changing them 
to return a view to that storage, since that storage does not go out of scope 
at function exit.

> For an example of where roleNames() goes horribly wrong, see
> QQmlListModel. Is has the data stored elsewhere and re-constructs a
> QHash each time it's called. With a runtime iterator, it could probably
> produce the values on the fly, and with a sorted array of {role, name}
> it would allocate one block of memory per call, not O(n).

I don't understand what you meant here. Are you advocating that the return 
type should have been different? What type would have helped?

Or are you saying that if we had different tools internally, the 
implementation of QQmlListModel::roleNames could have been better?

Either way, this is a very good example for why the return type mustn't be a 
reference or a non-owning container: the two sources for the function are not 
compatible with the return type.

> > How would you implement this one with a view-based return?
> 
> Glad you asked:
> 
>  static constexpr QGradientStop defaultStops[] = {{0,
> QColorLiterals::black}, {1, QColorLiterals::white}};
>  return SomeView{std::begin(defaultStops), std::end(defaultStops)};
> 
> Instead of the simple solution shown here, what we'll more likely see is
> QVector::fromRawData(). Which is trying to retrofit a view onto an
> owning container. Yuck.

It's a price we pay for flexibility. No doubt that a view is much cheaper to 
constructor, pass and destruct. But it's also more limited.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel System Software Products



___
Development mailing list
Development@qt-project.org

Re: [Development] Views

2019-05-17 Thread Bernhard Lindner

> I've done this experiment for QMap / QHash / QSet, where keeping COW at 
> the cost of an extra indirection (dptr -> [refcount + std:: class] -> 
> actual data) is more acceptable since these classes jump all over the 
> memory anyhow. Basically "it worked", still requiring a few changes 
> though, e.g. std::unordered_map iterators are forward, QHash ones are 
> bidirectional. If the SIC is acceptable, something to consider for Qt 6.

Are there any plans/discussions how to procede with that experiment?

-- 
Best Regards
Bernhard Lindner

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-17 Thread Mutz, Marc via Development

On 2019-05-17 11:36, Philippe wrote:
[...]

QVarLengthArray
While it is true that there's no such container, it's even more true
that there will never be one. Because C++ made the allocators, which
back in the 90s were just a way to handle near and far pointers on 
older

architectures, fit for actually abstracting allocation.


I don't know why you say there will never be such a standard allocator.

[...]

That may be because I didn't :O

In fact, I'd expect that some of the BDE allocators will eventually make 
it into the standard.


What I don't expect is to have stuff like inline_vector in the standard, 
because it's easy to replace (with a few elements lost) by vector + pool 
allocator + char[] buffer.

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Views

2019-05-17 Thread Philippe
> I start wondering if it is possible to wrap the STL containers in Qt6 and 
> give them a
> nice, intuitive, Qt-like API while still providing full STL compatibility. I 
> am sure this
> has been evaluated. Are the results documented somewhere?

A few years ago my application was affected by a bug found on
std::vector MSVC and not CLang/XCode.

Therefore, for me this is not such a good idea, because for a
cross-platform application, I like the containers to behave exactly the
same. Both in terms of performances and potential bugs. I mean, the STL
provides a uniform interface, not a same implementation, according to
the compiler's supplied library.

Philippe

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


  1   2   >