Monday, April 15, 2019

Digest for comp.lang.c++@googlegroups.com - 23 updates in 5 topics

"Öö Tiib" <ootiib@hot.ee>: Apr 15 03:19AM -0700

> Does the standard say anything about the format of the output of
> special numeric values, like NaNs and Infs, when formatted by
> iostreams?
 
No. Also it is possible for example that in conforming implementation
std::strtod and istream>> parse infs and nans differently.
 
> I'm writing the iostream routines for some numeric routines.
 
Basically ... avoid istream>> and ostream<<. These are slow and
behave non-portably.
 
> Or have I just managed to miss the specification?
 
No. If you need text transmission between different modules
then use some well-established serialization language like xml,
json or yaml. These have standardized specifications and
well-performing and -tested libraries for generating and
parsing can be found.
James Kuyper <jameskuyper@alumni.caltech.edu>: Apr 15 08:56AM -0400

> Does the standard say anything about the format of the output of
> special numeric values, like NaNs and Infs, when formatted by
> iostreams?
The behavior of to_string() for floating point arguments is defined in
terms of the C standard library function sprintf() with "%f" or "%Lf"
format specifiers (24.3.4p7). I'm fairly certain the specifications for
<iostream> cross-references to_string() somehow, but I'm in a bit of a
hurry, so I'll let someone else track down the precise specification.
 
You have to cross-reference the C standard to find out what that means
for those special values:
"A double argument representing an infinity is converted in one of the
styles [-]inf or [-]infinity — which style is implementation-defined. A
double argument representing a NaN is converted in one of the styles
[-]nan or [-]nan(n-char-sequence) — which style, and the meaning of
any n-char-sequence, is implementation-defined. The F conversion
specifier produces INF, INFINITY, or NAN instead of inf, infinity, or
nan, respectively." (C 7.21.6.1p8).
 
While the output is partially implementation-defined, there are parts
you can rely on. However, I see no way to determine from inside your
program where the implementation-defined n-char-sequence ends.
Daniel <danielaparker@gmail.com>: Apr 15 06:23AM -0700

On Monday, April 15, 2019 at 6:19:13 AM UTC-4, Öö Tiib wrote:
 
> Basically ... avoid istream>> and ostream<<.
 
> These are slow and behave non-portably.
 
Agreed, for the non-portably. There's also the issue of how many decimal
digits to preserve, to avoid losing precision. You could set that to
std::numeric_limits::max_digits10 (generally 17), but then you won't
have shortest representations for many numbers.
 
> json or yaml. These have standardized specifications and
> well-performing and -tested libraries for generating and
> parsing can be found.
 
Agreed, but ...
 
The json data format doesn't support nan/inf/-inf, it suggests that these be
reported as null. One or two json decoders/encoders support conversion
to strings "nan", "inf", "-inf", and back, but this is non standard and
non interoperable. The yaml data format does support "nan", "inf", "-inf",
but I think it's fair to say it's not nearly as well established as json or
xml.
 
Another alternative would be one of the JSON like binary format such as CBOR
that supports nan, inf, and -inf.
 
Daniel
jameskuyper@alumni.caltech.edu: Apr 15 12:20PM -0700

On Monday, April 15, 2019 at 8:56:18 AM UTC-4, James Kuyper wrote:
> format specifiers (24.3.4p7). I'm fairly certain the specifications for
> <iostream> cross-references to_string() somehow, but I'm in a bit of a
> hurry, so I'll let someone else track down the precise specification.
 
 
Correct citation, but not relevant. Sorry.
 
The relevant citation is for num_put::do_put(), whose behavior for
floating point types is defined in terms of passing "%f" to printf()
(26.4.2.2.2p2 and p5). ostream::operator<<() for floating point types is
defined in terms of calling do_put() (27.5.2.2p1). The rest of what I
wrote is still relevant:
 
Robert Wessel <robertwessel2@yahoo.com>: Apr 15 03:16PM -0500

On Mon, 15 Apr 2019 03:19:03 -0700 (PDT), 嘱 Tiib <ootiib@hot.ee>
wrote:
 
>json or yaml. These have standardized specifications and
>well-performing and -tested libraries for generating and
>parsing can be found.
 
 
You've got it backwards. I have a library/class with types that
should support the normal iostream functions. Thus I have to
implement them, and need to handle things like Infs and NaNs.
 
IOW, I'm trying to figure out what users of this library might be
expecting in those cases.
Robert Wessel <robertwessel2@yahoo.com>: Apr 15 04:20PM -0500

On Mon, 15 Apr 2019 12:20:39 -0700 (PDT),
 
>> While the output is partially implementation-defined, there are parts
>> you can rely on. However, I see no way to determine from inside your
>> program where the implementation-defined n-char-sequence ends.
 
 
Thank you, that's very helpful.
 
To which version of the C++ standard are you referencing? All of the
relevant information ("punt to printf definition") in C++17 appears to
be in 25.2.2.2.2 (not 26.x), and I'm not sure what 27.5.2.2 is
supposed to be referring to.
 
It's probably not a great idea, but I'm toying with the idea of using
sprintf() to generate the local forms of those (on first use, and then
saving them).
jameskuyper@alumni.caltech.edu: Apr 15 02:41PM -0700

> >> Does the standard say anything about the format of the output of
> >> special numeric values, like NaNs and Infs, when formatted by
> >> iostreams?
...
> implement them, and need to handle things like Infs and NaNs.
 
> IOW, I'm trying to figure out what users of this library might be
> expecting in those cases.
 
The requirement that I mentioned which cross-references the C standard
only applies to float, double, and long double. If you're defining your
own type to work with those routines, it's up to you to decide what you
want, but it would probably be best to use the behavior for those types
as inspiration.
 
That being the case, you should understand the purpose of the
"[-]nan(n-char-sequence)" option. std::nan("n-char-sequence") is defined
as equivalent to std::strtod("NAN(n-char-sequence)"). The behavior of
std::istream::operator>>() is defined in terms of std::strtod(), so C++
users can also use that function to achieve the same result.
 
The behavior of std::strtod() for such strings is implementation-
defined. For many implementations, calling strtod() with a suitable n-
char-sequence will create a NaN which, when printed out, displays the
same n-char-sequence - but the C standard fails to mandate such a
connection.
 
For an implementation that pre#defines __STDC_IEC_559__ the C standard
does recommend for the <math.h> functions that "If a function with one
or more NaN arguments returns a NaN result, the result should be the
same as one of the NaN arguments (after possible type conversion),
except perhaps for the sign." (C F10p13). On many implementations, the
same is true of ordinary floating point math operations. The net result
is that if a NaN in the inputs of a calculation is responsible for the
fact that the result of the calculation is also a NaN, then the n-char-
sequence can be used to determine which input NaN was responsible for
that result.
 
You get to choose whether you want to implement your types to allow the
same kind of tracing - I'd recommend doing so.
jameskuyper@alumni.caltech.edu: Apr 15 02:58PM -0700

> On Mon, 15 Apr 2019 12:20:39 -0700 (PDT),
> jameskuyper@alumni.caltech.edu wrote:
 
> >On Monday, April 15, 2019 at 8:56:18 AM UTC-4, James Kuyper wrote:
...
> >> program where the implementation-defined n-char-sequence ends.
 
> Thank you, that's very helpful.
 
> To which version of the C++ standard are you referencing?
 
I'm referring to n4762.pdf, the latest draft of the C++ standard that I
have access to. It's dated 2018-07-07, making it more recent than C++17,
which means it may include things that are not yet official, but nothing
I mentioned in my message falls in that category.
 
> relevant information ("punt to printf definition") in C++17 appears to
> be in 25.2.2.2.2 (not 26.x), and I'm not sure what 27.5.2.2 is
> supposed to be referring to.
 
My mistake. In n4762.pdf, that should have been 27.7.5.2.2p1. In the
draft version that most closely resembles the official C++2017 standard,
n4659.pdf, the corresponding section is 30.7.5.2.2p1.
 
> It's probably not a great idea, but I'm toying with the idea of using
> sprintf() to generate the local forms of those (on first use, and then
> saving them).
 
When your other message referred to "types that should support the
iostream requirements", I assumed that they were types you had to
implement from scratch. If using sprintf() is an option, that satisfies
the relevant requirements automatically, without you having to worry
about the details, which is a lot simpler. I'd recommend that approach.
Robert Wessel <robertwessel2@yahoo.com>: Apr 15 05:22PM -0500

On Mon, 15 Apr 2019 14:41:37 -0700 (PDT),
>own type to work with those routines, it's up to you to decide what you
>want, but it would probably be best to use the behavior for those types
>as inspiration.
 
 
The types in question will interoperable with normal floats, but are
not actual floats in the sense of float/double/long double. But I am
trying to follow the normal C++ behavior with these. I *think* I have
Inf, NaN and zero handling under control in computational situations
(although I'm basically following the IEEE FP rules, signed zeros
excluded, not so much the C/C++ specs.). There's probably some open
issues with when SNaNs actually signal in some of the semi-numerical
functions.
 
 
>char-sequence will create a NaN which, when printed out, displays the
>same n-char-sequence - but the C standard fails to mandate such a
>connection.
 
 
strtod(NAN()) may be suitable as-is, as are the INF() cases. An
implementation where those don't generate the same string as printf
and iostream is probably classifiable as a bit perverse. Probably
need to do some testing.
 
It would probably force a final commitment to requiring C++11...
 
 
>that result.
 
>You get to choose whether you want to implement your types to allow the
>same kind of tracing - I'd recommend doing so.
 
 
We're not planning to support NaN payloads, although I'm willing to
reconsider. It would only be a modest change. While I can see the
theoretical benefit for being able to backtrack sources, I've never
seen anyone actually use the facility for such. Of course then I have
to pick a payload size, and figure out how inter-operate with floats.
 
There seems to be a bit of a definitional issue with the NaN-string
conversions, they appear to allow a NaN payload of zero, which for a
QNaN would acually make it an Inf. Not my issue, though.
Robert Wessel <robertwessel2@yahoo.com>: Apr 15 05:26PM -0500

On Mon, 15 Apr 2019 14:58:23 -0700 (PDT),
>implement from scratch. If using sprintf() is an option, that satisfies
>the relevant requirements automatically, without you having to worry
>about the details, which is a lot simpler. I'd recommend that approach.
 
 
They are ("from scratch"). I was thinking of hacking out the local
representation by feeding a NaN or Inf float to sprintf.
James Kuyper <jameskuyper@alumni.caltech.edu>: Apr 15 09:10AM -0400

On 4/12/19 3:37 AM, Alf P. Steinbach wrote:
>>> $use_cppx( is_empty );
 
>> You understand that this is a C++ newsgroup, right?
 
> As I understand it you indicate that in your opinion the above is not C++.
 
The meaning of your syntax is certainly not specified by the C++
standard. Any such use of '$' outside of a character or string literal
is a C++ syntax error. You should not expect people monitoring
comp.lang.c++ to know what it means in whatever context does allow you
to use that syntax. It's also unreasonable to try to teach them that
syntax. If you're posting here, you should post using standard C++
syntax, even if you normally use something else.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 15 04:04PM +0200

On 15.04.2019 15:10, James Kuyper wrote:
> to use that syntax. It's also unreasonable to try to teach them that
> syntax. If you're posting here, you should post using standard C++
> syntax, even if you normally use something else.
 
It's not a non-standard syntax (though the $ is a non-standard token
form -- syntax is one level up from that), it's an ordinary macro.
 
It would be quite some work to rewrite the macro calls before posting,
and ~zero work for a reader here to grok it.
 
One simply does not include all the relevant parts of Boost if the code
uses Boost, say. One doesn't expect to get helpful responses from people
who fail to relate to some Boost functionality and need that source code
posted in the group. The same for the above; it's sheer lunacy to
require all library source code posted, instead of referenced.
 
Therefore, unless there's a reasonable request for a pared down example
(as was in one response), I just provide a link to some library that
defines the macros, or other stuff used in the code.
 
Re "whatever context does allow you", that's quite misleading. I don't
know any environment where a compiler does not by default accept the
above. Such an environment might exist, but your statement indicates
that instead of being exceedingly rare, possibly non-existing, it's
common, and that's very misleading and can't be based on actual experience.
 
 
Cheers!,
 
- Alf
jameskuyper@alumni.caltech.edu: Apr 15 08:38AM -0700

On Monday, April 15, 2019 at 10:04:33 AM UTC-4, Alf P. Steinbach wrote:
> > syntax, even if you normally use something else.
 
> It's not a non-standard syntax (though the $ is a non-standard token
> form -- syntax is one level up from that), it's an ordinary macro.
 
The standard uses the notation described in 4.3 "Syntax Notation" to
describe the rules for valid identifiers (5.10p1). I feel comfortable
referring to violations of those rules as syntax errors - the standard
doesn't provide any other simple term for referring to such violations.
 
...
> Re "whatever context does allow you", that's quite misleading. I don't
> know any environment where a compiler does not by default accept the
> above.
 
Any compiler that enforces C++ rules governing the characters permitted
in identifiers should, at an absolute minimum, issue a diagnostic for
such code when invoked in a fully conforming mode. I don't normally use
any compiler in a non-conforming mode.
 
> ... Such an environment might exist, but your statement indicates
> that instead of being exceedingly rare, possibly non-existing, it's
> common, and that's very misleading and can't be based on actual experience.
 
Since I know what characters are permitted in identifiers, I never use
the ones that aren't. It's therefore entirely possible that the
compilers I've used tolerate characters that are not permitted, and
might even be non-conforming by reason of failing to issue the mandatory
diagnostic when they do so. That's not a sign of lack of experience,
merely a failure on my part to exceed the limits of what's permitted,
just for the joy of finding out what happens when I do. That's the same
reason I don't have much experience with how compilers deal with
division by 0, or how they deal with bit-wise operations on negative values.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 15 05:46PM +0200

> just for the joy of finding out what happens when I do. That's the same
> reason I don't have much experience with how compilers deal with
> division by 0, or how they deal with bit-wise operations on negative values.
 
A claim of in-experience!
 
In support of your view.
 
But you're just adding noise in order to drown out the earlier exchange.
 
You have no point, just a dislike.
 
 
Cheers!,
 
- Alf
"Öö Tiib" <ootiib@hot.ee>: Apr 15 08:51AM -0700

> just for the joy of finding out what happens when I do. That's the same
> reason I don't have much experience with how compilers deal with
> division by 0, or how they deal with bit-wise operations on negative values.
 
AFAIK $ was not allowed in identifiers until C++11. C++11 started
to allow "and other implementation-defined characters" in identifiers.
I'm in doubt that it is violation of standard not to diagnose presence of
"other implementation-defined characters" in identifiers.
jameskuyper@alumni.caltech.edu: Apr 15 09:29AM -0700

On Monday, April 15, 2019 at 11:46:12 AM UTC-4, Alf P. Steinbach wrote:
> On 15.04.2019 17:38, jameskuyper@alumni.caltech.edu wrote:
...
> > reason I don't have much experience with how compilers deal with
> > division by 0, or how they deal with bit-wise operations on negative values.
 
> A claim of in-experience!
 
Yes, I routinely relevant disclaim experience that others might have
expected me to have. Don't you?
 
> In support of your view.
 
Er, no? It was the C++ standard that I was using to support my view;
explaining my inexperience was merely part of an explanation of why I
cannot directly address your assertion that compilers which do this are
commonplace.
 
...
> You have no point, just a dislike.
 
It's true that I dislike non-conformance with applicable and
authoritative standards. However, my point was about the standard, not
my dislike. My point would have been equally valid (and almost
identically written), if I had been an enthusiastic supporter of this
extension.
Paavo Helde <myfirstname@osa.pri.ee>: Apr 15 07:39PM +0300

On 15.04.2019 17:04, Alf P. Steinbach wrote:
> It's not a non-standard syntax (though the $ is a non-standard token
> form -- syntax is one level up from that), it's an ordinary macro.
 
> It would be quite some work to rewrite the macro calls before posting,
 
If these are really macros, then a simple preprocessor run would get rid
of them.
 
> and ~zero work for a reader here to grok it.
 
You must be kidding. Zero work for downloading and studying whatever
framework/library is defining these macros? And for what purpose?
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 15 07:55PM +0200

On 15.04.2019 18:39, Paavo Helde wrote:
 
>> It would be quite some work to rewrite the macro calls before posting,
 
> If these are really macros, then a simple preprocessor run would get rid
> of them
 
Then you get some zillions of tons of code from the standard library added.
 
But I guess I could write a simple name transformer. Will consider.
 
 
>> and ~zero work for a reader here to grok it.
 
> You must be kidding. Zero work for downloading and studying whatever
> framework/library is defining these macros? And for what purpose?
 
Well, `using` statements aren't exactly complex or rocket science.
They're just annoyingly needlessly impractically verbose in C++. And the
committee drags its feet, going by quarter-measures, where C++17 just
allows you to not redundantly repeat the word `using` for each item.
 
 
Cheers!,
 
- Alf
jameskuyper@alumni.caltech.edu: Apr 15 11:14AM -0700

On Monday, April 15, 2019 at 11:51:19 AM UTC-4, Öö Tiib wrote:
> On Monday, 15 April 2019 18:38:45 UTC+3, james...@alumni.caltech.edu wrote:
...
> > division by 0, or how they deal with bit-wise operations on negative values.
 
> AFAIK $ was not allowed in identifiers until C++11. C++11 started
> to allow "and other implementation-defined characters" in identifiers.
 
I don't currently have access to older versions of the standard, but
you're right about C++2011 and C++2014, but in C++2017 that part was
removed, and it's not present in the latest draft I have access to
(n4762.pdf, 2018-07-07), either.
 
 
> I'm in doubt that it is violation of standard not to diagnose presence of
> "other implementation-defined characters" in identifiers.
 
Diagnostics are sometimes mandatory, but never prohibited.
 
In the context of older versions of C++, I would have emphasized the
greater portability of identifiers that don't rely upon the "other ..."
option.
jameskuyper@alumni.caltech.edu: Apr 15 11:28AM -0700

On Monday, April 15, 2019 at 12:29:52 PM UTC-4, james...@alumni.caltech.edu wrote:
...
> Yes, I routinely relevant disclaim experience that others might have
> expected me to have.
 
Let me re-write that:
 
I routinely disclaim relevant experience that others might expect me to have, if I don't actually have it.
"Öö Tiib" <ootiib@hot.ee>: Apr 15 07:30AM -0700

On Saturday, 13 April 2019 19:42:31 UTC+3, bitrex wrote:
> overloaded derived class methods through a base class pointer, in theory
> to an "infinite" number of overloads in various derived classes. And has
> the usual vtable + dynamic dispatch overhead.
 
Note that when compiler can figure most derived type of object out
compile time then it can call virtual methods directly or even
inline those.

> constraint somewhere I guess or you're just talking about regular
> virtual based runtime polymorphism, again) that it works only with a
> limited subset of potential subclasses designed expressly for that purpose.
 
 
I do not know. The other way of dynamic polymorphism is to use
function pointers.
Bonuses compared with virtual method calls:
* calls are cheaper by one level of indirection.
* bigger flexibility since pointers can be re-directed during object's life-time.
Minuses:
* Object is bigger taking function pointer per "method".
* Object's initialization code is bigger by setting these up.
* Compilers tend to not optimize calls through function pointers.
 
> virtualization "in disguise." I have read a bit about the "Visitor"
> pattern which seems relevant to my question but don't know enough to
> know for sure. Thanks
 
Visitor pattern is double-dispatch pattern. Two virtual dispatches
joined together for to find the right spot in visitor/visitable square.
It means that technically we are paying *more* for adding new
operations to visitables without modifying the classes of visitables.
I am unsure if that was what you needed.
James Kuyper <jameskuyper@alumni.caltech.edu>: Apr 15 08:40AM -0400

On 4/13/19 7:14 AM, Bonita Montero wrote:
> _theoretically_ shouldn't memcpy()'d. But in this case there
> arent any complex members so that you won't get into trouble
> with any compiler.
 
"For any object (other than a base-class subobject) of trivially
copyable type T, whether or not the object holds a valid value of type
T, the underlying bytes (1.7) making up the object can be copied into an
array of char or unsigned char.
If the content of the array of char or unsigned char is copied back into
the object, the object shall subsequently hold its original value." (3.9p2).
It goes on to give memcpy() as an example of how such a copy could be
performed.
 
Note that this guarantee is tied to "trivially copyable type", not POD type.
 
Trivially copyable classes are not allowed to have non-trivial copy,
move, copy-assignment or move-assignment, constructors (9p6) - but other
user-defined constructors are permitted.
 
POD classes includes classes that are merely trivial, but not
necessarily trivially copyable (9p10).
James Kuyper <jameskuyper@alumni.caltech.edu>: Apr 15 07:56AM -0400

On 4/12/19 12:40 PM, Ben Bacarisse wrote:
...
> bool from a pointer, and the application of ! to a pointer, use the
> standard conversions, which is what you and Juha (and almost everyone!)
> calls implicit conversions.
 
As I understand it, "implicit conversions" should mean those conversions
that can occur without requiring any explicit conversion operator: a
C-style cast or one of the named casts.
The C++ standard doesn't define an "implicit conversion", but it does
define an "implicit conversion sequence" (13.3.3.1). Standard conversion
sequences are only a subset of implicit conversion sequences.
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: