Wednesday, November 18, 2015

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

Noob <dontspam@me.com>: Nov 18 07:30PM -0200

Hi there,
 
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.
 
int eval_lgk(const std::vector<int> coords,
const std::vector<double>factsgk) {
 
unsigned int nvars = coords.size();
std::vector<double> temp(coords.size()-1);
 
for (unsigned int i = 0; i < nvars-2; i++)
{
temp[i] = factsgk[i] * ( coords[i] - 1.0 );
}
 
return coords[nvars-1] +
std::accumulate(temp.begin(),temp.end(),0.0);
 
}
 
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.
 
Is it possible to get rid of the temp vector? Would it help?
 
Thank you for any help.
 
P.s: I'd also be grateful for any general advices about this little
piece of code.
Noob <dontspam@me.com>: Nov 18 07:36PM -0200

On 18/11/2015 19:30, Noob wrote:
 
> Thank you for any help.
 
> P.s: I'd also be grateful for any general advices about this little
> piece of code.
 
Oops: The types of factsgk and of temp should be int.
Paavo Helde <myfirstname@osa.pri.ee>: Nov 18 03:47PM -0600

> badly written.
 
> int eval_lgk(const std::vector<int> coords,
> const std::vector<double>factsgk) {
 
For speed, you probably want to use references instead of copying the
whole vectors (const std::vector<int>& coords, etc).
 
 
> unsigned int nvars = coords.size();
 
Wrong type. The correct type (in practice) is size_t, which is even less
to type than 'unsigned int'.
 
> std::vector<double> temp(coords.size()-1);
 
This will fail if coords is empty. One should have either a check-and-
throw-exception or an assert for that. If speed is critical, use an
assert which is compiled only in debug builds.
 
 
> for (unsigned int i = 0; i < nvars-2; i++)
 
Will fail if nvars<2; again, check or assert. Also, it seems that the
last element of temp is not used, so there was no need to allocate it.
 
> }
 
> return coords[nvars-1] +
> std::accumulate(temp.begin(),temp.end(),0.0);
 
You are collecting something in the temp array, only to sum it up later.
If the arrays are large, this means unneeded memory footprint and reduced
performance. Why don't you sum it during the loop?
 
> 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.
 
> Is it possible to get rid of the temp vector? Would it help?
 
Sure you can get rid of it, it has no use. If it helps with speed - no
idea, you have to measure.
Ian Collins <ian-news@hotmail.com>: Nov 19 10:56AM +1300

Noob wrote:
> badly written.
 
> int eval_lgk(const std::vector<int> coords,
> const std::vector<double>factsgk) {
 
It would be more idiomatic and maybe faster (depending on how well the
code gets optimised or inlined) to pass by const reference here.
 
> unsigned int nvars = coords.size();
 
A good candidate for "const auto"
 
> std::vector<double> temp(coords.size()-1);
 
Does this add any value? Can't you sum as you go in the loop?
 
> for (unsigned int i = 0; i < nvars-2; i++)
 
What if nvars < 2??
 
--
Ian Collins
"Tobias Müller" <troplin@bluewin.ch>: Nov 18 06:39AM

> definition before use where the data members are used in an in-class
> function definition, whether that function is member or friend.
 
> The convention of placing data members last doesn't cover that case.
 
Consequently I never use in-class function definitions (except for some
rare cases where the body is empty and I'm lazy).
 
IMO even the most simple in-class function definitions hurt the readability
of a class definition.
 
And yes, I prefer reading header files to a generated doxygen. Especially
because the header is always up to date and just one "go to definition"
away.
 
Tobi
Juha Nieminen <nospam@thanks.invalid>: Nov 18 09:12AM

> Consequently I never use in-class function definitions (except for some
> rare cases where the body is empty and I'm lazy).
 
In general, yes. However, with some complex template classes it can become
quite a nuisance to have to write half a dozen lines of code for something
that would be a one-liner in-class. Especially if you have lots of such
very short functions.
 
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
"Öö Tiib" <ootiib@hot.ee>: Nov 18 01:40AM -0800

On Wednesday, 18 November 2015 00:49:28 UTC+2, Alf P. Steinbach wrote:
> > And those are usually outside of the class definition body.
 
> I think it's a good idea to use a single convention instead of multiple
> conventions, when it's practical to use a single one.
 
That is indeed good idea but it seems to contradict with what you further
say. Might be my bad English.
 
> The convention of placing data members up top covers the case of having
> definition before use where the data members are used in an in-class
> function definition, whether that function is member or friend.
 
When the member functions and friend functions are defined sometimes
in-class but sometimes outside of class then that is not single
convention. Always in class however seriously clutters any real pieces
of code. Therefore function definitions always outside of class is
sole candidate of single convention here?
 
 
> The convention of placing data members last doesn't cover that case.
 
I do not see how. All the data members (when there are any) can be
always put as the very last (between last 'private:' and '};') in
class definition. Often these can not be put very first (before
nested type definitions).
Jorgen Grahn <grahn+nntp@snipabacken.se>: Nov 18 09:08PM

On Tue, 2015-11-17, Chris Vine wrote:
>> misleading.
 
> It doesn't mean that. It means "I can't use foo to modify the 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 simplified by ignoring the case where you can const_cast foo,
because it's a very rare thing to do.)
 
> want to confuse the basic point that const does not mean pure,
> 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,
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
"Lőrinczy Zsigmond" <zsiga@nospam.for.me>: Nov 18 10:18AM +0100

On 2015-11-17 01:50, Lynn McGuire wrote:
> "Breaking all the Eggs in C++" by Scott Meyers
> http://scottmeyers.blogspot.com/2015/11/breaking-all-eggs-in-c.html
 
You should realise that C++ isn't mature yet,
it does change even in trivial things like 0/NULL/nullptr.
Cholo Lennon <chololennon@hotmail.com>: Nov 18 04:06PM -0300

On 11/18/2015 06:18 AM, Lőrinczy Zsigmond wrote:
>> "Breaking all the Eggs in C++" by Scott Meyers
>> http://scottmeyers.blogspot.com/2015/11/breaking-all-eggs-in-c.html
 
> You should realise that C++ isn't mature yet,
 
Could you provide an example of a mature programming language?
 
> it does change even in trivial things like 0/NULL/nullptr.
 
Why not? Paradigms and good practices change, evolve, like the
programming languages...
 
 
--
Cholo Lennon
Bs.As.
ARG
Paavo Helde <myfirstname@osa.pri.ee>: Nov 18 01:13PM -0600

=?UTF-8?B?TMWRcmluY3p5IFpzaWdtb25k?= <zsiga@nospam.for.me> wrote in
>> http://scottmeyers.blogspot.com/2015/11/breaking-all-eggs-in-c.html
 
> You should realise that C++ isn't mature yet,
> it does change even in trivial things like 0/NULL/nullptr.
 
You meant to say it is not *dead* yet. A living language needs to change,
if not for other reasons then because the world is changing. And the whole
point of Scott Meyers is to propose a way for changing the language without
a fear of entropy death under the accumulated mass of obsolete features.
 
Cheers
Paavo
scott@slp53.sl.home (Scott Lurndal): Nov 18 09:03PM

>>> http://scottmeyers.blogspot.com/2015/11/breaking-all-eggs-in-c.html
 
>> 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?
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Nov 18 07:04PM

The newfangled ranged based for loops whilst dinky and useful do have an
irritating niggle: how to break out of nested loops?
 
We could write:
 
bool found = false;
for (auto& e1 : seq1)
{
for (auto& e2 : seq2)
{
if (e2 == 42)
{
found = true;
break;
}
}
if (found)
break;
}
 
This solution is plain is ugly.
 
We could try using the infamous goto keyword:
 
for (auto& e1 : seq1)
{
for (auto& e2 : seq2)
{
if (e2 == 42)
goto found;
}
}
found:
 
This solution is brittle from a maintenance point of view even if this
is about the only sane use-case for the goto keyword.
 
We could of course be slightly more traditional:
 
bool found = false;
for (auto i = seq1.begin(); !found && i != seq1.end(); ++i)
{
for (auto j = seq2.begin(); !found && j != seq2.end(); ++j)
{
if (*j == 42)
found = true;
}
}
 
But alas we are no longer using the range based for loop and have
introduced the extra level of iterator indirection; annoying.
 
We could perhaps change the language syntax and introduce an OPTIONAL
conditional expression:
 
bool found = false;
for (auto& e1 : seq1; !found)
{
for (auto& e2 : seq2; !found)
{
if (e2 == 42)
found = true;
}
}
 
But I am not convinced. What to do sausages? :/
 
/Flibble
Gareth Owen <gwowen@gmail.com>: Nov 18 07:20PM

> }
> }
 
> But I am not convinced. What to do sausages? :/
 
Share your distaste for the narrow applicability of range base loops.
 
How about:
for ((auto& e1 : seq1)
&& conditional_1
&& conditional_2)
{
}
 
I'd also like to do the following, to add to row-vectors say
 
for(auto& x: vec1, auto& y: vec2, auto& z = vec3){
z = x+y;
}
 
for simultaneous iteration - i.e. which expands to
 
for(_x = vec1.begin(), _y = vec2.begin(), _z = vec3.begin();
_x != vec1.end(), _y != vec2.end(), _z != vec3.end();
++_x, ++_y, ++_z)
{
*_z = *_x + *_y;
}
 
> /Flibble
 
Sausages
Paavo Helde <myfirstname@osa.pri.ee>: Nov 18 01:27PM -0600

Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk> wrote in
 
> The newfangled ranged based for loops whilst dinky and useful do have
an
> }
> }
 
> But I am not convinced. What to do sausages? :/
 
The 'found' variable here is artificial and increases the complexity of
the program for no reason. I would use 'goto'.
 
Another option is to place the inner loop in a different function, but
this would also increase the complexity of the program unnecessarily if
the new function does not serve a clear standalone task.
Daniel <danielaparker@gmail.com>: Nov 18 11:29AM -0800

On Wednesday, November 18, 2015 at 2:04:49 PM UTC-5, Mr Flibble wrote:
> break;
> }
 
> This solution is plain is ugly.
 
How about an elegant juxtaposition of old and new?
 
jmp_buf env;
int val = setjmp(env);
 
if (val == 0)
{
for (auto& e1 : seq1)
{
for (auto& e2 : seq2)
{
if (e2 == 42)
{
longjmp(env,1);
}
}
}
}
 
Daniel
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Nov 18 07:32PM

On 18/11/2015 19:29, Daniel wrote:
> }
> }
> }
 
Not compatible with destructors AFAIK sausages.
 
/Flibble
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Nov 18 07:34PM

On 18/11/2015 19:20, Gareth Owen wrote:
> && conditional_2)
> {
> }
 
Perhaps.
 
> {
> *_z = *_x + *_y;
> }
 
That would be very nice indeed sausages.
 
/Flibble
Daniel <danielaparker@gmail.com>: Nov 18 11:53AM -0800

On Wednesday, November 18, 2015 at 2:32:56 PM UTC-5, Mr Flibble wrote:
 
> Not compatible with destructors AFAIK sausages.
 
Sadly, no.
 
Daniel
Cholo Lennon <chololennon@hotmail.com>: Nov 18 05:24PM -0300

On 11/18/2015 04:04 PM, Mr Flibble wrote:
> }
 
> But I am not convinced. What to do sausages? :/
 
> /Flibble
 
I still prefer the goto solution, it's clearer and faster :-) (note
that Java for example, doesn't have goto, but it has "break label;" for
these cases)
 
Regards
 
--
Cholo Lennon
Bs.As.
ARG
scott@slp53.sl.home (Scott Lurndal): Nov 18 09:02PM

> }
>}
 
>Daniel
 
Substitute 'throw' for longmp and wrap
the outer loop in a try/catch.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 18 10:02PM +0100

On 11/18/2015 8:04 PM, Mr Flibble wrote:
> break;
> }
 
> This solution is plain is ugly.
 
Agreed.
 
 
 
> found:
 
> This solution is brittle from a maintenance point of view even if this
> is about the only sane use-case for the goto keyword.
 
I have no qualms about the "goto" here. Every other construct for this
is just euphemistic code to avoid writing the "goto" in clear. IMHO.
 
 
> [snip]
> But I am not convinced. What to do sausages? :/
 
I'd just write the "goto".
 
It's the same way as e.g. the use of "#include": one is implementing a
higher level language construct manually.
 
But if the word offends, then you can do this:
 
bool const found = [&]() -> bool
{
for( auto& e1 : seq1 )
{
for( auto& e2 : seq2 )
{
if( e2 == 42 ) { return true; }
}
}
return false;
}();
// Use "found" here.
 
Well, OK, that wasn't so bad as I feared.
 
 
Cheers & hth.,
 
- Alf
Lynn McGuire <lmc@winsim.com>: Nov 18 02:23PM -0600

On 11/15/2015 3:11 PM, Vladislav Yaroslavlev wrote:
 
>> Thanks,
>> Lynn
 
> There is no standardised way. Depends on your compiler.
 
Yup, bummer. One would think that the C++ standards committee would have this now.
 
Thanks,
Lynn
agent@drrob1.com: Nov 18 06:54AM -0500

I am trying to learn how to use scandir with c++ on Ubuntu 14.04. I
have been able to get the example in the man page working, but this
does not use a filter. I'm trying to understand how to use the filter
param. I found code online and works, but I don't understand what it
is doing and how to make it more flexible. Fragments of my attempts
to understand what is going on remain below. The template of scandir
says it takes a filter function. I have found that if this filter
function does not have a const dirent * param, it will not compile
under gcc. Needless to say, I don't always (are really ever) care
about files that begin with 'a'. I am interested in, say, files that
end in ".txt" but I don't understand what's needed here.
 
I am coming to C++ after many years of modula-2 programming with
stonybrook m-2. Pointers in m-2 are much easier to understand.
Pointers in C++ are much more complex. This confusion is compounded
by the lack of a proper array type in C++. So pointers are used much
more extensively than in the Wirthian languages.
 
Thanks,
Rob
 
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/param.h>
#include <stdio.h>
#include <unistd.h>
#include <cstring>
#include <cstdio>
#include <fstream>
#include <sstream>
#include <iostream>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <ctime>
#include <string>
using namespace std;
 
char pathname[MAXPATHLEN];
char input[MAXPATHLEN];
int * result;
 
// From example I found online
int filter(const dirent * filterpattern)
{
return (filterpattern->d_name[0] == 'a');
}
 
int main()
{
int count,i;
dirent * * files;
dirent * filterpattern;
char * CurrentPathName;

CurrentPathName = getcwd(pathname,MAXPATHLEN);
if (pathname == NULL )
{
cout << "Error getting path" << endl;
exit(0);
}
 
filterpattern = new dirent; // almost forgot that I have to
allocate this.

cout << "Current Working Directory = " << pathname << ", " <<
CurrentPathName << ", MAXPATHLEN = " << MAXPATHLEN << endl;
 
count = scandir(".", & files, filter, alphasort);
 
if (count <= 0)
{
cout << "No files in this directory" << endl;;
exit(0);
}
 
cout << "Number of files = " << count << endl;
for (i=0; i < count-1; ++i)
{
cout << files[i]->d_name << ", ";
free(files[i]);
}
 
cout << files[i]->d_name << endl;
free(files);
}
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 18 02:30PM +0100

> I am trying to learn how to use scandir with c++ on Ubuntu 14.04.
 
Use Boost file system library.
 
 
 
> #include <sys/types.h>
> #include <sys/dir.h>
> #include <sys/param.h>
 
All the above are system specific, non-portable. Avoid that by using
Boost file system library.
 
> using namespace std;
 
> char pathname[MAXPATHLEN];
> char input[MAXPATHLEN];
 
Global variables are ungood. Raw arrays are ungood. MAXPATHLEN is
system-specific, non-portable; avoid that by using Boost file system
library.
 
 
> int * result;
 
Global variables are ungood. Uninitialized pointers are ungood.
 
 
> {
> return (filterpattern->d_name[0] == 'a');
> }
 
This returns logical True if the first letter of d_name is "a". For C++
and C99 and later the function result type should be "bool".
 
 
> {
> cout << "Error getting path" << endl;
> exit(0);
 
Exit value 0 means success. Exit with `EXIT_FAILURE` or a non-zero
system specific value to indicate failure. And in "main", just "return":
that invokes "exit" automatically.
 
 
> }
 
> filterpattern = new dirent; // almost forgot that I have to
> allocate this.
 
No, you don't have to allocate the "dirent" dynamically. You could and
should just declare it as a local variable. But at a higher level, you
shouldn't be doing this at all: avoid all that by using the Boost file
system library.
 
 
> cout << "Current Working Directory = " << pathname << ", " <<
> CurrentPathName << ", MAXPATHLEN = " << MAXPATHLEN << endl;
 
In Windows a "char" based string is not sufficient to hold an arbitrary
path. So for Windows you need to use wide strings. The Boost file system
library does that automatically for you.
 
 
 
> cout << files[i]->d_name << endl;
> free(files);
> }
 
Cheers & hth.,
 
- ALf
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: