Main Page | Related Pages

User Manual of Quantities

Author:
Bernd Speiser, Institut für Organische Chemie, Universität Tübingen, Auf der Morgenstelle 18, D-72076 Tübingen, Germany; e-mail: bernd.speiser@uni-tuebingen.de
d9f9f1476f43c6a6d39d

Contents

  1. Introduction
  2. Main Concepts and Definitions
  3. Object Types in Quantities (to be finalized)
  4. Using Quantity Objects
  5. Generating New Quantities Types and Objects
  6. Physical Quantities
  7. References

Introduction

This manual describes the Quantities package from a user's perspective. It explains the main ideas behind the software and defines terms which are used later. It discusses the object types provided and describes the operations which can be performed on and with Quantities objects during their life cycle. Finally, it is shown how a user can expand the library by introducing specific modifications to already present quantities or by adding completely new types.

Main Concepts and Definitions

The central concept within the Quantities package is that of a quantity. A quantity is an entity which is composed of a (numerical) value and a unit, and related to other quantities by a dimension. Quantities are used to describe some "attribute of a phenomenon, body or substance" [1] in a quantitative way. For example, time is a particular quantity. If we perform calculations with quantities, we are engaged in quantity calculus.

The quantity's unit is the standard of measurement of that quantity. For example, time is measured in seconds (s). Although the SI (Système International d'Unités) provides only a single unit for a particular quantity, quite often several units for this quantity are in practical use. For example, time is also measured in minutes (min). Some units [e.g., millisecond (ms)] contain a prefix, which defines multiples of 10 of the base unit. In quantity calculus, the quantity represents the product of the value and the attached unit. The value of a quantity can be recalculated to be measured in any of its units. This will be called "to recalculate the quantity from one of the units into another unit". As an additional feature, we will provide units with a name and a symbol for easy identification.

Each quantity is related to one or more of seven base quantities defined by the SI (Système International d'Unités). These base quantities are length, mass, time, electric current, thermodynamic temperature, amount of substance and luminous intensity. The dimension of a quantity is given by the powers to which these base quantities are raised in the relation. We will call these seven numbers the components of a quantity's dimension.

The dimension of a quantity is important in quantity calculus to define commensurability. Two quantities are commensurate if their dimensions (i.e., the seven powers as defined above) are identical. Only commensurate quantities can be assigned to each other in a calculation. For example, a product of two lengths has the dimension of an area and can be assigned to an area quantity. However, it can not be assigned to a time quantity. For non-commensurate quantities also some other operations are impossible (see below). If all seven powers are zero, we call the quantity dimensionless.

The Quantities package provides header files and libraries which facilitate to write C++ programs incorporating quantity calculus. This is basically done by defining various types which have built-in abilities to follow and enforce the rules of quantity calculus. Thus, commensurability is tested for numerical and assignment operations, and units are taken into account. Furthermore, other operations are provided (Quantity library). There is also a collection of often used scientific (physical) quantities (see, Physical Quantities) in the PhysicalQuantities library, which is part of Quantities.

Once a C++ program has declared objects with the types mentioned, they can be used to perform quantity calculus. Such an object is generally referred to as a quantity object in the following. The type of such an object is the quantity type. We will further categorize quantity objects by their mode, i.e. whether they refer to a variable, a constant, a unique constant, or an unnamed transient variable.

A variable is a quantity object with a variable value. Consequently, it can be constructed with some value, be assigned to, and the value can be changed during an operation on the variable object.

A constant is a quantity object with a value which is fixed at construction. It can neither be assigned to nor have its value changed during an operation. However, it can be used in operations which leave the value of the constant object untouched, and the result of that operation can be assigned to a variable object.

A unique constant is a quantity object which does exist only once in a program. Its value is fixed already at compile time, and there is no way to construct another instance of such a unique constant object from user code. A change of the value is not possible. However, similar to a constant object it can be used in operations which leave the unique constant object untouched.

Unnamed transient quantity objects are often internally created (generated quantity objects), for example as return values of a function. Such objects can be used in operations, but in lieu of a name within the program it is not possible to assign or change the value. Other sources of such quantity objects are certain constructor calls. If this is the constructor of a well-defined quantity, the resulting object carries full unit information. However, generated quantity objects have only limited knowledge about the unit in which the value is stored. In particular, it is assumed that the standardization factor of the unit is 1.0. Thus, generated quantity objects should be used with great care (see below).

In rare cases, dynamic quantity objects are generated and returned from a function. Such an object has a type Dynamic<ST>, where ST is the storage type used (see, Object Types in Quantities (to be finalized)). A dynamic quantity object's properties can not be tested a compile time, since they are only defined at run time. Thus, they are not subject to the usual rules within this package, and could result in errors, which are only detected when the program runs. Consequently, such objects should be avoided as far as possible. At least, they should be converted into or assigned to normal quantity objects as soon as possible after they are returned from a function.

QuantityCluster objects are aggregates of simple quantity objects. In particular, the library implements variable vector, variable tuple, and variable vector tuple objects.

A variable vector object aggregates several variable objects of the same type (homogeneous aggregate). It is intended to avoid some overhead of collecting the various objects in a vector of variable objects.

A variable tuple object aggregates several variable objects of possibly different types (heterogeneous aggregate). It provides an ordered collection of these objects.

A variable vector tuple object aggregates several variable vectors in a certain order.

Object Types in Quantities (to be finalized)

The quantity types defined in the Quantities package are discussed here only briefly from a technical point of view. A more detailed description can be found elsewhere for Quantity and PhysicalQuantities types.

Dimensions

Units - NonPrefixable, Prexiable, Prefixed, Compound, Composed

Quantities

The numerical value of a quantity object is stored internally in a certain appropriate type, the "storage type". The default storage type is double. In the physical quantities (Physical Quantities) provided, the storage type is mentioned in the type name. For example, IntTime is a type for physical quantity time with storage type int. Physical quantities that use the default storage type do usually not have such a prefix, i.e. Time is assumed to have double as the storage type.

A quantity stores its value in a particular Unit, the "storage unit". This Unit's type is incorporated into the Quantity's type. Various types of a Quantity with different storage units are derived from the same parent quantity.

Moreover, all Quantity types derived from a particular parent quantity are characterized by a "standard unit". Each Quantity provides methods to recalculate its value into the standard unit, and from the standard unit into the storage unit. This unit is used as a standard for the recalculation between different quantities derived from the same parent quantity.

Finally, each parent quantity defines a "default unit". This default unit is used as the storage unit, if the latter is not provided when the Quantity is defined (as a template, see below).

Several Variable, Constant, and UniqueConstant types may be derived from a common parent quantity class. For example, Time, MinuteTime, and TimeConstant have the same parent quantity. As discussed below, objects of these related types can simply be converted by copy construction.

Technically most of the quantity types are typedefs of complex templates. Furthermore, the special case of a UniqueConabstract stant is an implementation of a Singleton. According to convention, UniqueConstants are written in capital letters like macro constants.

The fact that many operations done with Quantities are implemented as compile-time constructs (i.e., with template formulations), offers the possibility to use the compiler to check and help eliminate bugs in the code, for example if quantities are incommensurate. In this regard, `your compiler is your friend' [2] by issuing error or warning messages whenever illegal constructs are encountered.

PhysicalQuantities

... (to be written) ...

Using Quantity Objects

Preparing for Use of Quantities

First, make sure that the Quantities package is installed according to the instructions given elsewhere.

In order to use the classes within the Quantities package in your program, you have to (a) include header files in your client code, and (b) link the program against libraries.

For the discussion of header files, we assume that you point your compiler to use the installation directory of Quantities in the search path for header files. For example, with GNU gcc use

-I path-to-your-install-directory/Quantities

It is usually best to include header file Quantities.h as

#include "Quantities.h"

This directive includes all header files from the Quantities package.

If you want to include only some of the header files, use

#include "Quantity/Prefix.h"
#include "Quantity/Unit.h"
#include "Quantity/Dimension.h"
#include "Quantity/Quantity.h"
#include "Quantity/Generic.h"
#include "Quantity/Variable.h"
#include "Quantity/Constant.h"
#include "Quantity/UniqueConstant.h"
#include "PhysicalQuantities/PhysicalQuantities.h"

to include header file Prefix.h, Unit,h, Dimension.h, Quantity.h, Generic.h, Variable.h, Constant.h, UniqueConstant.h, and PhysicalQuantities.h respectively. This is only recommended for experienced users, and may be important if you want to override some of the definitions in the header files. Also, in the same way, only specific physical quantity header files, e.g. Time.h, can be included, by using e.g.

#include "PhysicalQuantities/Time.h"

If you do not want to explicitly qualify the namespace for names from the Quantities package, you may include a using directive into your code:

using namespace quantity
If you use special constructs (see, Functions and Operations not for Direct Use) from this library, you might have to include additional using directives to your code:
using namespace BSUtilities using namespace unit using namespace dimension
Declarations and definitions for PhysicalQuantities are given in separate namespaces. The name of these namespaces is xxx for PhysicalQuantity Xxx, respectively. The namespace contains the respective Dimension, Units, and Quantity definitions. Of these, user code in most cases will only need the names of the Unit classes. If you do not give a
using namespace xxx
directive (with xxx substituted by the name of the PhysicalQuantity) you have to qualify the scope if you use a unit, e.g.:
Length (1.0, length::Minute);
In the following examples, we will omit these qualifications.

As special case is namespace time. It may conflict with a name in time.h. Thus, to disambiguate, the scope qualifier quantity::time mazy be needed.

The linker must be instructed to use various libraries in the Quantities package when linking the client program. For GNU gcc, use

-Lpath-to-your-install-directory/lib -lPhysicalQuantities -lQuantity
Also, you must link your program against the BSUtilities library:
-Lpath-to-your-BSUtilities-install-directory/lib -lBSUtilities

The Life Cycle of a Quantity Object

Similar to other objects in a C++ program, the life cycle of a quantity object usually starts with construction. In the special case of a UniqueConstant the corresponding object is constructed only once at the first point of use. After construction the quantity object can be assigned to (if it is a variable quantity) and it can be used in various operations. Finally, the quantity object is destructed.

Construction of Quantity Objects

Explicit construction of a quantity object can be done as an automatic variable, e.g.
Time t; // example: default construction, 0 s
which according to C++ rules disappeares when program flow leaves the block of code in which is it created, or on the stack (with operator new), e.g.
Time *t = new Time; // also calls default constructor
In the latter case, the object is persistent. However, the client code has to make sure to explicitly delete the object later when it is no longer needed, in order to avoid memory leaks (see Destruction of Quantity Objects).

Of course, static quantity objects are also possible (except unique constant objects).

A quantity object (except UniqueConstant objects) can be constructed in several ways:

All examples above construct a named object. However, constructors can also be used to generate transient objects, which do not have a name within the client program. Of course, the state of the transient object has to be saved to another (named) object by copy construction or assignment, before it can be used. For example,
Time t = Time (5.); // copy construction by unnamed object // t now contains now 5 s Time t1 (5.); // t1 = 5 s
Since the above code generates a (superfluous) temporary object, and destroys it immediately after copying to t (see also [3]), it should possibly be avoided, and direct construction, as for t1 above should be preferred.
Such unnamed transient quantity objects can, however, also be used to print some value (for the use of operator<< see Input and Output Operations with Quantity Objects):
std::cout << Time (5.) << std::endl; // prints "5 s"

Variable and constant quantity objects can be used after construction in the C++ client code just as built-in types.

Unique constant objects do not need to be constructed explicitly. They are generated at first use. Consequently, you can just write the name of a unique constant in an expression (for assignment in the second line of code in this example, see section Assignment Operations with Quantity Objects):

AmountOfSubstance m(1., Mole ()); // construction, 1 mol ElectricCharge Q = m * FARADAYCONSTANT; // multiply by F = 96487 C/mol // and get an ElectricCharge
These two lines first construct an AmountOfSubstance object m, with contents 1 mol. Then, m is multiplied by the Faraday constant to yield an electric charge, in the present case this should be 96487 C.

Assignment Operations with Quantity Objects

With an assignment operation you can change the value of an already existing variable quantity object (target) using another quantity object (source). Of course, constant and unique constant quantity objects can not be assigned to (see for one exception for constant objects, below). However, you can assign to a variable quantity object from a quantity object in any other mode. There is one strict prerequisite which must be met for assignment: the source and target quantity object must be commensurate. Attempted assignment between incommensurate quantities yields a compile time error.

For example, you can assign time quantities to each other, but not a length to a time:

Time t1 (1.0); // construction, value 1 s Time t2; // default construction, value 0 s t2 = t1; // assignment, now t2 has value 1 s MinuteTime t3 (1.0); // construction, value 1 min t2 = t3; // assignment, now t2 has value 60 s Length l (5.0) // construction, value 5 m t2 = l; // ERROR, incommensurate quantities
In particular, assignment from an unnamed transient quantity object is possible if the source and the target quantity object are commensurate:
Time t1 (1.0); // construction, value 1 s Time t2; // default construction, value 0 s t2 = (t1 * t1)/t1; // value of t2 now 1 s
Assignment to a constant quantity object is only possible within a statement like
Time t (5.9); // construction of variable time, 5.9 s ConstantTime tc = t; // copy initialization
Such a statement can be regarded as initialization of the constant quantity object, and symbol = is not an assignment (see [3], and the precautions mentioned there).
Assignment can be chained, and it is possible to assign a value in one statement to more than one target:
Time t1 (25.); // construction, value 25 s Time t2, t3; // default construction, both objects have value 0 s t3 = t2 = t1; // now all three objects have value 25 s
A std::string can also be assigned to a variable. This is described below (see Input Operations with Quantity Objects).

Mathematical Operations with Quantity Objects

The Quantities package provides mathematical operations with and between quantity objects. Some of these operations concern only a single quantity object and calculate a result from it. Some other operations concern two quantity objects and the result depends on both of them. Note that bitwise operations are not provided for quantity objects.

Comparison Operations with Quantity Objects

Client programs can compare quantity objects using the conventional comparison operators == (equal), != (not qual), < (less than), > (greater than), >= (less equal), and <= (greater equal). All these operations are defined such that the values of the two objects are compared after recalculation to a common unit. Thus, comparisons are not only allowed between quantity objects of the same quantity type, but also between those related by the same parent quantity.
Time t (60.); // construction, 60 s MinuteTime t1 (1.); // construction, 1 min if (t == t1) // result: true // ..
Quantity objects which are not related by a parent quantity can not be compared. Consequently, the following is invalid:
Time t (60.); // construction, 60 s Length l (1.); // construction, 1 m if (t == l) // ERROR // ..
However, as an exception, comparison to unnamed transient quantity objects is allowed as long as the two quantities are commensurate:
Time t (1.); // construction, 1 s Time t1 (2.); // construction, 2 s if (t == (t * t1)/t) // comparison: false // ..
Furthermore, dynamic quantity objects may be compared to quantity objects:
Time t (1.); // construction, 1s SquareTime tsq = t * t; // value: 1 s^2 double power = 0.5; // define the power (i.e., take square // root) if (t == pow (tsq, power)) // comparison: true // .. if (pow (tsq, power) == t) // also possible // .. if (pow (tsq, power) == pow (tsq, power)) // also possible // ..
Here, the power function returns an object of type Dynamic<ST>, which is compared to the Time object. Such a comparison only makes sense if the two objects are commensurate, i.e. have the same dimension. With dynamic quantity objects, this can only be tested at run time, which decreases performance and may compromise type safety. Thus, such constructs should be used only when dynamic access is absolutely necessary.

For comparison operations, the mode of any of the two quantity objects is not important. Thus, for example, it is allowd to compare a variable quantity onject to a constant quantity object, provided the above conditions are met:

Time t (1.0); // construction, 1 s TimeConstant tc (5.0); // construction, 5 s if (t == tc) // comparison: false // .. LengthConstant lc (1.); // construction, 1 m if (t <= lc) // ERROR // ..
The comparison operations provided by the Quantities package simply compare the numerical values of the two quantity objects concerned. They do not take into account problems caused by the particular storage type of the value. For example, it is well known that comparison operations of floating point values (in particular the equality operation) can be dangerous and special precautions should be taken to avoid problems. For details, see the following links The Quantities package does not implement any of the schemes described in these references. Thus, if necessary, this has to be included in client code.

Logical Operations with Quantity Objects

In the present version, no logical operations (AND, OR, not, bitwise operations) are provided for quantity objects.

Input and Output Operations with Quantity Objects

Input and output of quantity objects into and from streams and strings is implemented. For such operations you should use operator>> and operator<<. One quantity object can be located on any side of these operators. Furthermore, a std::string can directly be assigned to a variable quantity object. The behavior of these input/output functions can be controlled by additional helper objects.

Output Operations with Quantity Objects

Quantity objects of all modes can be used in output statements. Any ostream object can be used for output of a quantity. Thus, output is not only possible into one of the global ostream objects (cout, cerr, clog), but also into objects of types std::ostringstream (i.e., into a string) or std::ofstream (i.e., into a file). For usage details of these objects see any current reference to the C++ standard library, for example [4]. For many of these output operations use operator << with the stream object to the left of this operator, or operator >> with the stream object to the right of this operator:
#include <iostream> Time t (1.0); // construction, 1 s cout << t; // write "1 s" to cout t >> cout; // write "1 s" to cout
If ostringstreams (and output file streams) are to be used for output, the corresponding objects have to be constructed first:
#include <sstream> // include header #include <fstream> // include header std::ostringstream oss; // construct output string stream Time t (5.0); // construction, 5 s oss << "a time quantity: " << t;// write text and "5 s" to stream std::string s (oss.str ()); // extract string from stream // and store it into s std::ofilestream ofs ("f.txt"); // construct output file stream // to file named f.txt Time t (5.0); // construction, 5 s ofs << "a time quantity: " << t;// write text and "5 s" to stream
This example also demonstrates that output of a quantity object can be intermixed with output of objects of other types.

Since unnamed transient objects do not carry information about the unit, their direct output is incomplete and contains the string "(unknown unit)". Thus, assignment to a commensurate object prior to output is strongly recommended:

Time t (5.0); // construction, 5 s cout << (t * t)/t; // writes "5 (unknown unit)" Time t1 = (t * t)/t; // writes "5 s" cout << (t1 = (t * t)/t); // alternative, writes "5 s"
Note in the latter, alternative formulation that the assignment has to be included into parentheses.

Output of quantity objects into a string can be done also directly, without using a stringstream:

Time t (2.0); // construction, 2 s std::string s1; // construct string t >> s1; // s1 contains "2 s" std::string s2; // construct string s2 << t; // s2 contains "2 s"

Furthermore, a conversion of a quantity object into a std::string is provided:

Time t (2.0); // construction, 2 s std::string s1 (t); // construct string, // store "2 s"

Input Operations with Quantity Objects

Input operations from input streams and from strings can only be performed into variable quantity objects. Any input stream (e.g., the global cin stream, or any std::istringstram od std::ifstream) or string can be used as the source of information. For usage details of these objects see any current reference to the C++ standard library, for example [4]. Operator>> and operator<< are used to direct information into a variable quantity object placed to the right or left of the operator, respectively. The input stream or the string must be placed on the respective other side of the operator. Interpretation of the input data is based on the control objects placed in the input stream (see, Control Objects for Input and Output). Per default, it is assumed that the input stream or string contains a value and a unit symbol. The following examples use an input string stream or a string.
Time t; // default construction, 1 s std::istringstream is ("5.0 s"); // define an input string stream iss >> t; // input from left: t = 5 s std::istringstream is1 ("6.0 s"); // define an input string stream t << iss1; // input from right: t = 6 s "7.0 s" >> t; // input from left: t = 7 s t << "8 s"; // input from right: t = 8 s
The substring representing the value of the variable is converted into the storage type. If this conversion fails, an InputError exception (Exceptions) is thrown:
Time t; // default construction, 1 s t << "xxxx s"; // InputError thrown
If the unit symbol does not correspond to one of the quantity's unit's symbols, also an InputError (Exceptions) is thrown:
Time t; // default construction, 1 s t << "3.5 x"; // InputError thrown
If the unit is omitted in the input information, the storage unit of the variable object is assumed:
Time t; // default construction, 1 s t << "60"; // read without unit: t = 60 s MinuteTime tm; // default construction, 1 min tm << "60"; // read without unit: tm = 60 min
For input from a string, there is an alternative formulation, which allows an assignment-type syntax:
Time t; // construction, 1 s t = "720 s"; // assign, t = 720 s MinuteTime tm; // construct, 1 min tm = "10 min"; // assign, tm = 10 min tm = "30 s"; // re-assign, tm = 0.5 min

Note, that if input of name and/or symbol of the quantity is requested by the respective control objects (Control Objects for Input and Output), these items must be present in the input. If they are absent in these cases, an InputError exception (Exceptions) is thrown.

Control Objects for Input and Output

Control objects manipulate the behavior of the input and output functions for quantity objects. In particular, they allow to switch on and off input and output of specific pieces of information (the name and the symbol of the quantity) and (for input) to define the unit which is assumed for the interpretation of the input value. Without using the control objects, neither the name nor the symbol of the quantity object are given to the output stream or read from the input stream. Also, per default, without defining a unit for input by a control object, it is assumed that the value is given in the storage unit of the quantity object, if a unit symbol is not present in the input. If name or symbol input is requested, per default it is mandatory to place an equal sign between these strings and the quantity object's value. This behaviour can be switched off. After having switched on input or output or having defined an input unit, this state will remain in effect until it is switched off, or until another input unit is defined. If either name of symbol output is switched on, an equal sign is also placed in the output between the name and/or symbol and the value of the quantity object.

The control objects excert their function by being placed in a stream as shown by the examples below. If several output or input streams are used, they affect all streams for which they are defined. Thus, if a control object is placed in the global cout stream, it will also affect output into an output file stream. Output control objects do also have an effect on conversion of a quantity object into a std::string (see Output Operations with Quantity Objects). Similarly, if placed in cin, a control object also affects input through an input string stream or other input possibilities.

Instances of the following control objects can be placed in an output stream.

Note, that placing such objects in an std::istream will cause a compile time error.

Instances of the following control objects can be placed in a std::istream:

Note, that placing such objects in an std::ostream will cause a compile time error.

Note also, that the implementation does not distinguish between a string in the input being a name or a symbol for a quantity object. All tokens in the input will be read subsequently and interpreted in the order name, symbol, equal sign, value, and unit symbol.

Conversion Operations with and between Quantity Objects

Conversion between quantity objects is usually only possible if the source and target object are related to the same parent quantity. One notable exception are objects of the various temperatures.
Some conversions have already been mentioned in paragraph Construction of Quantity Objects. In these cases the conversion is performed during the construction of a new quantity object. However, sometimes it is desired to convert and return the value of an existing quantity object without the overhead of creating a new quantity object.

You can generate a new (possibly transient) quantity object with the recalculated value:.

Time t(60.0): // construction, 60 s MinuteTime tm = t (Minute ()); // return value in min, // new transient object returned, // tm = 1.0 min MinuteTime tm1 (t (Minute ())); // return value in min, // new transient object returned, // tm1 = 1.0 min; alternative
The two alternatives should give the same result.
Another possibility is to recalculate the quantity objects value to another unit and return the resulting value:
Time t(60.0); // construction, 60 s double t_min = t.value (Minute ()); // return value in min, // no new object generated, // t_min = 1.0
Similarly, the conversion can be triggered by a string which corresponds to a symbol string of a unit, which is associated with the parent quantity of the quantity to be converted:
Time t(60.0); // construction, 60 s double t_min = t.value ("min"); // return value in min, // no new object generated, // t_min = 1.0

Status Report Operations with Quantity Objects

Some operations are provided in order to allow the extraction of certain pieces of information from a quantity object. It is noted that by necessity such information is incomplete as compared to the information stored in the quantity object. For example, if a value is extracted, it is just a number in the storage type without carrying information about the unit in which it is given or the dimension.

  1. value reporting operations
  2. unit reporting operations There are two sets of operations which report properties of the storage unit within a quantity object or class.

    The functions in the first set, unitsymbol () and unitname (), allow dynamic access to the requested information. They can be called on a particular object, i.e. an instance of a quantity class.

Status Change Operations with Quantity Objects

In most cases, the status of a quantity object should only be changed through the operations described above (e.g., assignment, mathematical operations). However, there are two exceptions from this rule, which refer to the setting of the name and the symbol of the quantity. These strings can not be set during construction, since no constructors are available which allow the definition of name or symbol. Rather, they must be set on an already existing quantity object in any mode by the following two functions:

  1. name sets the name string in a quantity object. It uses an argument of type std::string.
    Time t; // default construction, 1 s std::string namestring ("time"); // define a string t.name (namestring); // now t has name "time"
    The conversion of a character string into a std::string can be used to circumvent the explicit definition of a name string:
    Time t; // default construction, 1 s t.name ("time"); // now t has name "time"

  2. symbol sets the symbol string in a quantity object. It uses an argument of type std::string.
    Time t; // default construction, 1 s std::string symbolstring ("t"); // define a string t.symbol (symbolstring); // now t has symbol "t"
    The conversion of a character string into a std::string can be used to circumvent the explicit definition of a symbol string:
    Time t; // default construction, 1 s t.symbol ("t"); // now t has symbol "t"

Miscellaneous Functions and Operations on Quantity Objects

Here, functions and operations are described, which do not fit into any of the above sections.

The version () function returns a std::string with some information about the version of the currently used implementation and the versions of some packages it depends on. For example, this information can be placed in an output stream:

Time t(1.0); // default construction, 1 s cout << t.version () << endl; // prints a line with version // information

Functions and Operations not for Direct Use

(to be written)

The following low level functions and operations on or with quantity objects are not recommended for direct use in user code. They are, however, frequently used in the Quantities code itself.

print (ostream)

print_value (os)

read_value (str)

UnitPointerBySymbol<>

UnitIndexBySymbol<>

ListUnitSymbols<>

AllUnits<>

DefaultUnit<>

GenerateVariable<>

SameDimensioned<>

CheckSecondDimension<>

CheckUnit<>

CheckUnits<>

Unit::name ()

Unit::symbol ()

Unit::is_SI ()

Unit::Name ()

Unit::Symbol ()

Unit::Is_SI ()

Unit::version ()

Unit::Version ()

exact ()

ratio ()

dynamic_standardize ()

dynamic_reverse ()

Standardize<>

Reverse<>

Quantity::Name ()

Quantity::Symbol ()

further helper functions in Unit and Dimension classes

Destruction of Quantity Objects

Quantity objects generated on the stack with operator new should later be explicitly deleted:
Time *t = new (Time); // ... use pointer to Time object t delete t;

Quantity Clusters

(to be written)

Error Messages by the Compiler

The code of Quantities makes frequently use of metaprogramming techniques. Thus, the C++ compiler is internally used to perform calculations during compile time. For example, the compiler is instructed to check commensurability properties or the correctness of units. In this way, errors at run time can be minimized.

Note, that depending on the compiler used, these messages may be buried in a large number of output lines, and are often not easily found.

Exceptions

Quantities code may throw exceptions when it encounters during run time some unexpected situations. In addition, some exception-like error messages are generated during compilation (see Error Messages by the Compiler). Run time exceptions in Quantities are relatively rare since most errors are detected during compilation. However, dynamic problems may only be detected when the program runs and all information is available.

The following exceptions could be thrown:

Technically, all these exceptions are derived from QuantityException. It is thus possible to check for that exception type:
Dynamic q; int exp; exp = 1; // no exception expected try {q = pow (q, exp);} // raising to power of 1 is ok catch (QuantityError) { // handle exception } exp = 2; // exception expected try {q = pow (q, exp);} // dimensions are incommensurate catch (QuantityError) { // handle exception }
Alternatively, the more specific exceptions can be caught:
Dynamic q; int exp = 2; // DimensionMismatch expected try {q = pow (q, exp);} // dimensions are incommensurate catch (DimensionMismatch) { // handle exception }
QuantityError allows to transport a textual message. This message may be set when the exception is thrown. If the code does not set the message itself, a default text is provided. The message can be used when handling the caught exception:
try { // ... // try some code } catch (DimensionMismatch error) { std::cout << error.message () << std:: endl; // print out the text message }

Generating New Quantities Types and Objects

(to be written)

Specific Modifications to an Existing Quantity

(to be written)

Additional Quantities

(to be written)

Defining a New Unit

(to be written)

Defining a New Quantity

(to be written)

Physical Quantities

(to be finalized)

The PhysicalQuantities library provides implementations of various quantities, which are important in scientific work, on the basis of the Quantity library. These physical quantities are selected from the SI, and the library defines the most important units, including the SI unit, and if applicable other units in common use. In the present version, the quantities listed in the following table are implemented. In this table, also, the dimensions (in the form of the power septuple) and the units defined are given

quantity with
parent quantity
derived quantities dimension unit(s)
acceleration
AccelerationQuantities
Acceleration
AccelerationConstant
AccelerationVector
1, 0, -2, 0, 0, 0, 0 Gal
standard acc. of free fall
metre per square second
... ... ., ., ., ., ., ., . ...


PlaneAngleQuantities: specialized trigonometric functions -> recalculation into rad.

References

[1] A.D. McNaught and A. Wilkinson, Compendium of Chemical Technology, IUPAC Recommendations, 2nd edition, Blackwell Science, Oxford, 1997, p. 330.

[2] H. Sutter and A. Alexandrescu, C++ Coding Standards, Addison-Wesley, Boston, 2005, p. 4.

[3] S.C. Drewhurst, C++ Gotchas, Addison-Wesley, Boston, 2003, p. 129, p. 153 ff.

[4] N.M. Josuttis, The C++ Standard Library. A Tutorial and Reference, Addison, Wesley Longman, Reading, 1999.


Generated on Mon Feb 12 18:48:37 2007 for Quantities by doxygen 1.3.6