Thursday, November 19, 2015

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

Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Nov 18 11:42PM

On 18 Nov 2015 21:08:04 GMT
> > object foo points to".
 
> Sorry; I can't see the difference, unless you mean foo->bar->baz = 1,
> which I agree would be fair to describe.
 
I do not know what 'foo->bar->baz = 1' refers to, as I have not seen
your Foo class definition (have I missed a post somewhere? - if so my
apologies). You said '"const Foo* foo" just means "I can't use 'foo'
to modify anything"'. I took from this (and from the posting to which
you were replying) that this was intended as a general statement about
the qualities of 'const', rather than about a particular Foo class
definition which I have not seen. Saying that foo cannot modify
anything is a statement that it is pure. Taken on that basis, what you
said was wrong. This is valid code, but it modifies 'a', 'b', and the
state of the output stream:
 
#include <iostream>
int a = 0;
struct Foo {
static int b;
int do_it1() const {++a; std::cout << a << '\n'; return a;}
int do_it2() const {++b; std::cout << b << '\n'; return b;}
};
int Foo::b = 0;
int main () {
const Foo* foo = new Foo;
foo->do_it1();
foo->do_it2();
delete foo;
}
 
> > irrespective of whether there is any mutable object data around.)
> > "const" does not mean "no side effects".
 
> I don't know what "pure" means either, to be honest,
 
It refers to the absence of side effects. It requires amongst other
things that a function only depend on its arguments (in particular, not
on mutable state), and that the same input value(s) should always
produce the same return value. No function returning void could be
pure, because otherwise it would not do anything. It enables many
compiler optimizations, including lazy evaluation, common subexpression
elimination and memoization, and (because it doesn't silently change
program state) makes programs easier to reason about and facilitates
safe concurrency - all pure functions are by definition thread safe).
D has a 'pure' keyword, for example. I think all constexpr functions
must in fact be pure (I must look that up some time), but there are
many pure functions which are not constexpr.
 
This is not to be confused with gcc's C function 'const' attribute,
which does require purity.
 
Chris
"Öö Tiib" <ootiib@hot.ee>: Nov 18 06:14PM -0800

On Thursday, 19 November 2015 00:27:07 UTC+2, Ian Collins wrote:
 
> > Consequently I never use in-class function definitions (except for some
> > rare cases where the body is empty and I'm lazy).
 
> So you never use templates?
 
AFAIK every member or friend function of class or class template
(also templates of such functions and inline functions) can be
defined outside of class definition. So the only question is if it
is worth doing on case of templates and inline functions.
scott@slp53.sl.home (Scott Lurndal): Nov 19 03:41PM


>> Consequently I never use in-class function definitions (except for some
>> rare cases where the body is empty and I'm lazy).
 
>So you never use templates?
 
While I write template functions, I've not yet encountered a case
where it was necessary to write a template class (as opposed to
_using_ one from a library).
 
I also place private data members at the top of the class, and
define inline functions after the class (which allows them to be
moved to a separate header file when circular dependencies exist).
 
Multiline functions within the class definition seriously impair
readability, IMO.
"Tobias Müller" <troplin@bluewin.ch>: Nov 19 08:13PM


> I'm using them more over the past year or two. I've
> found some minor advantages from going this route in
> terms of executable/binary code size.
 
I find this hard to believe. I still use inline functions in the header,
just not in the class body. Those should be equivalent.
 
> functions like less lines of code. Imo that makes
> the library or program, as a whole, easier to work
> with.
 
 
How so. I don't care about the size of the files as long as the *relevant*
part (the class definition) is concise.
By stuffing everything into the class body, you make it harder to work
with, not easier.
 
> The more compact form for the software
> also helps in terms of downloading/bandwidth.
 
Usually you use compression for that.
 
Tobi
"Tobias Müller" <troplin@bluewin.ch>: Nov 19 08:18PM

> non-template code, I prefer not to have inline protected or private
> inline function. The former may be heavily used in client code, so
> making them available to the optimiser for inlining makes sense.
 
I often use inline functions and templates, sure. Just not inside the class
body. It's equivalent but the same.
 
Tobi
"Tobias Müller" <troplin@bluewin.ch>: Nov 19 08:20PM

> I often use inline functions and templates, sure. Just not inside the class
> body. It's equivalent but the same.
 
*not* the same.
legalize+jeeves@mail.xmission.com (Richard): Nov 19 07:32PM

[Please do not mail me a copy of your followup]
 
Ben Bacarisse <ben.usenet@bsb.me.uk> spake the secret code
 
> "During 1973-1980, the language grew a bit: the type structure gained
> unsigned, long, union, and enumeration types, and structures became
> nearly first-class objects (lacking only a notation for literals)."[1]
 
Nice; thanks for the research. So why are we arguing about avoiding
solutions that have been available for 35 years?
--
"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>
Juha Nieminen <nospam@thanks.invalid>: Nov 19 09:16AM

> The newfangled ranged based for loops whilst dinky and useful do have an
> irritating niggle: how to break out of nested loops?
 
You put it into its own function (and use a return).
 
There's a reason why modern programming design guidelines instruct to split
code into smaller logical functions.
 
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
seeplus <gizmomaker@bigpond.com>: Nov 19 02:47AM -0800

On Thursday, November 19, 2015 at 6:04:49 AM UTC+11, Mr Flibble wrote:
> }
> }
> found:
 
Does that goto version work if you are going to actually use "found"?
Doesn't it end up at "found" if it does find... but also when it gets hit
at the end of the main for loop .... and there is no way of knowing which
event happened.
By coincidence yesterday I had to write a complicated version of this
using medium newfangled (! not with goto!) and there seems to be no way of escaping having a BOOL in there.
Luca Risolia <luca.risolia@linux-projects.org>: Nov 19 05:25PM +0100

On 18/11/2015 20:04, Mr Flibble wrote:
> }
> }
 
> But I am not convinced. What to do sausages? :/
 
lambdas?
 
bool found = [&] {
for (auto& e1 : seq1)
{
for (auto& e2 : seq2)
{
if (e2 == 42)
return true;
}
}
return false;
}();
red floyd <no.spam@its.invalid>: Nov 19 09:59AM -0800

On 11/18/2015 11:32 AM, Mr Flibble wrote:
 
> Not compatible with destructors AFAIK sausages.
 
> /Flibble
 
Alternatively:
 
try
{
for (auto& e1 : seq1)
{
for (auto& e2)
{
if (e2 == 42)
throw 42;
}
}
}
catch (int)
{
}
 
I'd almost prefer the goto. IMHO, breaking out of nested loops is
the only legitimate use of goto.
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Nov 19 07:28PM

On 19/11/2015 09:16, Juha Nieminen wrote:
 
> You put it into its own function (and use a return).
 
> There's a reason why modern programming design guidelines instruct to split
> code into smaller logical functions.
 
Unnecessary functional decomposition can often increase a program's
complexity and in this case it is only necessary due to a shortcoming in
the language's syntax sausages.
 
/Flibble
Juha Nieminen <nospam@thanks.invalid>: Nov 19 09:09AM


>>> You should realise that C++ isn't mature yet,
 
>>Could you provide an example of a mature programming language?
 
> ALGOL? Bliss-32? Focal? BPL? SPL?
 
Is "mature language" a synonym for "long ago dead fringe language"?
 
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
scott@slp53.sl.home (Scott Lurndal): Nov 19 03:37PM


>>>Could you provide an example of a mature programming language?
 
>> ALGOL? Bliss-32? Focal? BPL? SPL?
 
>Is "mature language" a synonym for "long ago dead fringe language"?
 
ALGOL is not at all dead, and is in production today at hundreds
of sites. Yes, the VAX is toast, so Bliss-32 (which was really
mainly used internally at DEC) is dead. Focal was widely used
in its day, with ports to PDP8, PDP11, VAX and others. There is
still a bit of BPL code running after 40 years. SPL (the systems
programming language for the HP-3000) has been dead for a while
to the best of my knowledge.
ram@zedat.fu-berlin.de (Stefan Ram): Nov 19 12:57AM

>Be sure to measure the right thing, though, i.e. be sure to ask your
>compiler to optimize for speed. Usually that's an option like "-O2". But
 
... and then try to optimize for memory.
 
Sometimes, it happens that the code then will fit into a
cache, and the code optimized for memory will actually
run faster that the code that was optimized for speed.
 
>Here you should
>* hint to the compiler to inline calls to this function, by using the
>keyword "inline",
 
Which might also actually slow down the code, when it
will not fit into a cache anymore after the inlining.
 
>The temporary vector is expensive because unlike `std::string`, a vector
>cannot use the short buffer optimization, and so the above code incurs a
>dynamic allocation -- really expensive in this context.
 
In other cases, when a function does not have to be
recursive or thread-safe, such a temp buffer might be
allocated once with static lifetime and reused.
ram@zedat.fu-berlin.de (Stefan Ram): Nov 19 11:15AM

> }();
> // Use "found" here.
>Well, OK, that wasn't so bad as I feared.
 
Can we also use something like »inline« on such function
expressions?
 
I thought about the same solution, but within a named
function that has the »inline« attribute.
 
In this case, the function call does not take place in an
inner loop, at least it is outside of the loop visible above.
Still, it would be good to know that the extra function wrapper
does not waste any run-time.
Juha Nieminen <nospam@thanks.invalid>: Nov 19 09:11AM

> #include <cmath>
> #include <ctime>
> #include <string>
 
I think you missed a few includes there. There are still plenty in the
standard (and system) library.
 
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 19 01:45AM +0100

On 11/18/2015 10:30 PM, Noob wrote:
 
> I'm new to C++, coming from Fortran. I'd like some help writing the
> following function in a way to improve speed, if it turns out to be to
> badly written.
 
For numerical operations using Fortran used to be a good way to speed up
things. Most numerical libraries started out as Fortran libraries. I
don't know how that is today, but I think going from Fortran to C++ is
not likely to /improve/ the speed significantly.
 
Anyway, the first and also second rule of optimization is to MEASURE.
 
Be sure to measure the right thing, though, i.e. be sure to ask your
compiler to optimize for speed. Usually that's an option like "-O2". But
consult your compiler's or IDE's documentation or GUI. Also define
"NDEBUG" to remove assertion checking. It's generally a good idea to
leave assertion checking on, but not in time-critical code.
 
 
> int eval_lgk(const std::vector<int> coords,
> const std::vector<double>factsgk)
 
Here you should
 
* hint to the compiler to inline calls to this function, by using the
keyword "inline",
 
* pass the arguments by reference to const, not by value.
 
Passing by value the arguments are (at least logically) copied, and such
copying involves expensive dynamic allocations unless it's optimized
away by the implementation.
 
 
> {
 
> unsigned int nvars = coords.size();
 
For clarity it's best to declare "nvars" as "const". Sprinkle "const"
liberally throughout your code, wherever possible. That way you can see
at a glance, up front, that that value will not be changing, and this
helps to understand the code faster, and avoid silly mistakes.
 
Also, at this point add
 
assert( nvars >= 2 );
 
Include the "<assert.h>" header for that.
 
If nvars is 0 then the declaration below will declare a really huge
"temp" vector, and if nvars <= 1 then the loop will likewise loop a
really large number of times.
 
 
> {
> temp[i] = factsgk[i] * ( coords[i] - 1.0 );
> }
 
Either this loop is incorrect, or else the declaration of "temp" is
incorrect (apart from the item type which you have explained in a
follow-up should be "int"). "temp" has nvars-1 items, but only nvars-2
items are assigned to.
 
By the way, although the compiler is almost sure to optimize this,
introducing a name for "coords.size()" and then calling "coord.size()"
again is a lost nano-optimization opportunity.
 
 
 
> return coords[nvars-1] +
> std::accumulate(temp.begin(),temp.end(),0.0);
 
Are you sure that the "factsgk[nvars-1]" value doesn't exist or should
be ignored?
 
Additionally, instead of using a temporary vector just accumulate the
sum in the loop.
 
The temporary vector is expensive because unlike `std::string`, a vector
cannot use the short buffer optimization, and so the above code incurs a
dynamic allocation -- really expensive in this context.
 
 
> In real cases, factsgk and coords will both have size of about 3 to
> 5, say, but this function will be called many, many times inside loops
> and I'd like to write it in a way I can get good speed.
 
A general speedup might possibly be achieved by deferring this work
until you have zillion or two postponed calls. Then you could do them
all in parallel in the graphics card. A little dirty yes but still.
 
But first, make the code clearly correct.
 
The "assert" macro is a good tool to employ for that.
 
 
Cheers & hth.,
 
- Alf
Ian Collins <ian-news@hotmail.com>: Nov 19 02:02PM +1300

Stefan Ram wrote:
>> keyword "inline",
 
> Which might also actually slow down the code, when it
> will not fit into a cache anymore after the inlining.
 
Which is why the inline keyword is pointless in this context.
 
--
Ian Collins
Noob <dontspam@me.com>: Nov 18 11:18PM -0200

On 18/11/2015 22:45, Alf P. Steinbach wrote:
 
> Cheers & hth.,
 
> - Alf
 
Thank you very much for all your remarks!
 
I apologize for posting a code with logic errors prior to C++ mistakes.
I know it is no excuse but the whole deal about array indexing starting
at 1 in Fortran and 0 in C++ lead me to some mistakes when I wrote the
code for my post. The temp array was there for no logic reason other
than the fact that it remained from another version of the snippet
I typed before posting the final version.
 
What I have at the moment now is this
 
int eval_lgk(std::vector<int>& coords, std::vector<int>& factsgk) {
 
assert( factsgk.size() == coords.size() && coords.size() >= 1 );
 
int partial = coords.back();
 
for (size_t i = 0; i < coords.size()-1; i++)
{
partial+= factsgk[i] * ( coords[i] - 1 );
}
 
return partial;
 
}
 
For the moment, I can say that working with arrays is easier in Fortran,
but then there are a lot of other things C++ is allowing me to do much
cleaner and quicker.
 
I suppose I can start afresh from this. Having this construct: An
element-wise vector multiplication, followed by a "reduction", is this
a good way to code it or can I use some more compact syntax which will
also let the compiler do possibly a better job?
 
Thanks!
Noob <dontspam@me.com>: Nov 18 11:19PM -0200

On 18/11/2015 20:36, Stefan Ram wrote:
>> I'd like to write it in a way I can get good speed.
 
> You already have good speed.
 
> If you really want to optimize: Start by using a profiler.
 
Will do.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 19 02:19AM +0100

On 11/19/2015 2:02 AM, Ian Collins wrote:
 
>> Which might also actually slow down the code, when it
>> will not fit into a cache anymore after the inlining.
 
> Which is why the inline keyword is pointless in this context.
 
Not pointless, but as mentioned, it's important to MEASURE.
 
This is a very short function that's called a zillion times, so inlining
is likely to improve things. This is precisely the kind of function that
machine code inlining is /for/. Still nothing's guaranteed: only
measuring can tell for sure, or reduce doubt about it.
 
In addition to being aware of the rôle of caching, one should be aware
that some compilers (like g++) take the "inline" hint very seriously,
while others may ignore it, so measuring should ideally be done for all
relevant compilers and target systems, etc.
 
Cheers,
 
- Alf
Ian Collins <ian-news@hotmail.com>: Nov 19 03:54PM +1300

Alf P. Steinbach wrote:
>>> will not fit into a cache anymore after the inlining.
 
>> Which is why the inline keyword is pointless in this context.
 
> Not pointless, but as mentioned, it's important to MEASURE.
 
It is pointless because the compiler generally knows better than the
programmer which functions to inline. It will be able to include
platform specifics in its choices.
 
> is likely to improve things. This is precisely the kind of function that
> machine code inlining is /for/. Still nothing's guaranteed: only
> measuring can tell for sure, or reduce doubt about it.
 
Which will result in in it being inlined whether the hint is there or not.
 
> that some compilers (like g++) take the "inline" hint very seriously,
> while others may ignore it, so measuring should ideally be done for all
> relevant compilers and target systems, etc.
 
All the more reason to avoid the hint - let the compiler choose.
 
Totally agree with measuring :)
 
--
Ian Collins
Paavo Helde <myfirstname@osa.pri.ee>: Nov 19 12:37AM -0600

> possible. I understand somewhere something will perform this loop, but
> I'm looking for something that will do it efficiently without me
> coding it.
 
You need to understand there is nothing special with STL algorithms, they
are mostly template code places in the header file so they get compiled
with exactly the same compiler and with exactly the same optimizer
options than your code. So your loop is most probably as good as theirs.
Just take care to use optimized builds in production and ensure that in
these builds the NDEBUG macro is defined (this switches the assert() line
off - but this probably does not matter anyway).
 
hth
Paavo
Nobody <nobody@nowhere.invalid>: Nov 19 12:28AM

On Mon, 16 Nov 2015 14:44:03 +0000, Scott Lurndal wrote:
 
>>How do I read the contents of a directory in Ubuntu 14.04?
 
> man readdir
 
man 3 readdir
 
Otherwise you might get the section 2 page. Which, to be fair, starts off
with:
 
DESCRIPTION
This is not the function you are interested in. Look at readdir(3) for
the POSIX conforming C library interface.
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: