• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Louis Dionne 2013-2017
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
4 
5 #include <boost/hana/equal.hpp>
6 #include <boost/hana/minus.hpp>
7 #include <boost/hana/plus.hpp>
8 #include <boost/hana/tuple.hpp>
9 #include <boost/hana/zip_with.hpp>
10 
11 #include <functional>
12 namespace hana = boost::hana;
13 
14 
15 //
16 // Example of implementing basic dimensional analysis using Hana
17 //
18 
19 
20 // base dimensions                              M  L  T  I  K  J  N
21 using mass        = decltype(hana::tuple_c<int, 1, 0, 0, 0, 0, 0, 0>);
22 using length      = decltype(hana::tuple_c<int, 0, 1, 0, 0, 0, 0, 0>);
23 using time_       = decltype(hana::tuple_c<int, 0, 0, 1, 0, 0, 0, 0>);
24 using charge      = decltype(hana::tuple_c<int, 0, 0, 0, 1, 0, 0, 0>);
25 using temperature = decltype(hana::tuple_c<int, 0, 0, 0, 0, 1, 0, 0>);
26 using intensity   = decltype(hana::tuple_c<int, 0, 0, 0, 0, 0, 1, 0>);
27 using amount      = decltype(hana::tuple_c<int, 0, 0, 0, 0, 0, 0, 1>);
28 
29 // composite dimensions
30 using velocity     = decltype(hana::tuple_c<int, 0, 1, -1, 0, 0, 0, 0>); // M/T
31 using acceleration = decltype(hana::tuple_c<int, 0, 1, -2, 0, 0, 0, 0>); // M/T^2
32 using force        = decltype(hana::tuple_c<int, 1, 1, -2, 0, 0, 0, 0>); // ML/T^2
33 
34 
35 template <typename Dimensions>
36 struct quantity {
37     double value_;
38 
quantityquantity39     explicit quantity(double v) : value_(v) { }
40 
41     template <typename OtherDimensions>
quantityquantity42     explicit quantity(quantity<OtherDimensions> other)
43       : value_(other.value_)
44     {
45       static_assert(Dimensions{} == OtherDimensions{},
46         "Constructing quantities with incompatible dimensions!");
47     }
48 
operator doublequantity49     explicit operator double() const { return value_; }
50 };
51 
52 template <typename D1, typename D2>
operator *(quantity<D1> a,quantity<D2> b)53 auto operator*(quantity<D1> a, quantity<D2> b) {
54     using D = decltype(hana::zip_with(std::plus<>{}, D1{}, D2{}));
55     return quantity<D>{static_cast<double>(a) * static_cast<double>(b)};
56 }
57 
58 template <typename D1, typename D2>
operator /(quantity<D1> a,quantity<D2> b)59 auto operator/(quantity<D1> a, quantity<D2> b) {
60     using D = decltype(hana::zip_with(std::minus<>{}, D1{}, D2{}));
61     return quantity<D>{static_cast<double>(a) / static_cast<double>(b)};
62 }
63 
main()64 int main() {
65     quantity<mass>         m{10.3};
66     quantity<length>       d{3.6};
67     quantity<time_>        t{2.4};
68     quantity<velocity>     v{d / t};
69     quantity<acceleration> a{3.9};
70     quantity<force>        f{m * a};
71 }
72