Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle units in c++ interface

Tags:

c++

I am currently designing an API where I want that the user to be able to write code like this:

PowerMeter.forceVoltage(1 mV);
PowerMeter.settlingTime(1 ms);

Currently we do this using defines like:

#define mV *1.0e-03

This makes it very convenient for the user to write their code and it is also very readable, but of course has also drawbacks:

int ms;

Will throw some compiler errors which are hard to understand. So I am looking for a better solution.

I tried the new C++11 literals, but with this all I could achieve is:

long double operator "" _mV(long double value) {
  return value * 1e-3;
}
PowerMeter.forceVoltage(1_mV);

In the end the API does not care about the unit like Volt or second but only takes the number, so I don't want to do any checking if you really input Volts in forceVoltage or not. So this should also be possible:

PowerMeter.forceVoltage(2 ms);

Any idea besides staying with the defines?

like image 708
schnaufi Avatar asked Jun 14 '12 06:06

schnaufi


4 Answers

how about instead turning it around a bit by creating classes (ms,mV) for the different currents

e.g.

PowerMeter.forceVoltage( mV(1) );  
PowerMeter.settlingTime( ms(1) )

It is pretty clear to the user and arguably not hard to read plus you would get type checking for free. having a common base class for the different units would make it easier to implement.

like image 110
AndersK Avatar answered Nov 16 '22 15:11

AndersK


You can see the library "C++ Units" from Calum Grant as a good example of how to implement this. The library is a bit outdated, but still worth to see or may be to use.

Also, i think it might be interesting to read: "Applied Template Metaprogramming in SI UNITS: the Library of Unit-Based Computation"

There is one more good library: UDUNITS-2 which:

contains a C library for units of physical quantities and a unit-definition and value-conversion utility.

like image 34
Sergei Danielian Avatar answered Nov 16 '22 15:11

Sergei Danielian


You could use C++11's compile-time rational arithmetic support for the units, instead of defining literals or macros for the units.

like image 8
juanchopanza Avatar answered Nov 16 '22 15:11

juanchopanza


Take a look at Boost.Units. Here's some example code:

quantity<energy>
work(const quantity<force>& F, const quantity<length>& dx)
{
    return F * dx; // Defines the relation: work = force * distance.
}

...

/// 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.
like image 6
Danko Durbić Avatar answered Nov 16 '22 16:11

Danko Durbić