diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 3611812b3..908e5abb9 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -14,6 +14,9 @@ endfunction() boost_hana_add_example(bool.logical.eval_if) +boost_hana_add_example(core.defaults) +boost_hana_add_example(core.instance) + boost_hana_add_example(functional.always.basic) boost_hana_add_example(functional.always.dependent) boost_hana_add_example(functional.apply) diff --git a/example/core/defaults.cpp b/example/core/defaults.cpp new file mode 100644 index 000000000..1bec161a0 --- /dev/null +++ b/example/core/defaults.cpp @@ -0,0 +1,73 @@ +/* +@copyright Louis Dionne 2014 +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 +namespace hana = boost::hana; + + +template +struct Incrementable; + +BOOST_HANA_CONSTEXPR_LAMBDA auto next = [](auto x) { + return Incrementable>::next_impl(x); +}; + +BOOST_HANA_CONSTEXPR_LAMBDA auto next_n = [](auto x, unsigned int n) { + return Incrementable>::next_n_impl(x, n); +}; + +namespace boost { namespace hana { + template <> + struct instance { + template + struct with { }; + }; + + template <> + struct defaults { + template + struct with { + template + static constexpr auto next_n_impl(X x, unsigned int n) { + if (n == 0) return x; + else return next_n_impl(next(x), n - 1); + } + + template + static constexpr auto next_impl(X x) + { return next_n(x, 1); } + }; + }; +}} + +template +struct Incrementable + : hana::instance::template with +{ }; + +template <> +struct Incrementable : hana::defaults::with { + static constexpr auto next_impl(int x) + { return x + 1; } +}; + +template <> +struct Incrementable : hana::defaults::with { + static constexpr auto next_n_impl(long x, unsigned int n) + { return x + n; } +}; + +int main() { + BOOST_HANA_STATIC_ASSERT(next(1) == 2); + BOOST_HANA_STATIC_ASSERT(next_n(1, 3) == 4); // default implementation + + BOOST_HANA_STATIC_ASSERT(next(1l) == 2l); // default implementation + BOOST_HANA_STATIC_ASSERT(next_n(1l, 3) == 4l); +} diff --git a/example/core/instance.cpp b/example/core/instance.cpp new file mode 100644 index 000000000..e6dd20b74 --- /dev/null +++ b/example/core/instance.cpp @@ -0,0 +1,59 @@ +/* +@copyright Louis Dionne 2014 +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 +namespace hana = boost::hana; + + +template +struct Incrementable; + +BOOST_HANA_CONSTEXPR_LAMBDA auto next = [](auto x) { + return Incrementable>::next_impl(x); +}; + +namespace boost { namespace hana { + template <> + struct instance { + template + struct with { }; + }; + + template <> + struct defaults { + template + struct with { }; + }; +}} + +template +struct Incrementable + : hana::instance::template with +{ }; + +namespace boost { namespace hana { + template + struct instance::with{} || std::is_floating_point{}> + > + : defaults::template with + { + template + static constexpr auto next_impl(X x) + { return x + 1; } + }; +}} + + +int main() { + BOOST_HANA_STATIC_ASSERT(next(1) == 2); + BOOST_HANA_STATIC_ASSERT(next(3.3) == 4.3); + BOOST_HANA_STATIC_ASSERT(next('a') == 'b'); +} diff --git a/include/boost/hana.hpp b/include/boost/hana.hpp index 40bbf84eb..3f735b2c7 100644 --- a/include/boost/hana.hpp +++ b/include/boost/hana.hpp @@ -20,7 +20,7 @@ General purpose type classes provided by the library. @todo - Provide an integrated way of checking laws for type classes. - Creating new type classes is __way__ too complicated with the new -dispatching system. + dispatching system. */ //! @defgroup datatypes Data types diff --git a/include/boost/hana/core.hpp b/include/boost/hana/core.hpp index 7ed605ec9..1cddb24d5 100644 --- a/include/boost/hana/core.hpp +++ b/include/boost/hana/core.hpp @@ -13,6 +13,15 @@ Distributed under the Boost Software License, Version 1.0. namespace boost { namespace hana { //! @defgroup Core Core //! Miscellaneous core utilities. + //! + //! + //! @note + //! Users who only wish to instantiate a type class do not need to include + //! this header to get the declarations of `defaults` and `instance` in + //! scope. Type classes are required to either forward declare them or + //! include this header so users are free from that burden when they + //! include the type class' header. + //! //! @{ /*! @@ -40,11 +49,13 @@ namespace boost { namespace hana { @endcode The `Args...` are specific to each type class; the documentation should - explain their purpose. + explain their purpose. When possible, it is nice to include a dummy + template parameter for SFINAE, which allows `defaults` to be specialized + for all types satisfying a predicate. + + ### Example + @include example/core/defaults.cpp - @todo - - Document best practices with Enablers. - - Show examples with enablers and other useful stuff. */ template