// Copyright Louis Dionne 2013-2017 // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace hana = boost::hana; namespace support { template ::value >> constexpr T sqrt(T x) { T inf = 0, sup = (x == 1 ? 1 : x/2); while (!((sup - inf) <= 1 || ((sup*sup <= x) && ((sup+1)*(sup+1) > x)))) { T mid = (inf + sup) / 2; bool take_inf = mid*mid > x ? 1 : 0; inf = take_inf ? inf : mid; sup = take_inf ? mid : sup; } return sup*sup <= x ? sup : inf; } template ::value >> constexpr auto sqrt(T const&) { return hana::integral_c; } } // end namespace support namespace then { namespace mpl = boost::mpl; template struct sqrt : mpl::integral_c { }; template struct point { using x = X; using y = Y; }; //! [distance-mpl] template struct distance { using xs = typename mpl::minus::type; using ys = typename mpl::minus::type; using type = typename sqrt< typename mpl::plus< typename mpl::multiplies::type, typename mpl::multiplies::type >::type >::type; }; static_assert(mpl::equal_to< distance, mpl::int_<5>>, point, mpl::int_<2>>>::type, mpl::int_<5> >::value, ""); //! [distance-mpl] } namespace now { namespace hana = boost::hana; using namespace hana::literals; template struct _point { X x; Y y; }; template constexpr _point point(X x, Y y) { return {x, y}; } using support::sqrt; // avoid conflicts with ::sqrt //! [distance-hana] template constexpr auto distance(P1 p1, P2 p2) { auto xs = p1.x - p2.x; auto ys = p1.y - p2.y; return sqrt(xs*xs + ys*ys); } BOOST_HANA_CONSTANT_CHECK(distance(point(3_c, 5_c), point(7_c, 2_c)) == 5_c); //! [distance-hana] void test() { //! [distance-dynamic] auto p1 = point(3, 5); // dynamic values now auto p2 = point(7, 2); // BOOST_HANA_RUNTIME_CHECK(distance(p1, p2) == 5); // same function works! //! [distance-dynamic] } } int main() { now::test(); }