User Manual

Contents

  1. Introduction
  2. Object Types in Quantities (to be finalized)
  3. Using Quantity Objects
  4. Extending the Capabilities by Generating New Quantities Types and Objects
  5. Physical Quantities
  6. General 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.

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. Note, that the use of storage types that loose information when generated from a double (e.g., int), may result in incorrect results within Quantities.

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 base quantity.

Moreover, all Quantity types derived from a particular base 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 base quantity.

Finally, each base 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 base quantity class. For example, Time, MinuteTime, and TimeConstant have the same base 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 incommensurable. In this regard, `your compiler is your friend' [Sutter_2005] 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 Installation 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 _installdir_/include/Quantities/${VERSION}

with _installdir_ being the installation directory (e.g., given as the --prefix option during installation of the package) ${VERSION} being the version number of the Quantities package.

To include specific physical quantity header files, e.g. Time.h, use

 #include "PhysicalQuantities/Time.h"

or the respective include directive. In this case, all relevant basic header files are automatically included. This is recommended for user code.

If you want to include only some of the header files, without including any PhysicalQuantities header, 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"

to include header file Prefix.h, Unit,h, Dimension.h, Quantity.h, Generic.h, Variable.h, Constant.h, and UniqueConstant.h respectively.

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 may be needed.

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

-L_installdir_/lib -lPhysicalQuantities -lQuantity 

Also, you must link your program against the BSUtilities library:
-L_BSUtilities_installdir_/lib -lBSUtilities

If using a dynamically linked executable, you also have to give the runtime linker enough (and consistent) information about these libraries' place in your file system. Thus, _installdir_/lib/ (and the corresponding path to the BSUtilities library must be present either in ld.so.conf or in LD_LIBRARY_PATH.

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

During the construction of a quantity object, an initial value as well as the name and the symbol of the quantity are determined and stored.

Changes of the value of a variable object during its lifetime is performed mainly through assignment operations. The direct change by supplying a number is not possible. Assignments to (and, thus, value changes of) Constant and UniqueConstant objects are not allowed.

The initial name and symbol of a quantity are determined in the following way: for each base quantity, a default name and symbol is defined. If a derived quantity additionally defines its own name and symbol, and has the Overwrite traits set to true in the DerivedQuantityTraits class, the respective derived values are used. For Variable and Constant objects, the user can override these predefined defaults further by using a special constructor.

Time t;              // value: 0 s, name: time, symbol: t
ElectricCharge Q = ELEMENTARYCHARGE;
                     // the elementary charge uses overwriting values for name and symbol;
                     // name: elementary charge, symbol: e
                     // different from ElectricCharge objects with name: electric charge
                     // and symbol: Q 
Time t (7., "time_seven", "t_7");
                     // value:  7 s, name: time_seven, symbol: t_7

Explicit construction of a quantity object can be done as

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; preferred
Since the above code generates a (superfluous) temporary object, and destroys it immediately after copying to t (see also [Dewhurst_2003]), 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.

Conversion Operations between Quantity Objects

... definition of conversion: different storage type, different storage unit; different quantity type only in special cases ...

... conversion by copy construction ...

... conversion by assignment ...

... conversion in special cases ...

... check (copy) construction discussions above !!!!! ...

Assignment Operations with Quantity Objects

With an assignment operation you change the value of an already existing variable quantity object (target) using another object (source).

Of course, constant and unique constant quantity objects can not be target objects (see for one exception for constant objects, below). On the other hand, it is possible to assign to a variable quantity object from a quantity object in any other mode.

The following types of source objects are allowed:

The following types of source objects are prohibited:

There is one strict prerequisite which must be met for assignment: the source and target quantity object must be commensurable. Attempted assignment between incommensurable 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, incommensurable quantities
Assignment from an unnamed transient quantity object is possible if the source and the target quantity object are commensurable:
 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 Dewhurst [Dewhurst_2003], 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

Assignment from a Dynamic source object is implicitly used when assigning as in

Time t, t1 (1.0), t2 (2.0);
double exp (0.5);
t = pow ((t1 * t2), exp);             // corresponds to sqrt, but non-static exp
where the dimension of the power function result can only be determined at run-time. Note, that in general the dimension of the Dynamic can not be checked at compile-time. Consequently, incommensurable assignments can not be detected before run-time.

Among others, the following assignments are prohibited:

Time t;
t = 5.0;                              // no assignment from double
t = 5;                                // no assignment from int
t = 'a';                              // no assignment from char
BSUtilities::Rational<1,1> r;         // define a Rational<> number
t = r;                                // no assignment from Rational<>
The reason for these restrictions is that a value of a quantity itself is never meaningful. In order to interpret the value always a unit needs to be associated. The user of a quantity object is reminded of that fact when doing an assignment. If it is absolutely necessary to generate a quantity object from only a number, construction should be used.

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 any object related by the same base quantity. In particular, the storage unit or the storage type may be different.
Time t (60.);                 // construction, 60 s
MinuteTime t1 (1.);           // construction, 1 min
if (t == t1)                  // result: true
  // ...
IntTime tint (7);             // construction, 7 s
if (t != tint)
  // ...                      // result: true
Quantity objects which are not related by a base quantity in general 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
  // ...
Only if the conversion of the right hand side object in the comparison operation into an object of the left hand side type is allowed, the comparison statement is legal. Thus, the following is valid:
ThermodynamicTemperature T (273.15);        // construction, 273.15 K
CelsiusTemperature Tc (0.)                  // construction, 0 oC
if (T == Tc)                                // result: true
  // ...

Comparison to unnamed transient quantity objects is allowed as long as the two quantities are commensurable:

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 commensurable, 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.

Serialization [BoostSerialization] can be also regarded as a particular type of input/output. This will be discussed in a separate section.

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 [Josuttis_1999]. 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 commensurable 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 Josuttis [Josuttis_1999]. 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 between Quantity Objects

Conversion between quantity objects is usually only possible if the source and target object are related to the same base 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 base 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

Serialization ofQuantity Objects

... describe the use of serialization ... ... serialization of UniqueConstant is not allowed nor necessary ...

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; These operations return the value of the quantity object in the storage type without any additional information. Reporting of this number in a unit different from the storage unit as implemented in versions up to 1.2.1 is no longer possible.
  2. name/symbol reporting operations quantities can be interrogated for their name and symbol:
    Time t;                              // default construction
    t.name ();                           // returns the name
    t.symbol();                          // returns the symbol
    

  3. 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 be given by the default values for all modes, or set during construction for Variable and Constant objects. Furthermore, they may be set on an already existing quantity object for Variable or Constant 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 implicit 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 implicit 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"
    

Note that these functions are not available for a UniqueConstant quantity object.

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 dynamic information about the version of the currently used implementation. 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

... Version ... -> static info

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 incommensurable
  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 incommensurable
  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
  }

Extending the Capabilities by Generating New Quantities Types and Objects

Quantities is a package that is implemented mostly in the form of C++ template classes and functions. It is thus extandable by instantiating additional instances of these templates. An extension needs to define a new dimension, new units, a new base quantity and new derived quantities. In some cases, more simple modifications of existing quantities is possible.

Modifications to an Existing Quantity

(to be written)

Additional Quantities

(to be written)

Defining a New Unit

(to be written)

Defining a New Base Quantity

... needs QuantityTraits traits template ...

... defaults ...

(to be written)

Defining a New Derived Quantity

... reasonable set of quantities provided ...

... needs DerivedQuantity type ...

... needs DerivedQuantityTraits traits template ...

... defaults ...

... define OverwriteName/Symbol bools ...

... if bool set to true -> define the string, if set to false -> no definition of string is necessary ...

... define StorageUnit ...

... decide on the mode ...

... for UniqueConstant: only ONE for a particular derived quantity, unresticted number for a base quantity; if several UniqueConstants are needed based on a base quantity -> use different DQT ...

... can be defined ad hoc without typedef ...

Defining a New Physical Quantity

... specific conventions, ...

... physical quantities, base quantities, derived quantities ...

... fundamental physical constants (natural constants) ... (to be written)

Physical Quantities

(to be finalized)

The PhysicalQuantities library provides implementations of various quantities 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. For details, see the PhysicalQuantities page.

General Quantities

The GeneralQuantities library provides implementations of various generally useful quantities based on the Quantity library. For details, see the GeneralQuantities page.

References

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

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

[BoostSerialization] http://www.boost.org/doc/libs/1_35_0/libs/serialization/doc/index.html

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

back to top

back to Quantities start page


Generated on Mon Jul 27 15:55:46 2009 for Quantities by  doxygen 1.5.3