17

I'm working on a software design in which I'd like to leverage Boost.Units. Some of the units I'd like to use represent time, however, I'm inclined to use the C++11 std::chrono units for those since they're standard.

I'm wondering if there's any clean integration between Boost.Units and chrono or whether I have to resort to writing my own converters and lose type safety by just copying scalar values between the types.

Are there any best practices for this issue?

slybloty
  • 6,346
  • 6
  • 49
  • 70
user1714423
  • 191
  • 5
  • 2
    I recently started working with `boost::units`. AFAICT there is no relation to time or `boost::chrono` there. I think the concepts behind `boost::units` and `boost::chrono` differ too much. However you could have a look to `boost::date_time` which builds on (.. or re-implements) `std::chrono`. There you'll find a plethora of classes that deal with any thinkable aspect of time. – user23573 Nov 04 '15 at 21:20
  • Perhaps wrap the scalar in a new class, thus obscuring the scalar while providing `getAs[Type]` functions? One point of failure is better than many. – Conduit Dec 22 '15 at 18:57
  • For those that come here the following question is relevant, but slightly different: https://stackoverflow.com/questions/4910373/interoperability-between-boostdate-time-and-stdchrono – Andrew Hundt May 24 '16 at 01:18

2 Answers2

2

If you just want to convert a std::chrono duration to a boost time quantity you can use the following template function:

using time_quantity = boost::units::quantity<si::time, double>;

template<class _Period1, class _Type>
time_quantity toBoostTime( chrono::duration<_Type, _Period1> in)
{
  return time_quantity::from_value(double(in.count()) * double(_Period1::num) / double(_Period1::den) );
}

One thing to note is that the returned time_quantity will always be in seconds and the storage type will be of type double. If any of those two are a problem, the template can be adapted.

Example:

namespace bu = boost::units;
namespace sc = std::chrono;
using time_quantity_ms = bu::quantity<decltype(bu::si::milli * bu::si::second), int32_t>;

std::cout << "Test 1: " << toBoostTime(sc::seconds(10)) << std::endl;
std::cout << "Test 2: " << toBoostTime(sc::milliseconds(10)) << std::endl;
std::cout << "Test 3: " << static_cast<time_quantity_ms>(toBoostTime(sc::milliseconds(10))) << std::endl;

/* OUTPUT */
Test 1: 10 s
Test 2: 0.01 s
Test 3: 10 ms
CJCombrink
  • 3,738
  • 1
  • 22
  • 38
0

This may not be a perfect answer, but boost::chrono provides an example of how to integrate it with a units system they define in the example itself (devel) (version at time of writing).

Essentially, based on the boost.units examples for quaternion and complex numbers it should be possible to define the same functions for the std::chrono units, though it may require additional code for new user-defined units.

There is also a similar, though slightly different question regarding boost::date_time which may also have useful information.

Sorry this isn't a full answer, but perhaps it will be a start someone else can complete!

Andrew Hundt
  • 2,551
  • 2
  • 32
  • 64