This component contains a set of macros which provide optional debug code. The debug code is optional in the sense that it can be entirely stripped out when compiling a release version of software. It is also optional in that a program compiled for debugging will still not produce any debug output unless it is switched on through the environment.
It irritated me that I had to check for two mutually-exclusive macros when writing Windows-specific code - _WIN32 and _WIN32_WCE. So I have simply defined a single macro MSWINDOWS which is defined if either of the above macros is defined.
You can use the same macro in your own Windows-specific code:
#include "portability_fixes.hpp" ... #ifdef MSWINDOWS // Windows-specific bits ... #else // Generic Unix bits ... #endif
In principle, it is a good policy to make code compile with no warnings. However, this is sometimes not possible because there are some compiler warnings that simply cannot be avoided. This is not lazy programming - I'm talking about warnings that are unfixable because of problems with the compiler or assumptions by compiler writers.
In the portability_fixes header I include some pragmas for switching off these unfixable warnings so that it is possible to compile code warning-free.
I switch off the following warnings in Visual Studio:
ID | Description |
---|---|
4275 | VC6, exported class was derived from a class that was not exported |
4786 | VC6, identifier string exceeded maximum allowable length and was truncated (only affects debugger) |
4305 | VC6, identifier type was converted to a smaller type |
4503 | VC6, decorated name was longer than the maximum the compiler allows (only affects debugger) |
4309 | VC6, type conversion operation caused a constant to exceeded the space allocated for it |
4290 | VC6, C++ exception specification ignored |
4800 | VC6, forcing value to bool 'true' or 'false' (performance warning) |
4675 | VC7.1, "change" in function overload resolution _might_ have altered program |
4996 | VC8, 'xxxx' was declared deprecated |
ID | Description |
---|---|
8008 | Condition is always true. Whenever the compiler encounters a constant comparison that (due to the nature of the value being compared) is always true or false, it issues this warning and evaluates the condition at compile time. |
8060 | Possibly incorrect assignment. This warning is generated when the compiler encounters an assignment operator as the main operator of a conditional expression (part of an if, while, or do-while statement). This is usually a typographical error for the equality operator. |
8066 | Unreachable code. A break, continue, goto, or return statement was not followed by a label or the end of a loop or function. The compiler checks while, do, and for loops with a constant test condition, and attempts to recognize loops that can't fall through. |
All of these tend to happen a lot in template functions.
The STL defines two template functions called std::min and std::max which return the minimum and maxuimum of two values respectively.
However, the Windows headers up to and including Visual Studio v6 define macros called max/min which conflict with the templates std::max and std::min. To avoid conflicts, Microsoft removed the std::max/min from their version of the STL rather than fixing the problem!
Fortunately, from Visual Studio .NET (version 7) the STL templates have been added correctly.
I could have fixed this by providing my own min/max for Visual Studio version 6, but this could potentially have broken the MFC headers.
So, instead, I've created extra template function definitions minimum/maximum that avoid all the problems above.
template<typename T> const T& stlplus::maximum(const T& l, const T& r) {return l > r ? l : r;} template<typename T> const T& stlplus::minimum(const T& l, const T& r) {return l < r ? l : r;}
Use these functions to avoid the min/max problem.
On Unix, there is a function sleep(unsigned seconds)
That causes the program
(actually, just the current thread) to go to sleep for the specified interval. On Windows,
this is implemented as Sleep(DWORD millseconds)
. To make programs just a little
easier to write, I implemented a sleep(unsigned seconds)
function on Windows.
Different machine architectures store data using different byte orders. This is referred to as Big- and Little-Endian Byte Ordering.
The issue is: where does a pointer to an integer type actually point? The least-significant or the most-significant byte?
In other words, bytes are addressed from offset 0 upwards. This means that in big-endian order byte 0 is the msB, whereas in little-endian order byte 0 is the lsB.
For example, Intel-based machines store data in little-endian byte order.
This function establishes byte order at run-time:
bool stlplus::little_endian(void);