- Help improving this little function, if necessary. - 4 Updates
- "Bjarne Stroustrup announces C++ Core Guidelines" - 4 Updates
- "Breaking all the Eggs in C++" by Scott Meyers - 4 Updates
- Newfangled constructs - 10 Updates
- return the name of the class - 1 Update
- scandir help - 2 Updates
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:
Post a Comment