Tuesday, December 16, 2014

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

Lynn McGuire <lmc@winsim.com>: Dec 15 06:00PM -0600

"In defense of printf"
http://kennykerr.ca/2014/12/08/in-defense-of-printf/
 
"Folks seem to enjoy pointing out that I use printf in many of my examples of "modern C++", as if printf is not really proper C++.
Apparently, I should be using cout. The trouble is that cout isn't exactly modern either. It has been around for as long as I can
remember and it certainly doesn't exemplify modern C++ as envisioned by C++11 and beyond. The oldest C++ textbook on my shelf was
printed in 1993 and covers cout. I even posed the question to some C++ historians and they were able to date it back as far as 1989.
Therefore, the argument that printf is old and cout is modern doesn't fly. A truly modern C++ solution would also not be
substantially slower than hand-written code. Most printf implementations today provide adequate type checking both at compile time
and run time. Visual C++ even provides secure versions that make it quite straightforward to write defensive code quite easily with
printf. Go ahead and use cout if you prefer, but don't claim it's the modern replacement for printf."
 
I have tried to cut my printf usage to very basic functions that get called a lot so they are fairly well tested. Printf usege in an
error message is a bad idea, IMHO.
 
Lynn
william.bell@frog.za.net: Dec 15 10:45PM -0800

I agree with you. See boost's format library.
 
http://www.boost.org/doc/libs/1_57_0/libs/format/
 
The format library provides a class for formatting arguments according to a format-string, as does printf, but with two major differences :
 
format sends the arguments to an internal stream, and so is entirely type-safe and naturally supports all user-defined types.
The ellipsis (...) can not be used correctly in the strongly typed context of format, and thus the function call with arbitrary arguments is replaced by successive calls to an argument feeding operator%
scott@slp53.sl.home (Scott Lurndal): Dec 16 03:19PM

>printf. Go ahead and use cout if you prefer, but don't claim it's the modern replacement for printf."
 
>I have tried to cut my printf usage to very basic functions that get called a lot so they are fairly well tested. Printf usege in an
>error message is a bad idea, IMHO.
 
Of course, other opinions may differ. [sn/f]printf is far more readable, far more usable
and far more efficient than output streams.
Christopher Pisz <nospam@notanaddress.com>: Dec 16 10:27AM -0600

On 12/15/2014 6:00 PM, Lynn McGuire wrote:
> and it certainly doesn't exemplify modern C++ as envisioned by C++11 and
> beyond. The oldest C++ textbook on my shelf was printed in 1993 and
> covers cout.
 
1992 was when it made it in officially if memory serves.
 
I even posed the question to some C++ historians and they
> were able to date it back as far as 1989.
 
Perhaps before the library became standard.
 
Therefore, the argument that
> printf is old and cout is modern doesn't fly.
 
Philosophically unsound argument. Your premise is incorrect, but even if
it was your premises are the wrong ones.
 
printf is C plain and simple. Hence why you have to include the cstdio
header it requires! That's "C standard input output"...derp or in the
case of those who refuse to change, stdio.h
 
A truly modern C++
> solution would also not be substantially slower than hand-written code.
 
Says who? What exactly is substantial?
 
> Most printf implementations today provide adequate type checking both at
> compile time and run time.
 
Bullshit. Spent 6 months tracking down problems that boiled down to
unsafe usage of printf just last year. To my surprise (not really), it
was another stubborn C programmer that littered the code with printf and
sprintf, because he refused to change his ways.
 
Visual C++ even provides secure versions that
> make it quite straightforward to write defensive code quite easily with
> printf.
 
Let's use non portable code to fix the problem.
 
Go ahead and use cout if you prefer, but don't claim it's the
> modern replacement for printf."
 
It is, get over it.
Why are C programmers so stubborn? They'll argue to the death over the
most trivial things.
 
Christopher Pisz <nospam@notanaddress.com>: Dec 16 10:30AM -0600

On 12/16/2014 9:19 AM, Scott Lurndal wrote:
> Lynn McGuire <lmc@winsim.com> writes:
SNIP
> Of course, other opinions may differ. [sn/f]printf is far more readable, far more usable
> and far more efficient than output streams.
 
I don't mind if C programmers unite, but don't do it pretending to be
C++ programmers and don't outright lie.
 
Far more readable? Far more usable? Are you kidding me?
We can argue efficiency maybe, but the former two have absolutely no basis.
Jorgen Grahn <grahn+nntp@snipabacken.se>: Dec 16 05:22PM

On Tue, 2014-12-16, Lynn McGuire wrote:
> http://kennykerr.ca/2014/12/08/in-defense-of-printf/
 
>> Therefore, the argument that printf is old and cout is modern doesn?t
>> fly.
 
Printf doesn't work with user-defined types, and user-defined types
are central to writing good C++. /That's/ why people don't like
printf.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Paavo Helde <myfirstname@osa.pri.ee>: Dec 16 11:29AM -0600


> I have tried to cut my printf usage to very basic functions that get
> called a lot so they are fairly well tested. Printf usege in an error
> message is a bad idea, IMHO.
 
In general, I also like the printf style better than C++ streams. Almost
all my error messages are formatted printf-style. However, I am using a
typesafe implementation in C++ (similar to Boost.Format) to avoid all the
drawbacks of printf(). This way it is even slower than with streams as lots
of run-time checks and conversions are involved. So in general it is good
*only* for formatting error messages ;-)
 
Cheers
Paavo
Paavo Helde <myfirstname@osa.pri.ee>: Dec 16 11:53AM -0600

Jorgen Grahn <grahn+nntp@snipabacken.se> wrote in
 
> Printf doesn't work with user-defined types, and user-defined types
> are central to writing good C++. /That's/ why people don't like
> printf.
 
On the other hand, the stream version assumes that you always want to
stream your objects in the same way to text. In my experience, I always
need multiple ways for representing the object textually, e.g. as a
description, as an expression, as some kind of XML serialization, as a
MD5 hash, etc.
 
While there are probably ways to define custom manipulators for the
stream to get different texts, it seems to me way easier to just add
different member functions for the class returning the needed strings.
And if one has already got those member functions returning strings,
there is nothing prohibiting using them in printf as well.
 
So the user-defined types can be used with printf style without any
problems. To have type safety and avoid littering the code with c_str()
calls one should of course use Boost.Format or equivalent instead of
plain printf().
 
Cheers
Paavo
legalize+jeeves@mail.xmission.com (Richard): Dec 16 05:56PM

[Please do not mail me a copy of your followup]
 
Jorgen Grahn <grahn+nntp@snipabacken.se> spake the secret code
 
>Printf doesn't work with user-defined types, and user-defined types
>are central to writing good C++. /That's/ why people don't like
>printf.
 
Plus it isn't type-safe and it doesn't work well with localization.
 
If you prefer the conciseness of a printf style format string, then
use Boost.Format.
 
There are legitimate complaints about the speed of iostreams vs. stdio
and there are cases where this difference really matters. In the
tests I've seen, the comparison was between printf and the stream
insertion operator. The benchmark was pretty clear about the results.
What I never gained from such tests is *why* the stream insertion
operator was slower. I'm not yet convinced that the stream insertion
is *intrinsically* slower than printf, but I am convinced that
specific implementations are slower. The compiler has access to much
more code optimization opportunities with stream insertion than with
printf, so perhaps as the compilers get better, stream insertion will
simply outperform printf someday.
 
It is already the case that libraries like Boost.Spirit, which are
heavily based in C++ templates, can outperform C library functions
like itoa and atoi.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
scott@slp53.sl.home (Scott Lurndal): Dec 16 06:31PM

>> and far more efficient than output streams.
 
>I don't mind if C programmers unite, but don't do it pretending to be
>C++ programmers and don't outright lie.
 
I'm sorry, I don't understand your comment. I've been programming,
for pay in C++ since 1989. Very large codebases (operating systems,
hypervisors, simulators and large X.509 suites).
 
 
>Far more readable? Far more usable? Are you kidding me?
 
Yes, far more readable. Consider:
 
lp->log("%-132.132s\n", start);
 
or
 
bytecount = snprintf(tbp, tbsize, " [%6.6llx:%6.6llu]",
gethex(p_operands[1]->getaddress(), 6),
getdigits(p_operands[1]->getaddress()+6, 6));
 
The equivalent output stream version resembles COBOL in
terms of unnecessary verbosity (although in reality, COBOL
picture clauses are much more similar to *printf than cout).
 
I find your insistence on the "purity" of C++ to be completely
silly. One uses a language to accomplish a task. As the
*printf functions have been legitimately used in C++ code for
almost three decades, there seems little reason to use the
less readable and more verbose output streams particularly
given the performance constraints on most of the C++ software
that I'm responsible for.
Jorgen Grahn <grahn+nntp@snipabacken.se>: Dec 16 06:47PM

On Tue, 2014-12-16, Paavo Helde wrote:
> stream your objects in the same way to text. In my experience, I always
> need multiple ways for representing the object textually, e.g. as a
> description, as an expression, as some kind of XML serialization,
 
I rarely need that, but yes, it happens often enough to be a problem.
 
> as a MD5 hash, etc.
 
That's not a valid case IMHO -- you should have a way to hash your
object into a class MD5Hash, or something. /That/ one can be printed.
 
> different member functions for the class returning the needed strings.
> And if one has already got those member functions returning strings,
> there is nothing prohibiting using them in printf as well.
 
Simpler IMO to just provide member functions:
 
ostream& put_form1(std::ostream&);
ostream& put_form2(std::ostream&);
ostream& put_form3(std::ostream&);
 
But that's because my "smaller" types are also ostream-compatible
rather than printf- or to_string-compatible.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
legalize+jeeves@mail.xmission.com (Richard): Dec 16 06:55PM

[Please do not mail me a copy of your followup]
 
(Richard) legalize+jeeves@mail.xmission.com spake the secret code
>>are central to writing good C++. /That's/ why people don't like
>>printf.
 
>Plus it isn't type-safe and it doesn't work well with localization.
 
And I almost forgot: it's a long-standing source of hard crash bugs,
which is why the compilers are doing their best these days to analyze
such things and alert you to the sources of error.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
Ian Collins <ian-news@hotmail.com>: Dec 17 08:13AM +1300

Scott Lurndal wrote:
 
> The equivalent output stream version resembles COBOL in
> terms of unnecessary verbosity (although in reality, COBOL
> picture clauses are much more similar to *printf than cout).
 
While undoubtedly true for cases involving fixed format numeric output,
the reverse is true for outputting user defined types or output in
generic code.
 
--
Ian Collins
Luca Risolia <luca.risolia@linux-projects.org>: Dec 16 09:01PM +0100

Il 16/12/2014 19:31, Scott Lurndal ha scritto:
 
> The equivalent output stream version resembles COBOL in
> terms of unnecessary verbosity (although in reality, COBOL
> picture clauses are much more similar to *printf than cout).
 
I wonder what would be the equivalent version in C++ in your opinion.
scott@slp53.sl.home (Scott Lurndal): Dec 16 08:03PM


>While undoubtedly true for cases involving fixed format numeric output,
>the reverse is true for outputting user defined types or output in
>generic code.
 
When I need to dump a "user defined type" (aka class), I use a
member function that formats the relevent member data using snprintf;
in larger projects, an pure abstract class defines the member function
name (a la a java interface). This isn't really different from
using templated outputstream formatters.
 
Works fine; just doesn't require an ostream or string stream
(which in my experience is a good thing, since I find C++ I/O
pretty much useless for real applications, preferring to use the
posix[*] interfaces (pread/pwrite/mmap/poll/epoll) instead).
 
[*] I'm fortunate in that I've never been required to program under
a windows operating system in the last forty years of
programming, aside from a couple of optical storage (WORM) device drivers for
NT 3.51 back in the mid 90's as a consultant.
Luca Risolia <luca.risolia@linux-projects.org>: Dec 16 09:07PM +0100

Il 16/12/2014 16:19, Scott Lurndal ha scritto:
 
> Of course, other opinions may differ. [sn/f]printf is far more readable, far more usable
> and far more efficient than output streams.
 
The opposite is almost always true. streams are also type-safe (although
nothing forbids to implement a type safe version of printf in C++11).
Luca Risolia <luca.risolia@linux-projects.org>: Dec 16 09:14PM +0100

Il 16/12/2014 21:07, Luca Risolia ha scritto:
> Il 16/12/2014 16:19, Scott Lurndal ha scritto:
> The opposite is almost always true. streams are also type-safe (although
> nothing forbids to implement a type safe version of printf in C++11).
 
Furthermore there is no way for a classic C printf implementation to be
faster than the C++ counterpart using variadic templates. Guess why.
"Öö Tiib" <ootiib@hot.ee>: Dec 16 12:16PM -0800

On Tuesday, 16 December 2014 02:00:40 UTC+2, Lynn McGuire wrote:
> "In defense of printf"
> http://kennykerr.ca/2014/12/08/in-defense-of-printf/
 
You must be bored. ;)
 
> "Folks seem to enjoy pointing out that I use printf in many of my
> examples of "modern C++", as if printf is not really proper C++.
 
Since C++ does not have anything useful in standard set the 'printf'
is as perfect for usage in illustration code of raw C++ as is 'cout'.

> Apparently, I should be using cout.
 
It is sort of like discussing how good 'malloc' is compared to 'new'
when we can use neither in actual C++ code (unless we write standard
library or something competing with standard library) and it seems that
we only gain from avoiding those.
 
> The trouble is that cout isn't exactly modern either. It has been
> around for as long as I can remember and it certainly doesn't
> exemplify modern C++ as envisioned by C++11 and beyond.
 
Yeah, pot vs kettle.
 
> cout. I even posed the question to some C++ historians and they were
> able to date it back as far as 1989. Therefore, the argument that
> printf is old and cout is modern doesn't fly.
 
Indeed, poop vs feces here.
 
> straightforward to write defensive code quite easily with printf. Go
> ahead and use cout if you prefer, but don't claim it's the modern
> replacement for printf."
 
I don't understand. Both are dead without resurrection possible. Let
me evaluate ...
 
'printf' format becomes quickly complex and cryptic when the format
specifiers are something else and more detailed than the '%d' and '%s'.
Scott Lurndal already beat me in posting his oh so readable examples
else-thread. The format specifiers don't specify everything; we need
things like 'strftime' just to output time etc. also somewhere
underneath a locale is screwing things over. However the 'cout' I/O
manipulators are additionally annoyingly verbose so Scott is right
that we get COBOL trying to format raw numbers using those. 'cout' is
no way more familiar with 'struct tm' than 'printf' so sorry but
no sugar and it is screwed up by locale as deep.
 
Oh. But we next to never have raw context-free numbers exposed in C++.
So we run to extend 'cout' by overloading 'operator<<(ostream,Foo const&)'
*Terrible* idea. Especially devastating with novice in charge plus
dynamic or static polymorphism and/or any forms of implicit
conversions. They stare and debug it for hours and only positive outcome
is that learn to hate 'cout' with passion.
 
Soon we then pick the bit cleaner way out of it by making everywhere
things like 'Foo.asText(optional_specifiers)'. As ultimate result we
cut most features of both 'printf' and 'cout'. We use only '%s'
with 'printf' and only 'operator<<(ostream,string const&)' with 'cout'.
 
Hmm. What we now got? Big pile of unneeded bloat features underneath
dragging down our application's efficiency on *both* cases. And since
we are down to strings only it is now simple to verify that even
'operator+' of 'std::string' beats them both. :D
 
> I have tried to cut my printf usage to very basic functions that
> get called a lot so they are fairly well tested. Printf usege in
> an error message is a bad idea, IMHO.
 
There are no reason to use these in human interface when there is
anything more comfortable (QString, Boost.Format, your own lib,
whatever) available (and that must be is always the case).
There are no point to use these for structured text (like XML,
JSON, whatever). No well-performing parser/generator can result.
 
Only two usages I can see: For constructing cryptic code to ensure
job security for ourselves and for usage in academic raw C++
example codes for to screw schoolboys and enforce them to think
about ways out of that excrement.
Ian Collins <ian-news@hotmail.com>: Dec 17 09:38AM +1300

Scott Lurndal wrote:
> in larger projects, an pure abstract class defines the member function
> name (a la a java interface). This isn't really different from
> using templated outputstream formatters.
 
Which is all fine and dandy until you want dump the class in a function
template...
 
--
Ian Collins
scott@slp53.sl.home (Scott Lurndal): Dec 16 09:21PM

>> terms of unnecessary verbosity (although in reality, COBOL
>> picture clauses are much more similar to *printf than cout).
 
>I wonder what would be the equivalent version in C++ in your opinion.
 
lots of "<<" operators. Lots of useless verbiage to set field
widths (std::setw), std::showbase, std::internal, std::setfill('0')
and data format (std::hex). And for this
use case, I'd need to use a string output stream, and convert
it back to bytes.
 
But the point is, that the *printf* family of functions is perfectly
cromulent, and perfectly legal to use in C++ programs.
scott@slp53.sl.home (Scott Lurndal): Dec 16 09:25PM

>> and far more efficient than output streams.
 
>The opposite is almost always true. streams are also type-safe (although
>nothing forbids to implement a type safe version of printf in C++11).
 
The type-safety argument is overblown. Particularly since the compilers have
had the capability to warn about mismatched format arguments for almost
two decades.
 
Readability is in the eye of the beholder, obviously. But in all
my real-world C++ experience, I've never seen a project outside of
some class project or new-hire code that even used C++ formatted I/O
instead of snprintf; and I find snprintf much easier to read and
especially to write than the redefinition of the bit shift operator
into some sort of magic I/O operator.
scott@slp53.sl.home (Scott Lurndal): Dec 16 09:28PM

>> nothing forbids to implement a type safe version of printf in C++11).
 
>Furthermore there is no way for a classic C printf implementation to be
>faster than the C++ counterpart using variadic templates. Guess why.
 
Please enlighten us. How is:
 
std::cout << std::showbase << std::internal << std::setfill('0') << std::hex << std::setw(8)
<< x << endl;
 
more efficient or more readable than:
 
printf("0x%x\n", x);
 
?
Barry Schwarz <schwarzb@dqel.com>: Dec 15 04:02PM -0800


>Hi. I'm new to c and c++. I am coming from the world of Modula-2 and
>Ada and I'm trying to understand the following syntax
 
Trying to learn both languages at the same time can be confusing. The
languages have just enough similarity to lead newcomers in the wrong
direction when trying to use a construct from one in the other.
 
Pick one language. Get comfortable with it. Then tackle the other.
 
--
Remove del for email
Ian Collins <ian-news@hotmail.com>: Dec 16 02:01PM +1300

Ian Collins wrote:
 
> Note many coding standards reserve all cast for macro names, not
> class/struct names.
 
That should have said "reserve all caps"...
 
--
Ian Collins
Robert Wessel <robertwessel2@yahoo.com>: Dec 15 07:51PM -0600

>_win_border_struct, but instead uses the WIN_BORDER identifier.
 
>So my question is, what is the difference between the identifier that
>follows struct and the one that follows the closing }?
 
 
If you had just a stand alone struct definition:
 
struct struct_name {int a; int b;} struct_instance;
 
The name after the closing brace is, in fact, creating and naming of
an instance of the struct. In this example, there is a structure type
named struct_name defined, and an instance of struct_name called
struct_instance is created.
 
In a typedef:
 
typedef struct struct_name {int a; int b;} typedef_name;
 
You cannot create an actual instance of the structure, and the name
after the closing brace is the name of the new type. So in the above
typedef_name is an alias for "struct struct_name".
 
Now that will work in both C and C++, but in C++ the struct defintion
automatically creates a typename (the same as the structure name). So
in either case, in C++, a type named struct_name will be created (and
in the second example typedef_name will be created as well).
 
In C++ you would usually avoid the explicit typedef.
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: