Thursday, June 28, 2018

Digest for comp.lang.c++@googlegroups.com - 20 updates in 2 topics

Juha Nieminen <nospam@thanks.invalid>: Jun 28 05:12AM


> I didn't see Boltar's comment because he's in my kill file.
 
> And you're pretty close now, again.
 
> Just a heads up.
 
You are going to killfile me because I'm quoting Bjarne Stroustrup?
David Brown <david.brown@hesbynett.no>: Jun 28 10:39AM +0200

On 27/06/18 22:54, Alf P. Steinbach wrote:
>> cases it is common enough - for the sort of usage you have here, it /is/
>> obscure.
 
> How can a single ?: be obscure?
 
It is a matter of how you use it - it is not the ?: operator itself that
is hard. "(a < b) ? b : a" is fine. Your monstrosity is not.
 
 
> Beginners learn it, very early on, and you say some experienced
> programmers you've encountered find it challenging?
 
Beginners learn the syntax for ?:, and then a fair proportion promptly
forget about it and don't use it in normal code. However, I don't claim
many programmers would find something like the "maximum" ?: example to
be difficult. I am saying that the code /you/ wrote, with it's unusual
syntax, its use of poorly-understood lifetime rules, and unhelpful
layout is obscure, hard to understand, and easy to get wrong.
 
Good code is /clear/. It is clear what the code does, and what the code
does not do. The layout should reflect the logic of the code.
 
As to what experienced programmers would think about it - just read the
replies you have got in this thread. There are plenty of experienced
C++ programmers here - none of them think this is a good way to write
code, several have asked what it does, and others have simply not
bothered to even try to figure it out. The most positive response you
got was from me - that it is an interesting experiment, but not
something for real code.
 
 
> I find that claim hard to believe.
 
I am not sure what your normal programming environment is - maybe you
write your code alone. You have a very odd style, and are perhaps a
poor judge of what other people find comfortable in their coding. In
any coding review I have seen, your typical c.l.c++ code would be
rejected outright - reviewers would assume it is obvious where the
problems lie.
 
This does not mean your code is wrong - or even that there is a problem
with your style. It means it is significantly different from normal
styles - enough to be difficult and error-prone for many people to
interpret, and enough to be seen as different merely for the sake of
being different or appearing clever. Personally, I think it is good
sometimes to see such variation, and it can help us all learn - but I
would hate to have to /work/ with your code.
 
 
To balance this, it is clear that all programmers have a style and a
view of "normal programming styles" that is heavily influenced by the
type of work they do. That applies to me as well as anyone else.
 
 
> evident, one expects such an expression to just compute a boolean value.
 
> But
 
> 1. it isn't /always/ bad to do that with boolean expressions, and
 
There are a few idioms that rely on non-execution of parts of
expression, like "p && foo(*p)". As a C or C++ programmer, you need to
be familiar with these sorts of things to understand other people's code.
 
That does not mean it is a good idea to /write/ them. And coding
standards that are concerned with quality code, ban them. Here are a
couple of rules from MISRA (yes, I know MISRA has its faults):
 
Rule 12.3: The comma operator should not be used.
 
Rule 13.5: The right hand operand of a logical && or || operator shall
not contain persistent side effects.
 
 
This allows things like "x = p && cos(p);", but not "p && printf(*p)".
The point is that if someone reads quickly over the code and assumes
that the right-hand operand is evaluated in some cases when it is not,
it does not affect the logic of the code.
 
 
Having said that, there can certainly be places where this kind of thing
/can/ be appropriate. Deep within library code, you sometimes need code
constructs that are unusual, complicated, or take a long time to
understand. There is plenty in the implementation of the C++ standard
library that is beyond the comprehension of most C++ programmers.
 
> 2. a choice expression isn't like a boolean expression.
 
It is in this sense.
 
> operations that indicate success/failure via boolean returns:
 
> // A. OK for me
> const bool success = a() and b() and c() and d() and e();
 
Functions called "a", "b", etc., are not okay for me in real code - they
would have longer names. So this would have to be spread across many
lines - not okay. And real code would likely have parameters, and
probably some code between the function calls.
 
You are mistaking a hypothetical example with real code.
 
 
 
> Again, compare that to
 
> // OK for me
> const bool success = a() and b() and c() and d() and e();
 
There are many other ways to do this:
 
bool success = true;
if (success) success &= a();
if (success) success &= b();
if (success) success &= c();
if (success) success &= d();
if (success) success &= e();
 
or:
 
bool doAll() {
if (!a()) return false;
if (!b()) return false;
if (!c()) return false;
if (!d()) return false;
if (!e()) return false;
return true;
}
 
const bool success = doAll();
 
 
or:
bool success = false;
do {
if (!a()) break;
if (!b()) break;
if (!c()) break;
if (!d()) break;
if (!e()) break;
success = true;
} while (false);
 
 
> never allow short-circuit expressions that have side effects." appears
> to mean that the coding standards that you regard as decent, require the
> fantastic ugliness and awkwardness of (B) or (C) above.
 
No, it merely means you can imagine beauty in unrealistic examples, but
can't imagine good ways to implement real code.
 
 
 
> Regarding (2), that a choice expression isn't like a boolean expression,
> choice expressions are IME much more commonly used for side effects than
> boolean expressions are, especially where a result value is used.
 
And it would be, IME, an even worse idea to rely on side-effects and
lack thereof in a conditional expression compared to a logical one.
 
(If the gcc extension of statement expressions were to be included in
standard C and C++, it would allow you to express some of these things
neatly and clearly.)
 
>> would be a /good/ way to write it.
 
> Yes, considering all possibilities is often useful.
 
> If for nothing else, one might learn something from the exercise. :)
 
That is what we are doing here!
 
>> give new ideas. Writing it in actual serious code is "smart-arse",
>> which is no longer a complement.
 
> I don't get what's fancy or "smart" about it.
 
Ah, so you haven't learned enough yet :-)
 
>> coding practice.
 
> But what is it that's Greek to you, or that you suspect would be Greek
> to most others, in the code?
 
I mean like making "a Π b" be an intersection operator for sets.
 
> and `goto` a common cleanup.
 
> We use it because it's easier to understand and analyze, to prove
> correctness of, due to the simple guarantees.
 
Yes, of course - it is better to write code with lower risks of bugs
than to write code that makes it easier to find the bugs.
 
PoorOldAlFSaysMrBoltar@sadsack.com: Jun 28 09:22AM

On Wed, 27 Jun 2018 21:45:47 +0200
>On 27.06.2018 15:41, MrBoltarToYou@galactic.com wrote:
>> snip
 
>Your third identify to be killfiled by me.
 
It really makes little odds, I write my posts in vi and editing the From:
line takes seconds. You might end up with a very big kill file. Assuming you
actually use one and its not all just bluster.
Manfred <noname@invalid.add>: Jun 28 01:59PM +0200

On 6/28/2018 10:39 AM, David Brown wrote:
> if (success) success &= c();
> if (success) success &= d();
> if (success) success &= e();
 
Since &= is a bitwise operator, I'd rewrite this as:
 
bool success = true;
success = success && a();
success = success && b();
success = success && c();
success = success && d();
success = success && e();
 
But still I'd prefer Alf's expression, possibly split across multiple lines:
const bool success = a() and
b() and
c() and
d() and
e();
 
Which incidentally keeps the const qualifier (which is something I value)
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 28 04:53PM +0200

On 28.06.2018 10:39, David Brown wrote:
 
>> How can a single ?: be obscure?
 
> It is a matter of how you use it - it is not the ?: operator itself that
> is hard. "(a < b) ? b : a" is fine. Your monstrosity is not.
 
 
Well, let's investigate at what point you, or the programmers you
imagine, lose comprehension.
 
1. (s == "blah"? 1 : 2)
2. (s == "blah"? DerivedA{} : DerivedB{})
3. (s == "blah? A{}.x : B{}.x)
 
Has the conditional turned into a somewhat incomprehensible monstrosity
already in 2, or is it the use of a data member, as in 3, that makes
their eyes glaze over?
 
I hadn't ever dreamed that current programmers have such difficulties.
But I'm learning. And maybe we can nail this more precisely. ;-)
 
 
> [snip]
 
Cheers!,
 
- Alf
Bart <bc@freeuk.com>: Jun 28 07:03PM +0100

On 28/06/2018 15:53, Alf P. Steinbach wrote:
> their eyes glaze over?
 
> I hadn't ever dreamed that current programmers have such difficulties.
> But I'm learning. And maybe we can nail this more precisely. ;-)
 
I think this is the expression involved:
 
(args[1] == "--faux-text"? With_faux_text{}._ :
With_stream_detection{}._), app::run();
 
When I first glanced at this, I assumed it was in this form:
 
(A ? B : C, D);
 
With the D, as I thought, belonging to the C as I assumed that this was
one ?: term only, not a ?: term then something else. Actually it's like
this:
 
(A ? B : C), D;
 
That is, it evaluates B or C then executes D. At least, you do use
parentheses around the ?: which is rare in C code.
 
That your version is confusing might be something to do with it using 18
punctuation tokens, 22 punctation characters, 5 underlines, 3 hyphens,
and long indentifier names that look more like comments.
 
Now, ?: is used when you want to evaluate either x or y, and need to
immediately use the result of that within an expression. If you don't
need to use the actual value, just the side-effects, then you shouldn't
use ?:, as you would just being using it to avoid writing a proper
if-else statement.
 
The same argument applies to the comma operator; you use it when you
really need to evaluate one expression inside another, and not just to
be able to write:
 
X, Y;
 
instead of:
 
{X; Y;}
 
If you apply those guidelines, then your example becomes:
 
if (args[1] == "--faux-text")
With_faux_text{}._;
else
With_stream_detection{}._);
 
app::run();
 
Now you have form and indentation to help you see the structure. This
could with ?: and comma too:
 
(args[1] == "--faux-text"
? With_faux_text{}._ :
: With_stream_detection{}._),
app::run();
 
but it's not as good as just writing it properly.
 
--
bart
David Brown <david.brown@hesbynett.no>: Jun 28 10:10PM +0200

On 28/06/18 16:53, Alf P. Steinbach wrote:
> their eyes glaze over?
 
> I hadn't ever dreamed that current programmers have such difficulties.
> But I'm learning. And maybe we can nail this more precisely. ;-)
 
I think you'll have a lot of difficulty trying to get a precise point
here - this is not a binary issue. The "maximum" example is easy, your
original code is hard, and in between there is a sliding scale. It
takes experience and a good understanding of other programmers to be
able to tell if code is /too/ hard - and it will depend massively on the
details of the code, the type of problem you are solving, and of course
the programmers who are looking at the code. There is no black and
white answer here - sorry.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 28 12:56AM +0100

On 27 Jun 2018 20:29:34 GMT
> auto f();
 
> is hardly helpful. So should we avoid the auto return type
> for functions which are part of an API for this reason?
 
I think this is a bit of a side issue. My view is that you should
instead avoid C++14 deduced return types where you actually know what
the return type is, except in the case of short lambda expressions, as
a matter of good form and making your code intelligible. This is apart
from the documentation difficulties to which you refer.
 
Where you don't necessarily know what the return type is, this was
rather more self-documenting with C++11. With C++11 when deducing
return types you had to have a trailing return type specified using a
decltype expression (or std::result_of) except in the case of single
statement lambda expressions (I think, it's going back a bit now).
Doxygen does correctly document that form for you. There is nothing to
stop you doing that with C++14 also, but this sort-of offends the DRY
principle since it is duplicative.
 
I have only mainly used auto with C++14 deduced return types in cases,
say in template code, where you do not actually know what the return
type is in advance. This is often coupled with the use of decltype on
the function having that deduced return type[1], because the function
is used for compile time metaprogramming and is never actually executed
at all.
 
Usually such functions with deduced return types are not part of the
public API anyway. Where they are, I think the documentation should
explain the position.
 
Chris
 
[1] This is decltype applied to the function application itself, in
order to generate a type. It is not the same as using decltype in a
C++11 style auto return type function declaration.
Sam <sam@email-scan.com>: Jun 27 05:14PM -0400

Stefan Ram writes:
 
> auto f();
 
> is hardly helpful. So should we avoid the auto return type
> for functions which are part of an API for this reason?
 
Avoiding a very useful, new language feature only because a documentation
tool can't deal with it doesn't seem like a good reason to me.
 
With the increased complexity of C++, only an actual C++ compiler can fully
understand C++ code. This is not the only part of modern C++ that doxygen
doesn't quite pick up.
 
I find doxygen very useful, and I use it a lot. I do not take into
consideration doxygen's limitations when writing code. I only review
doxygen's output after the fact; and make whatever manual fixes and tweaks
to doxygen's output that can be reasonably done.
Juha Nieminen <nospam@thanks.invalid>: Jun 28 05:20AM

> ought to define an interface (that's the I) but auto depends on the
> implementation details. With something having an official API it should
> be vice versa, implementation should depend on the interface.
 
Note that using 'auto' in an API might sometimes be justified.
More particularly as a synonym for "none-of-your-business type".
 
I'm not joking. The most prominent example of this would be
the actual type of a lambda. It's quite literally "none of your
business". The programmer shouldn't concern himself about what
the actual type of a lambda is, hence it's always used as 'auto'.
The actual underlying type is unspecified, and up to the compiler,
and code using lambda should never try to use that type explicitly.
David Brown <david.brown@hesbynett.no>: Jun 28 10:48AM +0200

On 27/06/18 22:29, Stefan Ram wrote:
> auto f();
 
> is hardly helpful. So should we avoid the auto return type
> for functions which are part of an API for this reason?
 
No, you should avoid having the auto return type in an API because it is
a daft thing to have in an API. An API should be specific, and say
/exactly/ what it returns. (In cases where that is impossible, such as
in some template functions, you need to question your coding structure
and API design before resorting to auto.)
 
"auto" is extremely convenient for local functions - static functions,
anonymous namespaces, private methods, etc. It is not something you
would want in an API. That applies to functions, variables, consts, etc.
boltar@cylonHQ.com: Jun 28 09:40AM

On Wed, 27 Jun 2018 17:14:59 -0400
>With the increased complexity of C++, only an actual C++ compiler can fully
>understand C++ code. This is not the only part of modern C++ that doxygen
>doesn't quite pick up.
 
IMO the C++ syntax has now jumped the shark, its far to complex and rivals
Perl in its hideousnous. Originally it was commented that uglies such as
"virtual func() = 0" instead of "pure virtual func()" were because extra
keywords may break older programs that use them as names elsewhere. Then
we had new keywords such as override, final, explicit etc added anyway making
that argument moot. Then things got work and IMO the syntax reached its
nadir with the "[=/&]() -> <return type> { }" horror of lambda functions.
 
We have std::function. Why the hell didn't they simply introduce std::lambda
with a similar syntax?
 
eg: std::lambda<int((<local scoped vars>,(parameters)> { }
 
Or just do what other languages do and use the same syntax as primary functions
eg:
 
func(int mylambda(a,b,c) { }) or similar?
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 28 03:20PM +0100

On Thu, 28 Jun 2018 09:40:42 +0000 (UTC)
> Perl in its hideousnous. Originally it was commented that uglies such as
> "virtual func() = 0" instead of "pure virtual func()" were because extra
> keywords may break older programs that use them as names elsewhere.
 
A pure function means something completely different. That would be a
very poor choice of words, quite apart from needing a new keyword.
 
> Then
> we had new keywords such as override, final, explicit etc added anyway making
> that argument moot.
 
The argument is never moot. Presumably it was felt that the advantages
of having override, final and explicit as keywords outweighed the
potential for breakage, which would have been very small.
 
 
> We have std::function. Why the hell didn't they simply introduce std::lambda
> with a similar syntax?
 
> eg: std::lambda<int((<local scoped vars>,(parameters)> { }
 
A comma separating the captured variables from parameters, when
parameters are already separated by commas? Or are you inventing
a new meaning for parentheses (it is not clear because yours are
unbalanced). This syntax is hopeless. I prefer what we have.
 
> Or just do what other languages do and use the same syntax as primary functions
> eg:
 
> func(int mylambda(a,b,c) { }) or similar?
 
Because C++ language rules require you to find some way of identifying
the captured variables and whether the capture is to be by reference or
by value. To try to introduce automatic lexical closures as in
some other languages would have been a significant alteration to C++ and
wouldn't have worked. Languages which do have that generally work on
the basis that numbers and characters (so called "immediate" values) are
copied by value and any other object is copied by reference.
 
I think you are too easily offended by language syntax. Try another
language - there are plenty to choose from.
boltar@cylonHQ.com: Jun 28 02:34PM

On Thu, 28 Jun 2018 15:20:20 +0100
>> "virtual func() = 0" instead of "pure virtual func()" were because extra
>> keywords may break older programs that use them as names elsewhere.
 
>A pure function means something completely different. That would be a
 
It does? Please enlighten us because in C++ the "= 0" on the end definately
means pure virtual. Perhaps you're getting confused with another language.
 
 
>The argument is never moot. Presumably it was felt that the advantages
>of having override, final and explicit as keywords outweighed the
>potential for breakage, which would have been very small.
 
Ditto "pure".
 
>> eg: std::lambda<int((<local scoped vars>,(parameters)> { }
 
>A comma separating the captured variables from parameters, when
>parameters are already separated by commas? Or are you inventing
 
My mistake, I meant to write ";" as used in for().
 
>a new meaning for parentheses (it is not clear because yours are
>unbalanced). This syntax is hopeless. I prefer what we have.
 
Presumably you think the std::function syntax is hopeless too then.
 
>I think you are too easily offended by language syntax. Try another
 
I'm offended by hacks, which is what C++ seems to be descending into.
 
>language - there are plenty to choose from.
 
Most are flavour of the month with little real traction and any language take a
long time to become proficient in anyway. I have better things to do with my
time than start from scratch.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 28 03:58PM +0100

On Thu, 28 Jun 2018 14:34:30 +0000 (UTC)
 
> >A pure function means something completely different. That would be a
 
> It does? Please enlighten us because in C++ the "= 0" on the end definately
> means pure virtual. Perhaps you're getting confused with another language.
 
Look it up, and give yourself a broader background. If 'pure' were to
be used as a keyword, it would be to mark that a function is without
side effects, not to indicate that it is a virtual function without
implementation. Various languages have a 'pure' keyword, such as D; I
would not especially support its introduction in C++ but it should be
left alone for that use in case in the future others decide otherwise
as it may possibly have optimization benefits; it should not be expended
to give effect to your proposal.
 
> >of having override, final and explicit as keywords outweighed the
> >potential for breakage, which would have been very small.
 
> Ditto "pure".
 
No - see above. Your proposition that having 'overide, final and
explicit' as keywords means a free for all for any other half-baked
keyword anyone on a newsgroup thinks should be used, because it is now
"moot", is ridiculous. It is even more ridiculous when 'pure' already
has a well accepted and different meaning.
 
 
> >a new meaning for parentheses (it is not clear because yours are
> >unbalanced). This syntax is hopeless. I prefer what we have.
 
> Presumably you think the std::function syntax is hopeless too then.
 
You are missing the point. It does not make closures, and the syntax
of std::function does not provide for it to do so. If you want to have
a closure with std::function you have to construct it specifically with
a lambda expression, std::bind or the like. In fact, you have
deliberately snipped the part of my post which previously explained this
to you.
 
 
> Most are flavour of the month with little real traction and any language take a
> long time to become proficient in anyway. I have better things to do with my
> time than start from scratch.
 
Broadening your knowledge would help you avoid the temptation to think
that you know it all when it is apparent that you do not.
boltar@cylonHQ.com: Jun 28 03:06PM

On Thu, 28 Jun 2018 15:58:45 +0100
>be used as a keyword, it would be to mark that a function is without
>side effects, not to indicate that it is a virtual function without
>implementation. Various languages have a 'pure' keyword, such as D; I
 
In C++ that is the definition of pure. This discussion is about C++ not
the general definition of pure virtuals as you see it.
 
>> Ditto "pure".
 
>No - see above. Your proposition that having 'overide, final and
 
Yes.
 
>"moot", is ridiculous. It is even more ridiculous when 'pure' already
>has a well accepted and different meaning.
 
Not in C++.
 
>Broadening your knowledge would help you avoid the temptation to think
>that you know it all when it is apparent that you do not.
 
Spare me your feeble attempts at being patronising, they're falling flat.
I suggest you get your own clue.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 28 04:25PM +0100

On Thu, 28 Jun 2018 15:06:27 +0000 (UTC)
> >implementation. Various languages have a 'pure' keyword, such as D; I
 
> In C++ that is the definition of pure. This discussion is about C++ not
> the general definition of pure virtuals as you see it.
 
Pure functions are rarely virtual. Anyone with minimal knowledge of
computer science knows what a pure function is.

> >that you know it all when it is apparent that you do not.
 
> Spare me your feeble attempts at being patronising, they're falling flat.
> I suggest you get your own clue.
 
I don't need to be patronizing. You seem clueless, and you do it all
for yourself. I genuinely was suggesting that you need to widen your
experience in order to help deal with that.
boltar@cylonHQ.com: Jun 28 03:34PM

On Thu, 28 Jun 2018 16:25:23 +0100
>> the general definition of pure virtuals as you see it.
 
>Pure functions are rarely virtual. Anyone with minimal knowledge of
>computer science knows what a pure function is.
 
We're not talking about the mathematical definition of pure, we're talking
about the c++ definition of pure virtuals which mean something else entirely.
Either you're being pedantic for the sake of it or you're just another
aspie unable to follow normal discussion.
 
 
>I don't need to be patronizing. You seem clueless, and you do it all
>for yourself. I genuinely was suggesting that you need to widen your
>experience in order to help deal with that.
 
Do carry on, I'll get the popcorn! Your attempts at this are highly amusing :)
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 28 04:58PM +0100

On Thu, 28 Jun 2018 15:34:15 +0000 (UTC)
> about the c++ definition of pure virtuals which mean something else entirely.
> Either you're being pedantic for the sake of it or you're just another
> aspie unable to follow normal discussion.
 
If I were, that would be a totally inappropriate remark to make. Ad
hominem remarks of that kind would just be an indication that you have
lost the argument. So you seem not only to be lacking understanding
about C++, but to be unpleasant and lacking understanding about C++.
 
Anyway, you carry on with your fixation with pure virtual functions.
Better informed people would want to reserve any 'pure' keyword to
denote pure functions.
legalize+jeeves@mail.xmission.com (Richard): Jun 28 04:15PM

[Please do not mail me a copy of your followup]
 
Sam <sam@email-scan.com> spake the secret code
 
>With the increased complexity of C++, only an actual C++ compiler can fully
>understand C++ code. This is not the only part of modern C++ that doxygen
>doesn't quite pick up.
 
Use DoxyPress instead; it uses clang to parse.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
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: