Friday, March 13, 2020

Digest for comp.lang.c++@googlegroups.com - 25 updates in 4 topics

Maciej Sobczak <see.my.homepage@gmail.com>: Mar 13 12:46AM -0700

> Even WORST:
 
> What happens when the class is modified to have a new field?
 
Presumably that new field has some meaning that should not be neglected up-front.
 
> All the structured binding constructs have to be modified
 
And for some this is actually a feature, because without extremely costly review of existing code, the compiler will *automatically* tell you where are all the places that might require your attention. If neglecting the new field in any given place would result in a bug, you have all such potential places reported to you for free.
This is a similar reasoning to the capability of detecting that switch statements become incomplete when the new enumeration value is added to the enum type definition.
 
Interestingly:
Some people believe that having the "default" branch makes their code robust to such changes.
Others believe that it is the capability to detect *statically* that existing switch statements became incomplete and require attention makes their code even more robust.
 
Of course, there will be concrete examples for either way, but that's why it is good to have a choice *at the call site*.
So, if you want your code to be "robust" by making it indifferent to newly added fields, write your code that way.
But if you want your code to be "robust" by making it auto-detect structural changes and get your attention to potential problems, then write your code the other way.
 
I don't claim that any of these two definitions of "robust" is better, but I've seen real cases to support either one.
 
And I think that your actual problem is that you were given a choice. :-)
 
> All the tools have to be rewritten to accomodate
 
Yes, this is a disadvantage of introducing new features to the language.
But not all tools need to be rewritten - only those that want to stay competitive on the market. Or you also have a choice of standardizing on a smaller language subset, to stay with existing tools - this possibility was already discussed.
 
--
Maciej Sobczak * http://www.inspirel.com
"Öö Tiib" <ootiib@hot.ee>: Mar 13 09:40AM -0700

On Friday, 13 March 2020 01:14:10 UTC+2, jacobnavia wrote:
 
> Within the for statement the variables "city" and "population" will be
> bound automatically to the corresponding fields of the map.
 
> Cute isn't it?
 
No, doesn't compile, since necessary #includes are missing.
Someone posting this trash in anything-goes-newsgroup is fine,
but if it is really in book then burn it and use "Filipek" like
mild profanity.
 
The constructs like you seem to imply do not compile as well.
Try:
 
std::string city;
int population;
for (std::bind(city, population) : mapCityPopulation)
std::cout << city << ": " << population << '\n';
 
It does not parse, syntax error. Also you do not really post
what you would like to see so I'm confused what is your
suggestion.
jacobnavia <jacob@jacob.remcomp.fr>: Mar 13 12:27AM +0100

Consider:
 
auto f = foo();
 
What is "f"?
 
Ahhh you have to figure out the return type of foo() of course. Great,
there you go to your favorite IDE and try to jump to the correct
definition of the foo() method in the correct class with the correct
overload resolution...
 
Even worst... when you change the return type of foo() from type A to
type Z, all the "auto" constructs will continue to compile AUTOmatically
of course. Problem is, the type of "f" will have changed and that can
provoke incomprehensible compile time errors further down or even run
time errors in the form of access violation or whatever!
 
Wouldn't it be better to write:
 
TYPE_A F = foo();
 
????
 
If the return type of foo() changes, an easy to catch compile time error
will inform us that a change happened and that we have to revise the
code according to the new interface of foo().
 
Besides, the maintenance programmer doesn't need to figure out anything:
the type of "f" is there, for all to see.
 
WATCH THAT AUTO!
Jorgen Grahn <grahn+nntp@snipabacken.se>: Mar 13 12:27AM

On Thu, 2020-03-12, jacobnavia wrote:
> Consider:
 
> auto f = foo();
...
> Wouldn't it be better to write:
 
> TYPE_A F = foo();
 
> ????
 
Yes, sometimes. "How often should we use auto?" is a question that
has been discussed here several times. (By people who actually use
C++, want to use C++, and want to do it well.)
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Ian Collins <ian-news@hotmail.com>: Mar 13 01:57PM +1300

On 13/03/2020 12:27, jacobnavia wrote:
 
Overuse of ice cream is dangerous but we still use it...
 
WATCH THAT ICE CREAM!
 
--
Ian.
Cholo Lennon <chololennon@hotmail.com>: Mar 12 10:06PM -0300

On 3/12/20 8:27 PM, jacobnavia wrote:
> definition of the foo() method in the correct class with the correct
> overload resolution...
 
> Even worst... when you change the return type of foo() from type A to
 
I am completely agree with you. In my previous job I had the opportunity
to work with a very large C++14/17 project (EOS/WAX blockchains). The
temptation to use "auto" everywhere was big: easy to start using it, by
later I discovered that it was very awful to read and use the code,
especially when you don't have a good IDE (but surprise surprise, even
the good IDEs have serious problems with auto).
 
--
Cholo Lennon
Bs.As.
ARG
Daniel <danielaparker@gmail.com>: Mar 12 06:16PM -0700

On Thursday, March 12, 2020 at 8:57:31 PM UTC-4, Ian Collins wrote:
> On 13/03/2020 12:27, jacobnavia wrote:
 
> Overuse of ice cream is dangerous but we still use it...
 
Indeed, but it would be nice if it _could_ be used safely everywhere,
irrespective of whether we chose to use it. But it can't, it doesn't work when
functions return proxies.
 
Daniel
Bo Persson <bo@bo-persson.se>: Mar 13 03:17AM +0100

On 2020-03-13 at 00:27, jacobnavia wrote:
> Consider:
 
> auto f = foo();
 
> What is "f"?
 
Easy, "f" is the return value of foo(). Probably some kind of iterator
that you are just going to pass to one or more std::algorithm, so you
don't really care to spell out its name.
 
 
> time errors in the form of access violation or whatever!
 
> Wouldn't it be better to write:
 
> TYPE_A F = foo();
 
 
You mean like
 
typename std::unordered_map<key, data, std::hash<key>,
std::equal_to<key>, special_allocator<std::pair<const key,
data>>>::const_iterator F = foo();
 
 
Bo Persson
Ian Collins <ian-news@hotmail.com>: Mar 13 04:17PM +1300

On 13/03/2020 14:16, Daniel wrote:
 
> Indeed, but it would be nice if it _could_ be used safely everywhere,
> irrespective of whether we chose to use it. But it can't, it doesn't work when
> functions return proxies.
 
Ice cream always works!
 
--
Ian.
Daniel <danielaparker@gmail.com>: Mar 12 08:48PM -0700

On Thursday, March 12, 2020 at 11:17:55 PM UTC-4, Ian Collins wrote:
 
> Ice cream always works!
 
Just so.
jacobnavia <jacob@jacob.remcomp.fr>: Mar 13 08:51AM +0100

Le 13/03/2020 à 03:17, Bo Persson a écrit :
 
> typename std::unordered_map<key, data, std::hash<key>,
> std::equal_to<key>, special_allocator<std::pair<const key,
> data>>>::const_iterator F = foo();
 
Well, I know that C++ can be very unreadable. Maintaining C++ can be a
nightmare, but yes, I would prefer that long declaration since I know
that at the end f should be a const_iterator (if I parsed that correctly
from the template forest there).
"Öö Tiib" <ootiib@hot.ee>: Mar 13 01:14AM -0700

On Friday, 13 March 2020 04:18:06 UTC+2, Bo Persson wrote:
 
> typename std::unordered_map<key, data, std::hash<key>,
> std::equal_to<key>, special_allocator<std::pair<const key,
> data>>>::const_iterator F = foo();
 
That seems to be one of main annoyances with C++. Compiler diagnostics,
debuggers and smart code editors will talk something like that about
generically constructed types used.
 
So I usually suggest to be helpful by using typedefs when constructing
such types:
 
using KeyData = std::pair<const Key, Data>;
using KeyDataAlloc = special_allocator<KeyData>;
using MapKeyToData = std::unordered_map<Key, Data, std::hash<Key>
, std::equal_to<Key>, KeyDataAlloc>;
 
Same way MapKeyToData::const_iterator can be declared if it is
type of important citizens in code. Then that "poo" can be declared as;
 
MapKeyToData::const_iterator poo();
 
Going "auto poo();" here feels already deliberate waste of readers time
even when the usual "poo" has more descriptive name.
Now that voids your example since the question becomes between:
 
auto p = poo();
 
MapKeyToData::const_iterator p = poo();
 
It can be clear enough with auto and also lot of code viewing tools
let to one-click navigate to declaration of that "poo" when unsure.
David Brown <david.brown@hesbynett.no>: Mar 13 11:07AM +0100

On 13/03/2020 00:27, jacobnavia wrote:
 
> Besides, the maintenance programmer doesn't need to figure out anything:
> the type of "f" is there, for all to see.
 
> WATCH THAT AUTO!
 
What is the point you are trying to make with these posts? That
features which are useful can also be misused? Welcome to reality -
this is nothing new, either in programming languages or any other aspect
of life.
 
Drinking a glass of water is a good idea. Sticking your head in a
bucket of water is a really bad idea. Appropriate use of something is
good, excessive use or abuse is bad. The same applies to using auto,
structured bindings, C macros, "if" statements, or Usenet.
 
