Thursday, April 18, 2019

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

"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Apr 18 03:51PM -0400

I have a need fairly often to return distinct values for a return value.
I don't particularly care what the values are, but they just need to be
distinct and unique so that if they are returned later I can identify
the exact cause of the error, where it failed.
 
Something like this:
 
int my_function(void)
{
if (!test_condition1)
return -1; // Indicate it failed at this test
 
// Arbitrary code
 
if (!test_condition2)
return -2; // Indicate it failed at this test
 
// Arbitrary code
 
if (!test_condition3)
return -3; // Indicate it failed at this test
 
// If we get here, we're good
}
 
Is there an existing way in C/C++ to automatically create some value
that would allow me to add a new test and have it inject the new
value? Ideally, I'd like for the compiler abilities to be sticky,
meaning once you put in the token/whatever to identify you need a
locally scoped automatically incrementing or decrementing value, that
it bakes it into source code during the compile.
 
Something like coding it this way initially:
 
int my_function(void)
{
if (!test_condition1)
return #autodec; // Indicate it failed at this test
 
if (!test_condition2)
return #autodec; // Indicate it failed at this test
 
if (!test_condition3)
return #autodec; // Indicate it failed at this test
 
// If we get here, we're good
}
 
And during compilation it automatically translates it to this for, baking
in the number:
 
int my_function(void)
{
if (!test_condition1)
return #autodec[-1]; // Indicate it failed at this test
 
if (!test_condition2)
return #autodec_[-2]; // Indicate it failed at this test
 
if (!test_condition3)
return #autodec_[-3]; // Indicate it failed at this test
 
// If we get here, we're good
}
 
This would allow new code to be added later without a hard-value, and
it would automatically adjust to the value inside the scope:
 
int my_function(void)
{
==> if (!test_condition0)
==> return #autodec; // Indicate it failed at this test
 
if (!test_condition1)
return #autodec[-1]; // Indicate it failed at this test
 
if (!test_condition2)
return #autodec_[-2]; // Indicate it failed at this test
 
if (!test_condition3)
return #autodec_[-3]; // Indicate it failed at this test
 
// If we get here, we're good
}
 
It would change to this during compile, and write the source file
back out:
 
if (!test_condition0)
return #autodec[-4]; // Indicate it failed at this test
 
I can see doing this in an external tool, but is there some way to do
it in C/C++?
 
And if not, does anyone have any idea for a good syntax on how to do it?
 
--
Rick C. Hodgin
scott@slp53.sl.home (Scott Lurndal): Apr 18 08:07PM


>This would allow new code to be added later without a hard-value, and
>it would automatically adjust to the value inside the scope:
 
There are two sides to every function call - how do the callers of that
function know, a priori, which return code matches which (pre)condition
failure; particularly when subsequently code gets inserted into the existing set
such that successive autogenerated return codes are shifted by one?
 
Just use a #define, static const uint32_t or enum and update them as needed.
Ian Collins <ian-news@hotmail.com>: Apr 19 08:18AM +1200

On 19/04/2019 07:51, Rick C. Hodgin wrote:
 
> Is there an existing way in C/C++ to automatically create some value
> that would allow me to add a new test and have it inject the new
> value?
 
An enum.
 
--
Ian.
Bart <bc@freeuk.com>: Apr 18 09:25PM +0100

On 18/04/2019 20:51, Rick C. Hodgin wrote:
> meaning once you put in the token/whatever to identify you need a
> locally scoped automatically incrementing or decrementing value, that
> it bakes it into source code during the compile.
 
Not really sure what you're getting at. But this function:
 
int test(int n) {
 
switch (n) {
enum {base=__LINE__};
 
case 1:
return base-__LINE__;
case 2:
return base-__LINE__;
case 3:
return base-__LINE__;
}
return 0;
}
 
 
Returns -3, -5, -7 when called with n = 1,2,3.
 
A new case would return a different error (ie. negative value), with no
enums to maintain (assuming it's on a different line). Alternatively
just return -__LINENO__ for an absolute line number to pinpoint where it
went wrong in the function.
Ben Bacarisse <ben.usenet@bsb.me.uk>: Apr 18 09:37PM +0100

> I don't particularly care what the values are, but they just need to be
> distinct and unique so that if they are returned later I can identify
> the exact cause of the error, where it failed.
<cut>
> return #autodec; // Indicate it failed at this test
 
> // If we get here, we're good
> }
 
This ties the correctness of every calling function into the order in
which these tests are written. I think it should be added to your
language ASAP.
 
<cut>
--
Ben.
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Apr 18 04:42PM -0400

On 4/18/2019 4:07 PM, Scott Lurndal wrote:
 
> There are two sides to every function call - how do the callers of that
> function know, a priori, which return code matches which (pre)condition
> failure;
 
The functions pretty much always return 0 or a positive value if
there were no errors.
 
It's contextual. how_long_is_this_text() will return a negative
value if you don't pass in a valid parameter, or 0 or a larger
value if there is content there, etc.
 
> particularly when subsequently code gets inserted into the existing set
> such that successive autogenerated return codes are shifted by one?
 
I don't have any autogenerated code in most projects. Some, but not many.
 
> Just use a #define, static const uint32_t or enum and update them as needed.
 
I write enough new code that it's becoming tedious to keep track of
all the unique values.
 
I will probably write an external tool and add a pre-build processing
step during compilation.
 
--
Rick C. Hodgin
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Apr 18 04:45PM -0400

On 4/18/2019 4:37 PM, Ben Bacarisse wrote:
>> }
 
> This ties the correctness of every calling function into the order in
> which these tests are written.
 
You missed the part where the idea I'm looking for bakes the values
first encountered with the naked #autodec into solid values which
are later identified as #autodec[-1] ... #autodec[-Nn], which allows
later #autodec portions to be added and they'll automatically insert
the next value in that location.
 
> I think it should be added to your language ASAP.
 
You're such a hateful person to me, Ben. You said previously in a
private email that you were going to try to refrain from responding
to my posts. Please try harder. Your failures are unbecoming.
 
--
Rick C. Hodgin
Bonita Montero <Bonita.Montero@gmail.com>: Apr 18 07:29AM +0200

> "std" was a rather uninspired choice as a namespace name, in contrast with
> other languages that have well thought out divisions of namespaces, C++
> chose to put almost everything into one big garbage dump. ...
 
These languages - like Java - have a much larger standard-library.
And in the case of Java there is also the package-level of member
-access which enforces a finer granular naming of the packages.
Bonita Montero <Bonita.Montero@gmail.com>: Apr 18 07:34AM +0200

> in that library have the prefix "png_". Do you go your way to create
> aliases for those names (eg. using macros of whatever) that have that
> prefix removed?
 
No, because this is inconvenient.
But if there would be png::-prefixes this would be convenient.
"Fred.Zwarts" <F.Zwarts@KVI.nl>: Apr 18 09:07AM +0200

"Juha Nieminen" schreef in bericht
news:q97lu2$egu$1@adenine.netfront.net...
>have to write a prefix like for example "png_", but it does bother
>you to have to write a prefix like for example "std::"?
 
>I'm honestly curious to know.
 
I have not yet encountered such a situation.
I don't like macros, I like the scoping rules of 'using'. (If I use 'using'
in a header file, I never use it at the global :: namespace level, only in
my own namespaces.)
I do not know of an easy replacement of 'using' in the example you mention,
for variables, functions, classes, etc.
I assume that libpng is written in C, where no namespaces are available. If
there would be a simple replacement for 'using' I might consider to use it.
But only if it would be simple enough for the reader of the code to
understand in a blink of an eye the meaning of it.
The complexity of removing prefixes in your example bothers me more than the
prefixes themselves.
The difference with the std:: prefix is, that there is a very simple and
well known method to remove it, designed especially for this case.
wyniijj@gmail.com: Apr 18 12:26AM -0700

Juha Nieminen於 2019年4月17日星期三 UTC+8下午3時06分59秒寫道:
 
> I bet that if they didn't know that writing namespace prefixes is
> optional, that you can bypass it with a `using` expression, they
> would not protest having to write it.
 
It's because of, me-thinks, the way people remember/process words.
 
The advantage(or disadvantage)of prefix is that the object is more
uniquely named. Unlike namespace, every time I see 'string' I have to
look for, even analyse programs to figure-out the right meaning that
name is associated to, from file to file.
 
Ex:
Mars::wind, Mars::rock
Earth::wind, Earth::rock
 
When I see 'wind', 'rock', how am I supposed to think with these words?
Mars_wind, Earth_rock would be more clearer.
"Fred.Zwarts" <F.Zwarts@KVI.nl>: Apr 18 10:41AM +0200

"Jorgen Grahn" schreef in bericht
news:slrnqbe9ob.4jo.grahn+nntp@frailea.sa.invalid...
 
