HI Thiago, On 15.11.22 17:33, Thiago Macieira wrote: > On Tuesday, 15 November 2022 01:42:55 PST Marc Mutz via Development wrote: >>> Returning as an iteratable interface requires that we return a proxy >>> object, like QRegularExpressionMatch, so that the solution is >>> thread-safe. This is neither simple to understand, to code, or to port >>> existing code over to. It also requires copying the data over (hopefully, >>> implicitly) to the proxy object, so it doesn't solve anything. >> >> I disagree on all points. QREM is complicated because we need to >> shoehorn a coroutine into an iterator concept. Same with >> QStringTokenizer. Coroutines with lazy sequences (generator<>) are very easy >> to implement and use. >> >> If we're to discuss further, please watch my Meeting C++ presentation, >> which lays out all the pros and cons I'm aware of. No need to re-iterate >> them in text here. https://youtu.be/tvdwYwTyrig > > It will take some time to watch it.
Thanks. 2× is about the right speed :) > In the meantime, I'd appreciate a short answer on how you return the keys from > a stored associative map, std::generator<Key> func() { for (auto &[key, value] : m_assoc_cont) co_yield key; } > in a thread-safe manner (such that if something in > the same thread or another thread-safely modifies that map, the original user > isn't affected). The above isn't thread-safe, it isn't even re-entrant, in the same way that iteration using iterators isn't. This is a known issue whenever you hand out references, and it's nothing that violates our const-is-thread-safe promise, otherwise static const QMap map = ~~~; // T1 map["x"].size(); would also be affected. The promise doesn't end when you return from the const member function, it extends to references handed out in the process (op[], begin, end, any lazy sequence). Of course, in special cases where you have the need for actual thread-safety, some form of owning container will be required. But then we're talking about maybe 0,1% of all APIs, if even that many. > Because you pointed to QStringTokenizer and that implicitly- > copies a QString. That's imprecise. QStringTokenizer extends rvalue lifetimes ("rvalue pinning") so's to make this safe: for (auto part : qTokenize(label->text(), u';')) even though the return value of label->text() would ordinarily be destroyed at the end of the full-expression, which, seeing the way ranged-for is specified: { auto && __range = qTokenize(label->text(), u';'); // would be here auto __begin = begin-expr(__range); auto __end = end-expr(__range); while (__begin != __end) { decl = *__begin; ++__begin; } } iow: too early. It does this only for rvalue owning containers, not for lvalues and not for views (!borrowed_range in C++20 ranges parlor). This has nothing to do with multi-threading. Thanks, Marc -- Marc Mutz <marc.m...@qt.io> Principal Software Engineer The Qt Company Erich-Thilo-Str. 10 12489 Berlin, Germany www.qt.io Geschäftsführer: Mika Pälsi, Juha Varelius, Jouni Lintunen Sitz der Gesellschaft: Berlin, Registergericht: Amtsgericht Charlottenburg, HRB 144331 B _______________________________________________ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development