If you don't like C++, don't use it. If you don't want to support it in
your tools, that's fine (and understandable - it would be a massive
effort). If you don't understand C++ or the purpose of its features
(this is apparent from your posts), either ask about it or drop it. But
please stop whining.
Bart <bc@freeuk.com>: Mar 13 10:39AM

On 13/03/2020 10:07, David Brown wrote:
>> the type of "f" is there, for all to see.
 
>> WATCH THAT AUTO!
 
> What is the point you are trying to make with these posts?
 
Frustration with the way this spectacularly complex language is going?
 
> effort). If you don't understand C++ or the purpose of its features
> (this is apparent from your posts), either ask about it or drop it. But
> please stop whining.
 
The consequences can perculate through even if you don't use the language.
 
I've experienced that extensively with C. Much less so with C++ but
largely because I don't even bother trying to use libraries with C++
interfaces, or trying to port or understand bits of software written in
C++, or attempting to build any open source code that uses C++.
 
Even using C, if someone wants to make use of VS for example, that IDE
is heavily C++-centric.
 
However it is fascinating seeing how the language is developing, how it
is totally incapable of taking a simple, straightforward approach to
anything. Rule number one: every new feature must be arcane.
Paavo Helde <myfirstname@osa.pri.ee>: Mar 13 01:53PM +0200

On 13.03.2020 1:27, jacobnavia wrote:
> Consider:
 
> auto f = foo();
 
> What is "f"?
 
Right, with a non-informative name like 'foo' auto should probably not
be used. Auto should be used only if it increases readability:
 
for (auto& ref: mycontainer) {/*...*/}
 
auto myThread = std::make_unique<std::thread>(MyThreadFunc, par1, par2);
 
etc.
David Brown <david.brown@hesbynett.no>: Mar 13 02:26PM +0100

On 13/03/2020 11:39, Bart wrote:
 
>>> WATCH THAT AUTO!
 
>> What is the point you are trying to make with these posts?
 
> Frustration with the way this spectacularly complex language is going?
 
If you don't like a language, don't use it. If you don't know a
language, either learn about it or keep quite about it - it is pointless
to come to a language forum and complain about it.
 
I know only a little Ruby - but from what I have seen, it is an
unusually ugly and unclear language. I have three choices. First, I
could just ignore it and use other languages. Second, I could put the
effort into studying it, learning it, writing code in it, and see if it
has advantages that outweigh my initial bad impression - after all, a
great many other people choose to use it. Or third, I could go to a
Ruby Usenet group and grumble about how terrible I think it is. Which
do you think is the smart choice?
 
With C, there is at least the vague excuse that as the lingua franca of
the software world, you often can't get entirely away from it even if
you don't like it. That does not apply to C++.
 
 
> However it is fascinating seeing how the language is developing, how it
> is totally incapable of taking a simple, straightforward approach to
> anything. Rule number one: every new feature must be arcane.
 
Some things in C++ are hard to understand. But it is orders of
magnitude harder to understand how some people have such a hatred for
things they are basically clueless about as a result of determined
wilful ignorance.
Daniel <danielaparker@gmail.com>: Mar 13 07:27AM -0700

On Friday, March 13, 2020 at 6:07:33 AM UTC-4, David Brown wrote:
> On 13/03/2020 00:27, jacobnavia wrote:
 
> If you don't like C++, don't use it.
 
On the contrary, jacobnavia has no reason to leave C++. jacobnavia is happy
with legacy C++, their unhappiness is related to an ISO standards committee
that is not limiting itself to standardizing existing practice, but seemingly
trying to morph it into a new language. But jacobnavia will always have
backwards compatible legacy C++.
 
It's those of us that _want_ C++ to become a modern language, and have
reservations where that's going, that have to also think about leaving. But
where to?
 
Daniel
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Mar 13 03:46PM

On 12/03/2020 23:27, jacobnavia wrote:
 
> If the return type of foo() changes, an easy to catch compile time error will inform us that a change happened and that we have to revise the code according to the new interface of foo().
 
> Besides, the maintenance programmer doesn't need to figure out anything: the type of "f" is there, for all to see.
 
> WATCH THAT AUTO!
 
auto is great: use almost everywhere .. with concepts it will be even better:
 
iterator i = foo();
 
/Flibble
 
--
"Snakes didn't evolve, instead talking snakes with legs changed into snakes." - Rick C. Hodgin
 
"You won't burn in hell. But be nice anyway." – Ricky Gervais
 
"I see Atheists are fighting and killing each other again, over who doesn't believe in any God the most. Oh, no..wait.. that never happens." – Ricky Gervais
 
"Suppose it's all true, and you walk up to the pearly gates, and are confronted by God," Byrne asked on his show The Meaning of Life. "What will Stephen Fry say to him, her, or it?"
"I'd say, bone cancer in children? What's that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery that is not our fault. It's not right, it's utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates a world that is so full of injustice and pain. That's what I would say."
Jorgen Grahn <grahn+nntp@snipabacken.se>: Mar 13 07:13AM

On Thu, 2020-03-12, Keith Thompson wrote:
>>> popen(), select() and fgets()?
 
>> Did you assume it's POSIX because I use "ps" and "grep"?
 
> Or you could have just answered the question. Is it only for POSIX?
 
He did, further down:
 
I'm working on embedded Linux right now (arm 32-bit) but I'd like
to be able to write this with Boost so that it works on lots of
systems.
 
Surely these "lots of systems" boil down to Windows -- I doubt there
are other non-POSIX systems where this Boost library works.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
James Kuyper <jameskuyper@alumni.caltech.edu>: Mar 13 07:24AM -0400

On 3/12/20 11:25 AM, Frederick Gotham wrote:
 
>> From looking at the code, this is only for POSIX? Then what's wrong with
>> popen(), select() and fgets()?
 
> Did you assume it's POSIX because I use "ps" and "grep"?
 
That's a reasonable assumption. "find" is also a clue, but explicit
mention of Linux is the easiest clue to follow.
 
I notice that, even with Keith prompting you to do so, you still haven't
bothered answering that question.
 
If the answer is "Yes", then popen(), select(), and fgets() together
make a much simpler solution to your problem then the one you've
created. And because it's simpler, it should be much easier to get it
actually working.
 
If the answer is "No", then could you explain what kind of non-POSIX
environment supports commands named "ps", "grep", and "find", and can be
accurately described as Linux?
cdalten@gmail.com: Mar 13 08:42AM -0700

On Friday, March 13, 2020 at 12:13:40 AM UTC-7, Jorgen Grahn wrote:
> systems.
 
> Surely these "lots of systems" boil down to Windows -- I doubt there
> are other non-POSIX systems where this Boost library works.
 
Not that I'm the programming grandmaster, but I have done some kind of programming on embedded Linux (arm 32 -bit). And in general, to get it to work on a lot of systems is vague. For example, if this were android, in order to get it to work on a lot of systems, he would have Java/XML and these have different builds for that target the minimum API levels.
 
If he wanted to wanted to this to also work on say, an iPhone, he would either have to use swift and maintain a few different builds. Otherwise, he would have to use HookerScript, I mean JavaScript, and then do some serious optimizations in order to get JavaScript to perform well as the native APIS on both Android and iPhone.
Jorgen Grahn <grahn+nntp@snipabacken.se>: Mar 13 12:35AM

On Thu, 2020-03-12, Paavo Helde wrote:
> be joined, meaning that your program is basically not able to guarantee
> a clean shutdown any more. Failing to join the threads properly is just
> sloppy programming.
 
And an extremely common flaw.
 
My gut feeling for threads is, you need to design thread lifetimes as
carefully as process lifetimes (for forked processes), and a worker
thread should probably accept a special work request that says "please
exit".
 
(But that gut feeling is just based on experience dealing with bad
designs. I avoid threads myself.)
 
> for terminating the program, this will kill it on spot without any
> cleanup of global statics etc, and so it should avoid any errors in the
> still running threads.
 
How about std::quick_exit()?
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Paavo Helde <myfirstname@osa.pri.ee>: Mar 13 09:11AM +0200

On 13.03.2020 2:35, Jorgen Grahn wrote:
>> If you still insist on having detached threads, I suggest to use _exit()
>> for terminating the program,
 
> How about std::quick_exit()?
 
Yes, that's the same as far as I can see.
Paavo Helde <myfirstname@osa.pri.ee>: Mar 13 09:15AM +0200

On 13.03.2020 2:35, Jorgen Grahn wrote:
> carefully as process lifetimes (for forked processes), and a worker
> thread should probably accept a special work request that says "please
> exit".
 
Not necessarily. If the thread is carrying out a specific task and will
terminate by itself after that, then all what's needed is to join it in
the main thread before ending the program. The join operation will just
wait until the worker thread is completed.
David Brown <david.brown@hesbynett.no>: Mar 13 10:56AM +0100

On 13/03/2020 08:15, Paavo Helde wrote:
> terminate by itself after that, then all what's needed is to join it in
> the main thread before ending the program. The join operation will just
> wait until the worker thread is completed.
 
It all depends on what kind of thread it is - a one-off thread that does
something and exits, or one that lives for a long time and has to be
told to die.
 
Outside of simple test examples, I don't think it is common to have
threads that just run a job then exit themselves (and can be cleared up
with a join). If you have work to do in parallel or in the background,
then a pool of worker threads is more useful and avoids the overhead of
creating and destroying threads. In that case, the final "task" you
send to each thread is "please exit".
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: