Macros for Fixing Compiler Differences


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"
  // Windows-specific bits
  // Generic Unix bits

Silencing Unnecessary Warnings

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.

Visual Studio

I switch off the following warnings in Visual Studio:

Unfixable warning in Visual Studio
4275VC6, exported class was derived from a class that was not exported
4786VC6, identifier string exceeded maximum allowable length and was truncated (only affects debugger)
4305VC6, identifier type was converted to a smaller type
4503VC6, decorated name was longer than the maximum the compiler allows (only affects debugger)
4309VC6, type conversion operation caused a constant to exceeded the space allocated for it
4290VC6, C++ exception specification ignored
4800VC6, forcing value to bool 'true' or 'false' (performance warning)
4675VC7.1, "change" in function overload resolution _might_ have altered program
4996VC8, 'xxxx' was declared deprecated

Borland Compiler

Unfixable warning in Borland
8008Condition 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.
8060Possibly 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.
8066Unreachable 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.

minimum/maximum 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.

Missing sleep function on Windows

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.

stlplus::little_endian function

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?

Byte 0 = The most significant byte
Byte 0 = The least 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);