...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Before discussing the basics of the library, we first define a few terms that will be used frequently in the following :
To begin, we present two short tutorials. Tutorial1
demonstrates the use of SI
units. After including the appropriate system headers and the headers for the
various SI units we will need (all SI units can be included with boost/units/systems/si.hpp
) and
for quantity I/O (boost/units/io.hpp
),
we define a function that computes the work, in joules, done by exerting a
force in newtons over a specified distance in meters and outputs the result
to std::cout
. The quantity
class accepts
a second template parameter as its value type; this parameter defaults to
double
if not otherwise specified.
To demonstrate the ease of using user-defined types in dimensional calculations,
we also present code for computing the complex impedance using std::complex<double>
as the value type :
#include <complex> #include <iostream> #include <boost/typeof/std/complex.hpp> #include <boost/units/systems/si/energy.hpp> #include <boost/units/systems/si/force.hpp> #include <boost/units/systems/si/length.hpp> #include <boost/units/systems/si/electric_potential.hpp> #include <boost/units/systems/si/current.hpp> #include <boost/units/systems/si/resistance.hpp> #include <boost/units/systems/si/io.hpp> using namespace boost::units; using namespace boost::units::si; quantity<energy> work(const quantity<force>& F, const quantity<length>& dx) { return F * dx; // Defines the relation: work = force * distance. } int main() { /// Test calculation of work. quantity<force> F(2.0 * newton); // Define a quantity of force. quantity<length> dx(2.0 * meter); // and a distance, quantity<energy> E(work(F,dx)); // and calculate the work done. std::cout << "F = " << F << std::endl << "dx = " << dx << std::endl << "E = " << E << std::endl << std::endl; /// Test and check complex quantities. typedef std::complex<double> complex_type; // double real and imaginary parts. // Define some complex electrical quantities. quantity<electric_potential, complex_type> v = complex_type(12.5, 0.0) * volts; quantity<current, complex_type> i = complex_type(3.0, 4.0) * amperes; quantity<resistance, complex_type> z = complex_type(1.5, -2.0) * ohms; std::cout << "V = " << v << std::endl << "I = " << i << std::endl << "Z = " << z << std::endl // Calculate from Ohm's law voltage = current * resistance. << "I * Z = " << i * z << std::endl // Check defined V is equal to calculated. << "I * Z == V? " << std::boolalpha << (i * z == v) << std::endl << std::endl; return 0; }
The intent and function of the above code should be obvious; the output produced is :
F = 2 N dx = 2 m E = 4 J V = (12.5,0) V I = (3,4) A Z = (1.5,-2) Ohm I*Z = (12.5,0) V I*Z == V? true
While this library attempts to make simple dimensional computations easy to code, it is in no way tied to any particular unit system (SI or otherwise). Instead, it provides a highly flexible compile-time system for dimensional analysis, supporting arbitrary collections of base dimensions, rational powers of units, and explicit quantity conversions. It accomplishes all of this via template metaprogramming techniques. With modern optimizing compilers, this results in zero runtime overhead for quantity computations relative to the same code without unit checking.