>It's not, not necessarily. I may want to use the name "string"
>locally, and don't expect such a name to conflict with the standard
>library. Not to mention names like find().
 
I don't think it is wise to use such a widely used name as 'string' locally.
The other extreme is that someone may want to use 'std' locally. Then it
would be even more safe to always use ::std:: as a prefix. Some people do.
 
Bart <bc@freeuk.com>: Apr 18 10:44AM +0100

> Earth::wind, Earth::rock
 
> When I see 'wind', 'rock', how am I supposed to think with these words?
> Mars_wind, Earth_rock would be more clearer.
 
On Earth, how many times do people talk about Earth-rocks or Earth-wind
to distinguish them from not only Martian rocks and wind, but from any
other planet?
 
How annoying would it be to have to do that all the time?
 
(And just to make those terms absolutely unambiguous, would we also have
to prefix them with the the location of this solar system within this
galaxy?)
 
It is sufficient to use 'rocks' and 'wind' for 99.99% of the time, and
only use the qualifiers when you are actually talking about
extra-terrestrial versions.
wyniijj@gmail.com: Apr 18 06:44AM -0700

Bart於 2019年4月18日星期四 UTC+8下午5時44分50秒寫道:
 
> On Earth, how many times do people talk about Earth-rocks or Earth-wind
> to distinguish them from not only Martian rocks and wind, but from any
> other planet?
 
What on 'Earth' we are actually talking about and physically live in are
an imaginary programming world.
 
 
> (And just to make those terms absolutely unambiguous, would we also have
> to prefix them with the the location of this solar system within this
> galaxy?)
 
Ambiguity are more of the problem than annoyance.
We should try to avoid name collision as possible, all the times.
 
> It is sufficient to use 'rocks' and 'wind' for 99.99% of the time, and
> only use the qualifiers when you are actually talking about
> extra-terrestrial versions.
 
I will try to eliminate that 0.01% hard-to-find 'bug'
"Öö Tiib" <ootiib@hot.ee>: Apr 18 06:51AM -0700

On Thursday, 18 April 2019 11:41:47 UTC+3, F.Zwarts wrote:
 
> I don't think it is wise to use such a widely used name as 'string' locally.
> The other extreme is that someone may want to use 'std' locally. Then it
> would be even more safe to always use ::std:: as a prefix. Some people do.
 
Why you are using that "string" in complex expressions? Can you bring
example? I use string mostly in super simple contexts like:
 
using PhoneNumber = std::string;
 
Meaning of it is that in first sketch std::string can be enough;
but likely there will be a class PhoneNumber later. We may need
operations like PhoneNumber::countryCode() and we may need
a PetName not to be assignable to PhoneNumber. Same is true
with every kind of text values. These have type that in long run
can have more operations and constraints than "basic sequence
of chars". So why to type "std::string" in complex expressions?
Manfred <noname@add.invalid>: Apr 18 03:57PM +0200

On 4/18/2019 11:44 AM, Bart wrote:
> to distinguish them from not only Martian rocks and wind, but from any
> other planet?
 
> How annoying would it be to have to do that all the time?
 
The translated geography of "On Earth" would be "within std", i.e.
inside standard-library code, not application code.
Juha Nieminen <nospam@thanks.invalid>: Apr 18 02:09PM

> for variables, functions, classes, etc.
> I assume that libpng is written in C, where no namespaces are available. If
> there would be a simple replacement for 'using' I might consider to use it.
 
Why would you want to? Why would you want to remove the "png_" prefix from
all the names in the library? That would only make your code harder to read
because you can't see anymore where you are calling the libpng library
functions and where you are calling something else.
Juha Nieminen <nospam@thanks.invalid>: Apr 18 02:12PM

> It is sufficient to use 'rocks' and 'wind' for 99.99% of the time, and
> only use the qualifiers when you are actually talking about
> extra-terrestrial versions.
 
Suppose a program is using the Boost library, and you see a stray
"shared_ptr" without a prefix. Which version is it using?
 
(This is from an actual real-life example, not just an artificially
invented one.)
Bonita Montero <Bonita.Montero@gmail.com>: Apr 18 04:21PM +0200

> all the names in the library? That would only make your code harder to read
> because you can't see anymore where you are calling the libpng library
> functions and where you are calling something else.
 
If there would be namespaces with libpng and the types / fuctions within
this namespace would be meaningful and not ambigous when stripped, this
could be convenient.
With std:: the types and functins are well known to the deveopers so
there isn't any confusion when std:: is stripped.
Vir Campestris <vir.campestris@invalid.invalid>: Apr 18 09:36PM +0100

On 18/04/2019 15:09, Juha Nieminen wrote:
> all the names in the library? That would only make your code harder to read
> because you can't see anymore where you are calling the libpng library
> functions and where you are calling something else.
 
There are those who wish to remove the std:: prefix from all the names
in STL. That's not really different to removing the png_ prefix from all
the names in the PNG library.
 
I asked this question on the C++ group at work. Early indications are
that people want to keep the std:: prefixes in place. I'll try to report
back... I think there are more people on that than regularly post here.
 
Andy
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 18 10:39PM +0200

On 18.04.2019 16:12, Juha Nieminen wrote:
> "shared_ptr" without a prefix. Which version is it using?
 
> (This is from an actual real-life example, not just an artificially
> invented one.)
 
First note that you don't need to know. `std::shared_ptr` is an adaption
of `boost::shared_ptr`, so you already know all about it even if you
don't know details of Boost. Also if you're going to maintain that code,
 
* use the smart pointer that the original developers did,
 
unless you're going to refactor it, in which case you're in for a larger
effort anyway.
 
---
 
But let's say the example was, instead, something like
`something::Image` versus `something_else::Image` versus
`boost::gil::Image`, where the two first have nothing to do with
photographic images.
 
Ordinarily you get acquainted with the relevant types as you dive into
the code.
 
But if one just, unexpectedly, encounters an unqualified "Image", then
one checks what that means in this code, once.
 
The easiest way is just visual inspection, move eyeballs up with line of
sight in roughly the direction of the nearest `using` declaration.
 
If that's out of sight then I find it easier to hover the mouse over the
word than to scroll.
 
 
Cheers & hth.,
 
- Alf
David Brown <david.brown@hesbynett.no>: Apr 18 12:21PM +0200

On 17/04/2019 18:44, Bart wrote:
 
> (This processes command-line options and filenames for a C compiler, but
> the same pattern is used in several programs.)
 
> This bit doesn't need to be fast, and it doesn't need to be clever.
 
Since it doesn't need to be fast, and doesn't need to be clever, what's
wrong with existing C solutions - using a boolean flag, splitting things
out into a separate function (you can give it a name, rather than using
a lambda), or using a goto ?
 
If your language already has a "for/else" statement, then it's fair
enough to use it, of course.
Bart <bc@freeuk.com>: Apr 18 06:54PM +0100

On 18/04/2019 11:21, David Brown wrote:
> a lambda), or using a goto ?
 
> If your language already has a "for/else" statement, then it's fair
> enough to use it, of course.
 
Well, this is the point really. If a feature is reliably available, then
you just use it because it's convenient. Instead of inventing a solution
or rewriting a pattern you've used 100s of times before.
 
Same argument with the subject of multi-level loop breaks. If writing C,
then every so often you have to stop and work around the problem of C
having only single-level breaks. (Or zero-level breaks if you happen to
be inside 'switch'.)
 
(Last time I used a multi-level break: about 15 minutes ago. I wasn't
writing C. It's just there. What I could also have done with actually
was 'while-else' that I haven't got. So something to ponder adding.)
Ben Bacarisse <ben.usenet@bsb.me.uk>: Apr 18 08:36PM +0100


> ... If writing C, then every so often you have to stop and work around
> the problem of C having only single-level breaks.
 
This is a case where what you call a work-around, I call an improvement.
 
I like to reason about code, and the label helps a lot. I often ask,
particularly after loops, "what is the state of the program at this
point?" and the presence of a label is a big red flag telling me I have
to take partial execution into account. It's not a huge advantage,
since multi-level breaks are rare and likely to be flagged by a big
comment, but the label is in just the right place for me to know I have
to think about gotos.
 
--
Ben.
Bart <bc@freeuk.com>: Apr 18 09:15PM +0100

On 18/04/2019 20:36, Ben Bacarisse wrote:
> since multi-level breaks are rare and likely to be flagged by a big
> comment, but the label is in just the right place for me to know I have
> to think about gotos.
 
In my codebase (only compiled code not scripting), about 2.5% of all
'breaks' are multi-level ones (and break is used very commonly in my
code to terminate endless loops), and 2% of all 'for' loops are 'for-else'.
 
It doesn't sound much, but DB mentioned once that only 1.5% of his C
for-loops were anything other simple iteration via a variable. Yet C
loops still allow all those other possibilities, things that can make
code harder to reason about, not easier.
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: