C++ portability rules

Labels: , |

1. Be very careful when writing C++ templates.

Don't use C++ templates unless you do only things already known to be portable because they are already used in Mozilla (such as patterns used by nsCOMPtr or CallQueryInterface) or are willing to test your code carefully on all of the compilers we support and be willing to back it out if it breaks.

2. Don't use static constructors.

Non-portable example:

FooBarClass static_object(87, 92);

void
bar()
{
if (static_object.count > 15) {
...
}
}

Static constructors don't work reliably either. A static initialized object is an object which is instanciated at startup time (just before main() is called). Usually there are two components to these objects. First there is the data segment which is static data loaded into the global data segment of the program. The second part is a initializer function that is called by the loader before main() is called. We've found that many compilers do not reliably implement the initializer function. So you get the object data, but it is never initialized. One workaround for this limitation is to write a wrapper function that creates a single instance of an object, and replace all references to the static initialized object with a call to the wrapper function:
Portable example:

static FooBarClass* static_object;

FooBarClass*
getStaticObject()
{
if (!static_object)
static_object =
new FooBarClass(87, 92);
return static_object;
}

void
bar()
{
if (getStaticObject()->count > 15) {
...
}
}

3. Don't use exceptions.

Exceptions are another C++ feature which is not very widely implemented, and as such, their use is not portable C++ code. Don't use them. Unfortunately, there is no good workaround that produces similar functionality.

One exception to this rule (don't say it) is that it's probably ok, and may be necessary to use exceptions in some machine specific code. If you do use exceptions in machine specific code you must catch all exceptions there because you can't throw the exception across XP (cross platform) code.

4. Don't use Run-time Type Information.

Run-time type information (RTTI) is a relatively new C++ feature, and not supported in many compilers. Don't use it.

If you need runtime typing, you can achieve a similar result by adding a classOf() virtual member function to the base class of your hierarchy and overriding that member function in each subclass. If classOf() returns a unique value for each class in the hierarchy, you'll be able to do type comparisons at runtime.

5. Don't use C++ standard library features, including iostream

Using C++ standard library features involves significant portability problems because newer compilers require the use of namespaces and of headers without .h, whereas older compilers require the opposite. This includes iostream features, such as cin and cout.

Furthermore, using the C++ standard library imposes difficulties on those attempting to use Mozilla on small devices.

There is one exception to this rule: it is acceptable to use placement new. To use it, include the standard header by writing #include NEW_H.

0 comments: