C++ tips

Scenario

There exists a long inconvenient namespace "SuperLibrary::NiftyStuff" which
contains a useful type named "UsefulType." The author wishes to create a class
outside of the "SuperLibrary" namespace, that uses this "UsefulType."

Problem

It is very inconvenient to use the fully qualified name in the header.

It is inappropriate to place a "using namespace SuperLibrary::NiftyStuff;" line
into a header since it pollutes the namespace of anyone including the header.

Solution 1

The author can issue the "using namespace" command in the header without
interfering with other libraries by placing the command inside an unnamed
namespace. Unfortunately, MSVC (others???) have issues with unnamed namespaces;

Solution 3

Microsoft Visual C++ has many pages of options for C/C++ projects. While the
defaults are reasonable, there are several settings changed that I recommend
every developer do as soon as they create the project:

Debug Information Format: C7

This setting determines which type of debugging information is created when you
build in debug mode. If you are building a .LIB or a .DLL, C7 debugging format
may save you pain. The default value is "Program Database."

The default setting will build a VC70.PDB file along with the .LIB or .DLL.
This file has all the debugging information including line numbers, the
location of the source code, and symbolic information. If you copy the library
(.LIB or .DLL) to another location, you must also copy the PDB file. But what
if you have multiple libraries in one folder? In that case, the VC70.PDB files
overwrite each other, and you cannot debug into the libraries. Further, the
main application also has a vc70.pdb file, so it quickly becomes confusing to
both the programmer and the compiler(!) which VC70.PDB
is which.

C7 is a standard debugging format that can be read by multiple debuggers (in
the odd case that you want to use another debugger.) But most importantly, it
writes the debug information inside the .LIB or .DLL file. This is not a good
thing in release mode since it bloats the library file size.

Runtime Library: Multithreaded

Everyone should make sure to build with multithreaded libraries. The
performance benefits do not warrant the potential compatibility issues when
linking with multiple libraries.

All the libraries your program links to must use the same library: you cannot
mix multi-threaded and single-threaded libraries. Any application that runs
with the single-thread library works with the multi-threaded library, with
perhaps some loss of speed.

Suppose you create a library that does not need to be multi-threaded, so you
link to the single-threaded library. This works fine until someone must use
your library AND a library that is multi-threaded. Now they are stuck. They
cannot use your library any longer, and they cannot change the other one to be
single-threaded! It would be nicer for everyone to standardize on using one or
the other. It is impossible to standardize on the single-threaded library.
Instead, we should standardize on the multi-threaded libraries.

When creating an application you can use the single-threaded library for
efficiency only when you know all of the libraries you link too also use the
single-threaded library. I personally choose not to worry about it, and use the
multi-threaded library at all times.

This is a trick question: The C++ standard states that, the variable "counter"
is scoped to the for statement. Thus, the variable does not exist and has no
value. Microsoft Visual C++ version 6 and earlier do not follow this rule (in
their defence, the C++ standard has been updated since then). By default, MSVC7
will attempt to deduce what the author expected to happen, and will compile the
code either way without reporting an error. This leads to code that may not
compile on other compilers, or in future versions of MSVC. Microsoft should at
least issue a warning about this, but it does not. Enabling this setting will
cause MSVC to report an error if the variable "counter" is used outside of the
for statement. Much like using new C++ style casts, this is a good habit to get
into.

Disable Language Extensions: True

This setting disables certain minor nice things that MSVC does. The Visual
Studio help describes exactly what language extensions exist. It is a good idea
not to rely on these, lest your code not work on other compilers or future
versions of the same compiler.

OS != Compiler

Sometimes, when writing applications that target both POSIX/GNU operating
systems and proprietary operating systems, it is necessary to wrap sections of
platform-specific code in #ifdef / #endif statements.

Do not confuse the compiler with the operating system. They are not the same!
For example, under Microsoft Windows, I can compile with mingw/gcc or with
Microsoft Visual C++ (MSVC). When writing code that is platform- specific, or
compiler-specific, be sure you check the appropriate #define!

Example 1: Misuse of #ifdef _WIN32

The above is a mistake. It checks to see if you are compiling on a WIN32
platform, and if so, issues a command to the MSVC compiler. The author has
forgotten that there are other compilers for WIN32. Compiling the above code
with gcc/mingw on Windows may result in an error about an incorrect compiler
directive. The proper way to write this code is:

Example 2: Another misuse of #ifdef _WIN32

Here, the author has recognized that MSVC does not ship the stdint.h header,
part of the C99 standard. Thus, they added a check to provide an
equivalent type when necessary. But mingw defines _WIN32 but does not provide
the MSVC __int64 type. Again, the correct code is shown below follows:

Example 3: Proper use of #ifdef _WIN32

The above checks the platform, not the compiler. This is because the Sleep()
function exists in any compiler targeting the Microsoft Windows Platform. So we
use the _WIN32 flag to determine if we should call the Windows Sleep()
function, or the POSIX nanosleep() function. This code will compile properly on
gcc/mingw or MSVC.