Empty Member Optimization

Header File

The empty_member class is in the header file empty_member.h.

Introduction

When implementing some classes, the objects often need to keep a member object of a template type which may or may not be an empty class. A good example is the STL containers needing to keep copies of their allocator objects, which are normally empty classes.

This will cause wasted space if the classes are empty because the ANSI specification requires member subobjects of class type to have nonzero size [ANSI 9.0.3]. However, the ANSI specification does not require empty base class subobjects to have nonzero size [ANSI 9.0.3, Note 94].

The solution is to bundle the possibly empty class type with another member of the same object whose size is known to be nonzero. This solution was first invented by Nathan C. Myers (www.cantrip.org) and his paper on the subject may be found at http://www.cantrip.org/emptyopt.html.

Classes

empty_member

Template Parameters

Base: The (possibly empty) base class that empty_member is to derive from

Member: The (not empty) member class that empty_member is to hold; Member may be a reference type

Typedefs

base_type: The template parameter Base

member_type: The template parameter Member

Public Data Members

m: An object of type Member

Constructors

empty_member(): Initializes the base class and member object with their default constructors.

explicit empty_member(const Base & nb): Initializes the base class with nb and the member object with its default constructor.

explicit empty_member(const Member & nm): [For non-reference types of Member only] Initializes the base class with its default constructor and the member object with nm.

explicit empty_member(Member & nm): [For reference types of Member only] Initializes the base class with its default constructor and the member reference with nm.

empty_member(const Base & nb, const Member & nm): [For non-reference types of Member only] Initializes the base class with nb and the member object with nm.

empty_member(const Base & nb, Member & nm): [For reference types of Member only] Initializes the base class with nb and the member object with nm.

Note: There is an ambiguity danger with the single-parameter constructors; if Base could be the same class as Member, then always use the constructor which takes both arguments.


Note: There is no danger of ambiguous name lookup resulting if the Base class has a member named "m". This is because the ANSI specification requires that base class members "hide" their parent class members of the same name [ANSI 10.2.2].
A Note on Usage:
empty_member should be used in a consistent fashion to increase readability. The recommended usage is as follows (the names are taken from STL concepts):
Given a class Container, templated on a type T and a (possibly empty) type Allocator, let us suppose that Container wishes to hold an object of type Allocator named "alloc" and an object of type "T *" named "ptr". Then the Container would declare an empty_member<Allocator, T> named some unique name, say "_m1". Container should then declare, at appropriate access levels, functions with the objects' originally intended names, as follows: "T & ptr() { return _m1.m; }", "const T & ptr() const { return _m1.m; }", "Allocator & alloc() { return _m1; }", "const Allocator & alloc() const { return _m1; }", which allows access to the objects through their proper names.

This technique is used because it is not unusual to have unrelated objects grouped in empty_members.