1 2
5 6 7 8
arflech
He/Him
Joined: 5/3/2008
Posts: 1120
opps all I remembered was to optimize to the fullest (-O3, which I realize does make larger executables than -Os) and build for my processor (-march=pentium4)
i imgur com/QiCaaH8 png
Joined: 11/1/2007
Posts: 100
arflech wrote:
opps all I remembered was to optimize to the fullest (-O3, which I realize does make larger executables than -Os) and build for my processor (-march=pentium4)
The interesting thing is, it's possible to create code that actually runs faster with -Os if it ends up emitting blocks of code that can fit inside of the CPU's cache.
Joined: 4/13/2009
Posts: 431
arflech wrote:
It is not a good idea to put a using declaration in the global scope, like right after the include directives, because it is then too easy for namespaces to clash.
I would not call it a bad idea, or not a good idea. You just have to be aware that it can clash. I would also point out a few things in the code... Use typedefs for pointers! The syntax looks real messy if you do not. Do not use function pointers - use functors! Functors are actually faster than function pointers, which would make the C++ example faster. Furthermore, stripping the names of parameters in declarations is bad. Bad, bad, bad. The C version is not much better because they lack descriptive names.
Banned User
Joined: 3/10/2004
Posts: 7698
Location: Finland
The "using namespace std;" is a really, really bad habit that approximately 100% of beginner C++ programmers have (the percentage begins to lower the more advanced the programmer is). This sometimes goes to such ridiculous extents that you may even see a short example code which has a "using namespace std;" in order to save writing one "std::" prefix in the later code (thus the total amount of writing that was saved was -16 characters). What most C++ programmers (beginner and intermediate) don't seem to realize is that the "std::" prefixes actually make the code easier to read, not harder. For example, suppose you have a line of code like this:
search(i1, e1, i2, e2);
Is that calling some local function, perhaps some member function of the current class, a function defined in some of the header files included in this file, or maybe a function in the standard library? It's impossible to say from that line alone. However, suppose the line was written as:
std::search(i1, e1, i2, e2);
Now there isn't even a shadow of a doubt what this function is: A function in the C++ standard library. Even if you don't know what it does, it's easy to find info about it. I can think of only one valid usage for "using namespace", and that's if you want to import some custom namespace into another, like:
namespace SomeNamespace { using namespace AnotherNamespace; }
Any other use is horrible programming.
EEssentia wrote:
I would also point out a few things in the code... Use typedefs for pointers! The syntax looks real messy if you do not.
That should not be taken as a general principle. Sometimes substituting pointers with typedeffed names can only make the program harder to read because it will be harder to visually distinguish between pointers and non-pointer types.
Do not use function pointers - use functors!
Functors can only be passed as parameters to template functions, and consequently cannot be used in every possible situation where a function pointer is required. (Also functors are more verbose to write, at least until the next C++ standard gets ratified and implemented widely.)
Furthermore, stripping the names of parameters in declarations is bad. Bad, bad,
It's not always bad. For example, if you have eg. a member function named "setXCoordinate(int)" or "setModifiedFlag(bool)", those don't really require the parameters to be named. They are rather self-evident even without. (Also many people leave parameters of private function declarations unnamed to reduce the visual clutter of header files.)
Joined: 7/2/2007
Posts: 3960
I tend to err on the side of verbosity when it comes to variable names and the like. Not to the extent that it impedes readability, mind you, but I'd rather write e.g. "point" than "p", and better still "pointOnPlane" if, say, I'm doing a projection. Including variable names in functions is just a part of that. Having recently had to maintain the code of someone who was absolutely in love with single-letter variable names and the abolishment of namespaces wherever possible, I'm coming to appreciate my own coding style more and more.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Banned User
Joined: 3/10/2004
Posts: 7698
Location: Finland
What I have come to appreciate in the last year or two is something that many programmers have a huge prejudice against (for reasons I cannot understand anymore): prefixing your variable names descriptively. Nowadays I prefix all member variable names with an 'm', constants with a 'k' and variables inside namespaces (named or unnamed) with a 'g' (which stands for "global"; they are "global" in the sense that they are not local to any function or class, although not really in the global namespace, but always local to either the current compilation unit or a named namespace). I don't prefix variables local to a function in any way, as I feel that the very lack of prefix is in itself indicative that they are in the local scope. (Some programmers prefix even these, with an 'a'.) (Variables with the 'g' and 'k' prefixes are in fact usually at the same scope, ie. a nameless or named namespace. Their difference is that the 'k' indicates that the variable is a constant. If it's of integral type, it can be used where compile-time constants are expected. I usually don't prefix local constants with a 'k', unless I want to emphasize that it's being used as a compile-time constant.) I have found that this simple naming convention really makes my code more readable to myself, especially after months or even years. It's much easier to look for variable declarations when you see from its name whether it's a member variable, a variable local to the current function, a variable in a nameless namespace, or a constant.
marzojr
He/Him
Experienced player (763)
Joined: 9/29/2008
Posts: 964
Location: 🇫🇷 France
The prejudice of programmers regarding Hungarian notation came about due to overuse of it. The Windows API is a notorious offender, but there are many other notable cases (one example, given by the Wikipedia article, being a variable named "a_crszkvc30LastNameCol"). Hungarian notation can get so bad that it is one of the "weapons" suggested in the (humorous) article "How To Write Unmaintainable Code". Finally, there is also the case that variables may change their type over the course of a program's life (maybe because the programmer found a more efficient/faster data storage method), but the overall concept remains the same (and with the same semantics), forcing the programmer to replace all instances of the prefixed name with the new prefix.
Marzo Junior
Joined: 7/2/2007
Posts: 3960
Here's how I differentiate my variables: * Constants: in all caps. MAX_SPEED_X, NUM_COLUMNS, etc. * Member variables: prefixed with "self.". self.velocity, self.animations, etc. This is Python; all member functions accept as their first argument the object they're operating on. I find this approach a lot more intuitive than the implicit "this" variable in C++. * Globals: referred to by their module name (e.g. map.minUniverseWidth, physicsobject.defaultGravity). Or, simply by being names that are not declared in the current scope -- most of my functions are short enough that such are easily recognizable. Not to say that "scope prefixes" are useless; this is just my approach to the same problem.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Joined: 4/3/2005
Posts: 575
Location: Spain
"What most C++ programmers (beginner and intermediate) don't seem to realize is that the "std::" prefixes actually make the code easier to read, not harder." Yes, it also makes it a lot uglier, and I'm the one that has to read the code. Thank you.
No.
Editor, Active player (297)
Joined: 3/8/2004
Posts: 7469
Location: Arzareth
Warp wrote:
<...> the "std::" prefixes actually make the code easier to read, not harder. For example, suppose you have a line of code like this:
search(i1, e1, i2, e2);
Is that calling some local function, perhaps some member function of the current class, a function defined in some of the header files included in this file, or maybe a function in the standard library? It's impossible to say from that line alone. However, suppose the line was written as:
std::search(i1, e1, i2, e2);
Now there isn't even a shadow of a doubt what this function is: A function in the C++ standard library.
In my opinion, the same rationale could be used to justify putting an explicit this-> before all references to the current class's methods and properties, such as:
this->copy(this->elem1, this->elem2);
Or perhaps:
this->myClass::copy(this->myClass::elem1, this->myClass::elem2);
We all just have to draw the line somewhere(Note: I do use std:: prefixes in my code, but I try to write my code such as to avoid scattering them throughout, especially from having many on the same line.)
Joined: 4/13/2009
Posts: 431
Whoa, you poked holes in all my arguments. But you are right.
Warp wrote:
The "using namespace std;" is a really, really bad habit that approximately 100% of beginner C++ programmers have (the percentage begins to lower the more advanced the programmer is). This sometimes goes to such ridiculous extents that you may even see a short example code which has a "using namespace std;" in order to save writing one "std::" prefix in the later code (thus the total amount of writing that was saved was -16 characters). What most C++ programmers (beginner and intermediate) don't seem to realize is that the "std::" prefixes actually make the code easier to read, not harder. For example, suppose you have a line of code like this:
search(i1, e1, i2, e2);
Is that calling some local function, perhaps some member function of the current class, a function defined in some of the header files included in this file, or maybe a function in the standard library? It's impossible to say from that line alone. However, suppose the line was written as:
std::search(i1, e1, i2, e2);
Now there isn't even a shadow of a doubt what this function is: A function in the C++ standard library. Even if you don't know what it does, it's easy to find info about it. I can think of only one valid usage for "using namespace", and that's if you want to import some custom namespace into another, like:
namespace SomeNamespace { using namespace AnotherNamespace; }
Any other use is horrible programming.
This is subjective. You might like it this way, but others might not. So I would not call it bad practice in any way.
EEssentia wrote:
I would also point out a few things in the code... Use typedefs for pointers! The syntax looks real messy if you do not.
That should not be taken as a general principle. Sometimes substituting pointers with typedeffed names can only make the program harder to read because it will be harder to visually distinguish between pointers and non-pointer types.
Yes, you are right in a certain sense. typedef VoidPtr void*; That is an example of bad usage of typedefs. But when it comes to function pointers that you return, it is usually a good idea, since you see how verbal the syntax became without the use of it.
Do not use function pointers - use functors!
Functors can only be passed as parameters to template functions, and consequently cannot be used in every possible situation where a function pointer is required. (Also functors are more verbose to write, at least until the next C++ standard gets ratified and implemented widely.)
Partily true, I suppose. Functors usually do require templates, and often it is possible to use templates. In this example, it certainly was. Then there is the std::function or whatever it is called. I believe this one can encapsulate a functor so long as you specify the types the functor must have. Which is pretty much the same as the member function pointer, but probably faster.
Furthermore, stripping the names of parameters in declarations is bad. Bad, bad,
It's not always bad. For example, if you have eg. a member function named "setXCoordinate(int)" or "setModifiedFlag(bool)", those don't really require the parameters to be named. They are rather self-evident even without.
I cannot say that is a good argument. It obfuscates the code. Do not dwell on whether it is good or bad - just do it. Always.
(Also many people leave parameters of private function declarations unnamed to reduce the visual clutter of header files.)
This may or may not be a good idea. It all depends on what they are used for. But you are right that it might be okay.
Banned User
Joined: 3/10/2004
Posts: 7698
Location: Finland
marzojr wrote:
The prejudice of programmers regarding Hungarian notation came about due to overuse of it.
True, but I'm not talking about overusing the notation. As I said, just the distinction between local, member and "global" variables helps readability a lot. IMO there's no much need to go further than that (eg. indicating the type of the variable in its name). I had myself a prejudice against the prefixes for years, but some time ago I really started to consider it more seriously when I regularly had to go through old code of mine and was having trouble remembering what all the variables meant. I really have noticed an improvement now that I have started using those three prefixes.
Derakon wrote:
* Constants: in all caps. MAX_SPEED_X, NUM_COLUMNS, etc.
Many C++ (and C) programmers limit the usage of all-caps to preprocessor macros, as another distinguishing naming convention. (After all, a preprocessor macro can be a lot more than just an alias for a literal constant.) Personally I also use all caps with enumerated constants (but not any other type of constants), but I have been considering changing that habit.
* Globals: referred to by their module name (e.g. map.minUniverseWidth, physicsobject.defaultGravity). Or, simply by being names that are not declared in the current scope -- most of my functions are short enough that such are easily recognizable.
In C++ you can have nameless namespaces, so obviously you can't use a "module name" with them (there is a radical difference between nameless and named namespaces; if you used a named namespace, all the identifiers inside it would become globally visible, while the visibility of identifiers in a nameless namespace are strictly restricted to the compilation unit where they reside.) Of course you could prefix the usage of variables in a nameless namespace with a "::" (eg. "::value += 5;"), but the empty "::" prefix also has meanings other than just "the current global scope" so it may become confusing. (For example, "new" and "::new" are two very different things.)
DrJones wrote:
"What most C++ programmers (beginner and intermediate) don't seem to realize is that the "std::" prefixes actually make the code easier to read, not harder." Yes, it also makes it a lot uglier, and I'm the one that has to read the code. Thank you.
This is precisely the kind of view that I don't understand anymore. As I said, to me the "std::" prefixes make the code easier to read and understand, not harder or "uglier". It's a clear visual clue that a standard library element is being used. Honestly, I just can't understand where the "ugly" part is coming from. What do you mean "ugly"? It's three letters and two colons. What's so "ugly" about that? Granted, if you had three nested namespaces, each one with a name which is 15 characters long, then one might consider some "using namespace" or a namespace alias to make the usage shorter. But this is just 5 characters, "std::".
Or perhaps:
this->myClass::copy(this->myClass::elem1, this->myClass::elem2);
We all just have to draw the line somewhere…
Every time I defend the "std::" prefix, someone always comes up with the slippery slope argument. It's not very convincing. "std::" is just 5 characters, and it does make the code easier to read when you get used to it (which happens pretty quickly once you get over the prejudice).
Joined: 9/6/2009
Posts: 24
Location: Renton, WA
EEssentia wrote:
Functors usually do require templates, and often it is possible to use templates. In this example, it certainly was. Then there is the std::function or whatever it is called. I believe this one can encapsulate a functor so long as you specify the types the functor must have. Which is pretty much the same as the member function pointer, but probably faster.
Functors can be faster than function pointers if the functor is statically known at the call site; in this case, where the functor is not statically known, I don't see how they could be faster than a function pointer. (Functors could be the same speed as a function pointer, which is probably faster than a member function pointer.)
arflech
He/Him
Joined: 5/3/2008
Posts: 1120
Bisqwit wrote:
Warp wrote:
<...> the "std::" prefixes actually make the code easier to read, not harder. For example, suppose you have a line of code like this:
search(i1, e1, i2, e2);
Is that calling some local function, perhaps some member function of the current class, a function defined in some of the header files included in this file, or maybe a function in the standard library? It's impossible to say from that line alone. However, suppose the line was written as:
std::search(i1, e1, i2, e2);
Now there isn't even a shadow of a doubt what this function is: A function in the C++ standard library.
In my opinion, the same rationale could be used to justify putting an explicit this-> before all references to the current class's methods and properties, such as:
this->copy(this->elem1, this->elem2);
Or perhaps:
this->myClass::copy(this->myClass::elem1, this->myClass::elem2);
We all just have to draw the line somewhere(Note: I do use std:: prefixes in my code, but I try to write my code such as to avoid scattering them throughout, especially from having many on the same line.)
"->" is a cop-out, be a truly elite hacker by saying "(*this).myClass::elem1" etc. of course the most elite hackers just code in assembly, and not with assemblers like HLA and MASM that provide macros and even (in the case of HLA) allow object-oriented programming, I mean a low-level assembler, like FASM
i imgur com/QiCaaH8 png
Joined: 7/2/2007
Posts: 3960
Real Programmers don't write in assembler. They write in machine code, because nobody who isn't using the One True Architecture deserves to benefit from their creations. And they don't use keyboards, either; they solder bare copper wires to the motherboard and then chew on them to send the appropriate write signals. (Real Programmer jokes are basically the original Chuck Norris jokes, only funny)
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Joined: 4/7/2008
Posts: 117
Alternate Text: Real programmers set the universal constants at the start such that the universe evolves to contain the disk with the data they want. Obligatory.
Editor, Active player (297)
Joined: 3/8/2004
Posts: 7469
Location: Arzareth
In more seriousness, in my opinion, real programmers do what is necessary to get the task accomplished in an elegant manner and no more. Elegance is defined by a number of meters, such as the ratio of "accomplishes" to "does" in the code (this is my favourite) and its ease to be understood at glance. To understand the ratio of "accomplishes" to "does" in the code, consider these two examples (C):
int main() { putchar('H'); putchar('e'); putchar('l'); putchar('l'); putchar('o'); return 0; }
int main() { printf("Hello"); return 0; }
It is clear that the second code accomplishes the same as the first code but with less do'ing. It is also easier to understand at glance. A better, real world example (paraphrased from Nach's article that partially addresses this same topic):
/* Log on mondays, wednesdays and fridays.
 * dayOfTheWeek is 0-6, with 0 signifying sunday. */
void logEveryOtherDay(int dayOfTheWeek)
{
  if (dayOfTheWeek == 1)
  {
    logOpen();
    logWrite("-------------");
    logWrite("Monday");
    logData();
    logClose();
  }
  else if (dayOfTheWeek == 3)
  {
    logOpen();
    logWrite("---------------");
    logWrite("Wednesday");
    logData();
    logClose();
  }
  else if (dayOfTheWeek == 5)
  {
    logOpen();
    logWrite("------------");
    logWrite("Friday");
    logData();
    logClose();
  }
}
Changed like this, the code accomplishes more by doing less, while being also less error-prone:
static const char* const daysOfTheWeek[7] =
{ "Sunday", "Monday", "Tuesday", "Wednesday",
  "Thurday", "Friday", "Saturday" };
void logEveryOtherDay(int dayOfTheWeek)
{
  if (dayOfTheWeek % 2 != 0) /* Do logging on odd days only */
  {
    logOpen();
    logWrite("-------------");
    logWrite(daysOfTheWeek[dayOfTheWeek]);
    logData();
    logClose();
  }
}
This attitude naturally reflects the thinking of the person, and thus, it carries to daily activities as well. While this is sometimes a blessing, it is also a curse: it makes a programmer rather bad at following instructions, because they become easily distracted in trying to see patterns and in trying to optimize the instructions for lesser actions, or to eliminate the need for the actions alltogether. :) At least that applies to me.
Banned User
Joined: 3/10/2004
Posts: 7698
Location: Finland
Bisqwit wrote:
In more seriousness, in my opinion, real programmers do what is necessary to get the task accomplished in an elegant manner and no more. Elegance is defined by a number of meters, such as the ratio of "accomplishes" to "does" in the code (this is my favourite) and its ease to be understood at glance.
What both of your examples are actually telling is that real programmers avoid code repetition (a rather common beginner mistake). Brevity in itself, when done wrong, can actually be extremely counter-productive. "Don't do needless work when a shorter/simpler solution will do the same" yes. "Shorten the code just for the sake of making it shorter" no. That first principle actually reminds me of some of the most horrible pieces of C++ code I have had to review as a teaching assistant at the University here. You wouldn't believe how complicated a function like "calculate the distance between two 2D points" can be (which is a simple 1-liner). I think that the worst examples spawned over 100 lines of code.
Emulator Coder
Joined: 3/9/2004
Posts: 4588
Location: In his lab studying psychology to find new ways to torture TASers and forumers
Code repetition isn't just a common beginner mistake, it's the cardinal programming sin. Of course the better you are, the more you realize what is repetitious. http://insanecoding.blogspot.com/2009/05/ancient-coding-ideas-finally-in-english.html http://insanecoding.blogspot.com/2009/05/ancient-coding-ideas-finally-in-english_25.html
Warning: Opinions expressed by Nach or others in this post do not necessarily reflect the views, opinions, or position of Nach himself on the matter(s) being discussed therein.
Joined: 7/2/2007
Posts: 3960
My stance on repetition: * The first time you write something, do it in-line. That is, don't make a separate function for it; just incorporate it into your program. * The second time you write something, recognize that you're duplicating functionality. Don't make a new function yet, but also don't copy and paste your previous implementation. * The third time you write something, it's time to refactor. Make a new function, and look at the previous ways you accomplished your goal. Pick the best approaches from each. Sometimes, like with a "distance between two points" function, there's really only one good way to get the job done, so the "no copy/pasting" rule isn't really relevant. But I find the "refactor only on the third time" rule tends to strike a good balance between having duplicated code and having lots of functions scattered about that have only one or two clients. Lots of functions is bad largely because it means that when you're trying to figure out what a given piece of code does, you have to go bouncing about the codebase a lot tracking down what all of the functions the code calls do. Other Derakon maxims for quality code: * Use source control. Source control gives you the freedom to delete code you aren't using right this instant. Odds are you'll never need it again. Without proper source control, you become leery of deleting code, which causes your codebase to become filled with unused functions and large blocks of commented-out code. * When you make a change to the code, describe the purpose and method for the change in the check-in description, not in the code comments. Your code comments should say what something does and why it's done, not when it was changed. * Don't overdesign your code. Figure out what you need and write code that meets those needs. Recognize what you may want to do, and leave yourself room to expand in that direction, but don't write a function with the assumption that you will use it. Rather, find yourself in need of a function, and write it to meet that need. Code that you write in anticipation of future need will never be used, or will need to be rewritten anyway because of changing requirements. * Conversely, don't start coding until you have a high-level design made. * Don't optimize until you need the speed. But when you're writing new code, be aware of its algorithmic complexity. When you do optimize, use a profiler to figure out what in your code is slowing you down. When you make changes, verify that they actually sped things up.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Emulator Coder
Joined: 3/9/2004
Posts: 4588
Location: In his lab studying psychology to find new ways to torture TASers and forumers
Derakon wrote:
* The first time you write something, do it in-line. That is, don't make a separate function for it; just incorporate it into your program.
That's taking a limited view on functions. Functions aren't just about making parts of your code reusable. They're also about making parts of your code readable. If you have some complex logic which can be named in a descriptive fashion, move into a function even if you only use it once.
Derakon wrote:
Lots of functions is bad largely because it means that when you're trying to figure out what a given piece of code does, you have to go bouncing about the codebase a lot tracking down what all of the functions the code calls do.
Your problem is the sign of a bad programmer, or badly created functions. You shouldn't have to track down a function to know what does. You should know from its name. If you had to also look inside the function, it's a sign you're a bad programmer, or the function is poorly named. So on the flip size, break down your code into sensible functions. Each function should do exactly what it says it does and be appropriately named. This way any part of your code should be readable and fixable on its own. Abstracting away logic to other functions helps understanding the current function better. Remember, programming is about managing complexity. No matter how smart you are, there will always be a function which you can't keep the entire flow of it in your head without breaking it down. So you might as well break down even large cases that you can keep all in your head, and use your spare brainpower for other needed improvements.
Warning: Opinions expressed by Nach or others in this post do not necessarily reflect the views, opinions, or position of Nach himself on the matter(s) being discussed therein.
Joined: 7/2/2007
Posts: 3960
Your points are well-made, and my original maxims could have stood to be better-written. I was writing them as a reaction to the code I'm having to maintain (and which I did not originally write). It could be of better quality -- as an example, in the past week I've deleted over 2500 lines of outright dead code, out of a codebase that was originally about 16000 lines. Most of it was commented-out or unused functions. Pretty soon I'm going to start to be able to set up some actual abstraction in there, and then I anticipate my life will get much better.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Banned User
Joined: 3/10/2004
Posts: 7698
Location: Finland
Derakon wrote:
My stance on repetition: * The first time you write something, do it in-line. That is, don't make a separate function for it; just incorporate it into your program. * The second time you write something, recognize that you're duplicating functionality. Don't make a new function yet, but also don't copy and paste your previous implementation. * The third time you write something, it's time to refactor. Make a new function, and look at the previous ways you accomplished your goal. Pick the best approaches from each.
I think that's an acceptable principle only for small pieces of code (a few lines, a dozen at the very most). If we are talking about large pieces of code, it may be a good idea to divide it logically into separate functions, even if those function are called only from one single place (and are not even visible outside of the current compilation unit) just so that you don't end up having one function with one thousand lines of code. Function naming in itself can often act as self-documenting code. We can also apply your principles at a higher level: * If you find yourself passing the same parameters to a group of functions from many places, that's usually a sign that the parameters and the functions are more or less closely related to each other. You should start considering if you could group both the data and those functions into a module or class. This not only organizes the code better, it usually also simplifies the calling code (because now the calling code doesn't have to manage those parameters nor pass them to functions all around).
* Don't optimize until you need the speed. But when you're writing new code, be aware of its algorithmic complexity. When you do optimize, use a profiler to figure out what in your code is slowing you down. When you make changes, verify that they actually sped things up.
One should distinguish between two types of optimization: Low-level optimization ("hacker optimization") and high-level optimization. These two things should not be confused. (Very especially, the "optimize" in "don't optimize unless necessary" should not be confused with high-level optimization. It should only refer to the hacker optimization.) One should be aware of computational complexities and have experience on which algorithms and data containers are best suited to solve which problems. Choosing the proper algorithm or data container to begin with will be a lot easier than using a naive solution and having to change it afterwards. "Hacker optimization", on the other hand, should usually be avoided, especially because it tends to make the code more obfuscated and less readable, unless you know that a specific (preferably small) piece of code will need to be as fast as possible (for example because it will be called millions of times per second). Even in these cases you should know the difference between null optimizations (optimizations which might look like they are doing something even though the aren't, because the compiler was making that optimization already anyways), micro-optimizations (optimizations which might have some minuscule effect, but which may get completely overwhelmed by the slowness of the surrounding code, making the optimization useless in practice) and real low-level optimization (such as reducing the amount of useless memory allocations in a C++ program, which can be a significant source of inefficiency).
arflech
He/Him
Joined: 5/3/2008
Posts: 1120
Would it be too hacker-ish to test for an odd integer with n&1, or to replace n%2 with (n>>1)<<1, or to pepper your functions with inline asm?
i imgur com/QiCaaH8 png
Joined: 4/7/2008
Posts: 117
Do what's readable.
template <typename> // not by reference, would likely be slower
const bool is_even(const T pValue)
{
    return (pValue % 2) == 0;
}

template <typename>
const bool is_odd(const T pValue)
{
    return !is_even(pValue);
}
The compiler will choose which bit tricks are best for you. EDIT: wtf? I can't put "T" after "typename".
1 2
5 6 7 8