Skip to content

Instantly share code, notes, and snippets.

@ubnt-intrepid
Last active August 29, 2015 14:27
Show Gist options
  • Save ubnt-intrepid/4276d610a9d51b8cfe49 to your computer and use it in GitHub Desktop.
Save ubnt-intrepid/4276d610a9d51b8cfe49 to your computer and use it in GitHub Desktop.
std::chrono::durationを使ったBoost.Unitsもどき
1.21111
121.111
1.21111
12
12000
0
#include <iostream>
#include <chrono>
#include <ratio>
namespace units {
template <typename T, typename Tag>
class tagged_value {
T value_ = 0;
public:
tagged_value() = default;
tagged_value(T val)
: value_(val)
{
}
template <typename U>
tagged_value(tagged_value<U, Tag> const& other)
: value_(static_cast<T>(other.value_))
{
}
inline T value() const { return value_; }
};
// called when converting to higher resulution
template <typename T1, typename T2, typename Tag>
inline auto operator*(tagged_value<T1, Tag> v1, tagged_value<T2, Tag> v2)
-> tagged_value<decltype(v1.value()*v2.value()), Tag>
{
return tagged_value<decltype(v1.value()*v2.value()), Tag>(v1.value() * v2.value());
}
// called when converting to lower resulution
template <typename T1, typename T2, typename Tag>
inline auto operator/(tagged_value<T1, Tag> v1, tagged_value<T2, Tag> v2)
-> tagged_value<decltype(v1.value()/v2.value()), Tag>
{
return tagged_value<decltype(v1.value()/v2.value()), Tag>(v1.value() / v2.value());
}
} // namespace units;
namespace std { namespace chrono {
template <typename T, typename Tag>
struct treat_as_floating_point<units::tagged_value<T, Tag>>
: std::is_floating_point<T> {};
} } // namespace std::chrono;
namespace std {
template <typename T, typename Tag>
ostream& operator<<(ostream& os, units::tagged_value<T, Tag> val) {
return os << val.value();
}
} // namespace std;
// tags:
struct Meter {};
struct Watt {};
int main(int argc, char const* argv[])
{
using namespace std;
using namespace std::chrono;
{
// unit type definitions:
using meter_base_t = units::tagged_value<long double, Meter>;
using watt_base_t = units::tagged_value<long double, Watt>;
using meter_t = duration<meter_base_t, ratio<1>>;
using centimeter_t = duration<meter_base_t, centi>;
using watt_t = duration<watt_base_t, ratio<1>>;
meter_t meter(1.21111111);
cout << meter.count() << endl;
centimeter_t centimeter = meter;
cout << centimeter.count() << endl;
// watt_t watt = meter; // compile error!
meter_t meter2 = centimeter;
cout << meter2.count() << endl;
}
{
using meter_base_t = units::tagged_value<long long, Meter>;
using kilometer_t = duration<meter_base_t, kilo>;
using meter_t = duration<meter_base_t, ratio<1>>;
using millimeter_t = duration<meter_base_t, milli>;
meter_t meter(12);
cout << meter.count() << endl;
millimeter_t millimeter = meter;
cout << millimeter.count() << endl;
kilometer_t kilometer = duration_cast<kilometer_t>(meter);
cout << kilometer.count() << endl;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment