diff options
Diffstat (limited to 'boost/hana')
36 files changed, 308 insertions, 185 deletions
diff --git a/boost/hana/empty.hpp b/boost/hana/empty.hpp index 8cb97a3ebc..86b81f408c 100644 --- a/boost/hana/empty.hpp +++ b/boost/hana/empty.hpp @@ -20,21 +20,21 @@ Distributed under the Boost Software License, Version 1.0. BOOST_HANA_NAMESPACE_BEGIN + //! @cond template <typename M> - struct empty_t { + constexpr auto empty_t<M>::operator()() const { #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::MonadPlus<M>::value, "hana::empty<M>() requires 'M' to be a MonadPlus"); #endif - constexpr auto operator()() const { - using Empty = BOOST_HANA_DISPATCH_IF(empty_impl<M>, - hana::MonadPlus<M>::value - ); + using Empty = BOOST_HANA_DISPATCH_IF(empty_impl<M>, + hana::MonadPlus<M>::value + ); - return Empty::apply(); - } - }; + return Empty::apply(); + } + //! @endcond template <typename M, bool condition> struct empty_impl<M, when<condition>> : default_ { diff --git a/boost/hana/experimental/printable.hpp b/boost/hana/experimental/printable.hpp index e24a3426ea..f41d3fd906 100644 --- a/boost/hana/experimental/printable.hpp +++ b/boost/hana/experimental/printable.hpp @@ -99,7 +99,7 @@ BOOST_HANA_NAMESPACE_BEGIN namespace experimental { namespace print_detail { std::string strip_type_junk(std::string const& str) { - return std::regex_replace(str, std::regex("^([a-z_]+::)*([a-z_]*)_t<"), "$2<"); + return std::regex_replace(str, std::regex("(?:struct )?([a-z_]+::)*([a-z_]*)_t<((?:struct )?[a-z:<>_]*)>"), "$2<$3>"); } } diff --git a/boost/hana/ext/boost/mpl/vector.hpp b/boost/hana/ext/boost/mpl/vector.hpp index 29e9972b5d..706c2dd06d 100644 --- a/boost/hana/ext/boost/mpl/vector.hpp +++ b/boost/hana/ext/boost/mpl/vector.hpp @@ -99,9 +99,25 @@ BOOST_HANA_NAMESPACE_BEGIN using vector_tag = ::boost::mpl::sequence_tag< ::boost::mpl::vector<>>::type; }}} + namespace mpl_detail { + // When `BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES` is not defined (e.g. on + // MSVC), different MPL sequences (like vector0 and vector1) have different + // tags, so we need to take that into account when we compare them. +#ifndef BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES + template <typename T1, typename T2> + struct is_same_mpl_vector_tag : std::false_type { }; + + template <template <long> class Tag, long x, long y> + struct is_same_mpl_vector_tag<Tag<x>, Tag<y>> : std::true_type { }; +#else + template <typename T1, typename T2> + struct is_same_mpl_vector_tag : std::is_same<T1, T2> { }; +#endif + } + template <typename T> struct tag_of<T, when< - std::is_same< + mpl_detail::is_same_mpl_vector_tag< typename ::boost::mpl::sequence_tag<T>::type, ::boost::mpl::sequence_tag< ::boost::mpl::vector<>>::type >::value diff --git a/boost/hana/fwd/basic_tuple.hpp b/boost/hana/fwd/basic_tuple.hpp index 8444f0f50e..69d4073f03 100644 --- a/boost/hana/fwd/basic_tuple.hpp +++ b/boost/hana/fwd/basic_tuple.hpp @@ -22,6 +22,11 @@ BOOST_HANA_NAMESPACE_BEGIN //! `std::tuple`, `basic_tuple` provides the strict minimum required to //! implement a closure with maximum compile-time efficiency. //! + //! @note + //! When you use a container, remember not to make assumptions about its + //! representation, unless the documentation gives you those guarantees. + //! More details [in the tutorial](@ref tutorial-containers-types). + //! //! //! Modeled concepts //! ---------------- diff --git a/boost/hana/fwd/empty.hpp b/boost/hana/fwd/empty.hpp index ed3cc38cc7..719f58055f 100644 --- a/boost/hana/fwd/empty.hpp +++ b/boost/hana/fwd/empty.hpp @@ -41,7 +41,9 @@ BOOST_HANA_NAMESPACE_BEGIN struct empty_impl : empty_impl<M, when<true>> { }; template <typename M> - struct empty_t; + struct empty_t { + constexpr auto operator()() const; + }; template <typename M> constexpr empty_t<M> empty{}; diff --git a/boost/hana/fwd/lift.hpp b/boost/hana/fwd/lift.hpp index 9491dab8a4..2d4ac6cc13 100644 --- a/boost/hana/fwd/lift.hpp +++ b/boost/hana/fwd/lift.hpp @@ -49,7 +49,10 @@ BOOST_HANA_NAMESPACE_BEGIN struct lift_impl : lift_impl<A, when<true>> { }; template <typename A> - struct lift_t; + struct lift_t { + template <typename X> + constexpr auto operator()(X&& x) const; + }; template <typename A> constexpr lift_t<A> lift{}; diff --git a/boost/hana/fwd/map.hpp b/boost/hana/fwd/map.hpp index c00f57195f..782b0f1e97 100644 --- a/boost/hana/fwd/map.hpp +++ b/boost/hana/fwd/map.hpp @@ -36,21 +36,23 @@ BOOST_HANA_NAMESPACE_BEGIN //! keys must be `Hashable`, and any two keys with equal hashes must be //! `Comparable` with each other at compile-time. //! - //! Note that the actual representation of a `hana::map` is an implementation + //! @note + //! The actual representation of a `hana::map` is an implementation //! detail. As such, one should not assume anything more than what is //! explicitly documented as being part of the interface of a map, //! such as: //! - the presence of additional constructors //! - the presence of additional assignment operators //! - the fact that `hana::map<Pairs...>` is, or is not, a dependent type - //! + //! . //! In particular, the last point is very important; `hana::map<Pairs...>` //! is basically equivalent to //! @code //! decltype(hana::make_pair(std::declval<Pairs>()...)) //! @endcode //! which is not something that can be pattern-matched on during template - //! argument deduction, for example. + //! argument deduction, for example. More details [in the tutorial] + //! (@ref tutorial-containers-types). //! //! //! Modeled concepts diff --git a/boost/hana/fwd/monadic_fold_left.hpp b/boost/hana/fwd/monadic_fold_left.hpp index c037989dea..aa66097b3e 100644 --- a/boost/hana/fwd/monadic_fold_left.hpp +++ b/boost/hana/fwd/monadic_fold_left.hpp @@ -94,7 +94,13 @@ BOOST_HANA_NAMESPACE_BEGIN struct monadic_fold_left_impl : monadic_fold_left_impl<T, when<true>> { }; template <typename M> - struct monadic_fold_left_t; + struct monadic_fold_left_t { + template <typename Xs, typename State, typename F> + constexpr decltype(auto) operator()(Xs&& xs, State&& state, F&& f) const; + + template <typename Xs, typename F> + constexpr decltype(auto) operator()(Xs&& xs, F&& f) const; + }; template <typename M> constexpr monadic_fold_left_t<M> monadic_fold_left{}; diff --git a/boost/hana/fwd/monadic_fold_right.hpp b/boost/hana/fwd/monadic_fold_right.hpp index 2028e15369..fff6fc0c1f 100644 --- a/boost/hana/fwd/monadic_fold_right.hpp +++ b/boost/hana/fwd/monadic_fold_right.hpp @@ -96,7 +96,13 @@ BOOST_HANA_NAMESPACE_BEGIN struct monadic_fold_right_impl : monadic_fold_right_impl<T, when<true>> { }; template <typename M> - struct monadic_fold_right_t; + struct monadic_fold_right_t { + template <typename Xs, typename State, typename F> + constexpr decltype(auto) operator()(Xs&& xs, State&& state, F&& f) const; + + template <typename Xs, typename F> + constexpr decltype(auto) operator()(Xs&& xs, F&& f) const; + }; template <typename M> constexpr monadic_fold_right_t<M> monadic_fold_right{}; diff --git a/boost/hana/fwd/one.hpp b/boost/hana/fwd/one.hpp index d2c67b7228..27d4f37bd6 100644 --- a/boost/hana/fwd/one.hpp +++ b/boost/hana/fwd/one.hpp @@ -35,7 +35,9 @@ BOOST_HANA_NAMESPACE_BEGIN struct one_impl : one_impl<R, when<true>> { }; template <typename R> - struct one_t; + struct one_t { + constexpr decltype(auto) operator()() const; + }; template <typename R> constexpr one_t<R> one{}; diff --git a/boost/hana/fwd/optional.hpp b/boost/hana/fwd/optional.hpp index 28bb68e8af..8a348a8b12 100644 --- a/boost/hana/fwd/optional.hpp +++ b/boost/hana/fwd/optional.hpp @@ -38,6 +38,11 @@ BOOST_HANA_NAMESPACE_BEGIN //! by the compiler. This makes `hana::optional` well suited for static //! metaprogramming tasks, but very poor for anything dynamic. //! + //! @note + //! When you use a container, remember not to make assumptions about its + //! representation, unless the documentation gives you those guarantees. + //! More details [in the tutorial](@ref tutorial-containers-types). + //! //! //! Interoperation with `type`s //! --------------------------- diff --git a/boost/hana/fwd/pair.hpp b/boost/hana/fwd/pair.hpp index 897e87ad12..1ce0e22772 100644 --- a/boost/hana/fwd/pair.hpp +++ b/boost/hana/fwd/pair.hpp @@ -24,6 +24,11 @@ BOOST_HANA_NAMESPACE_BEGIN //! Instead, one must use the `hana::first` and `hana::second` free //! functions to access the elements of a pair. //! + //! @note + //! When you use a container, remember not to make assumptions about its + //! representation, unless the documentation gives you those guarantees. + //! More details [in the tutorial](@ref tutorial-containers-types). + //! //! //! Modeled concepts //! ---------------- diff --git a/boost/hana/fwd/product.hpp b/boost/hana/fwd/product.hpp index 96bbd77c4e..ff545ceacb 100644 --- a/boost/hana/fwd/product.hpp +++ b/boost/hana/fwd/product.hpp @@ -60,7 +60,10 @@ BOOST_HANA_NAMESPACE_BEGIN struct product_impl : product_impl<T, when<true>> { }; template <typename R> - struct product_t; + struct product_t { + template <typename Xs> + constexpr decltype(auto) operator()(Xs&& xs) const; + }; template <typename R = integral_constant_tag<int>> constexpr product_t<R> product{}; diff --git a/boost/hana/fwd/range.hpp b/boost/hana/fwd/range.hpp index 82d0f75232..3fb2a939dc 100644 --- a/boost/hana/fwd/range.hpp +++ b/boost/hana/fwd/range.hpp @@ -35,7 +35,8 @@ BOOST_HANA_NAMESPACE_BEGIN //! The representation of `hana::range` is implementation defined. In //! particular, one should not take for granted the number and types //! of template parameters. The proper way to create a `hana::range` - //! is to use `hana::range_c` or `hana::make_range`. + //! is to use `hana::range_c` or `hana::make_range`. More details + //! [in the tutorial](@ref tutorial-containers-types). //! //! //! Modeled concepts diff --git a/boost/hana/fwd/replicate.hpp b/boost/hana/fwd/replicate.hpp index 4861adabae..842812d692 100644 --- a/boost/hana/fwd/replicate.hpp +++ b/boost/hana/fwd/replicate.hpp @@ -65,7 +65,10 @@ BOOST_HANA_NAMESPACE_BEGIN struct replicate_impl : replicate_impl<M, when<true>> { }; template <typename M> - struct replicate_t; + struct replicate_t { + template <typename X, typename N> + constexpr auto operator()(X&& x, N const& n) const; + }; template <typename M> constexpr replicate_t<M> replicate{}; diff --git a/boost/hana/fwd/set.hpp b/boost/hana/fwd/set.hpp index 7312854782..acbcbc7fb5 100644 --- a/boost/hana/fwd/set.hpp +++ b/boost/hana/fwd/set.hpp @@ -30,7 +30,8 @@ BOOST_HANA_NAMESPACE_BEGIN //! In particular, one should not take for granted the order of the //! template parameters and the presence of any additional constructors //! or assignment operators than what is documented. The canonical way of - //! creating a `hana::set` is through `hana::make_set`. + //! creating a `hana::set` is through `hana::make_set`. More details + //! [in the tutorial](@ref tutorial-containers-types). //! //! //! Modeled concepts diff --git a/boost/hana/fwd/string.hpp b/boost/hana/fwd/string.hpp index 80c1622500..8af2e709ba 100644 --- a/boost/hana/fwd/string.hpp +++ b/boost/hana/fwd/string.hpp @@ -40,7 +40,8 @@ BOOST_HANA_NAMESPACE_BEGIN //! In particular, one should not take for granted that the template //! parameters are `char`s. The proper way to access the contents of //! a `hana::string` as character constants is to use `hana::unpack`, - //! `.c_str()` or `hana::to<char const*>`, as documented below. + //! `.c_str()` or `hana::to<char const*>`, as documented below. More + //! details [in the tutorial](@ref tutorial-containers-types). //! //! //! Modeled concepts @@ -212,7 +213,8 @@ BOOST_HANA_NAMESPACE_BEGIN //! //! This macro is a more convenient alternative to `string_c` for creating //! compile-time strings. However, since this macro uses a lambda - //! internally, it can't be used in an unevaluated context. + //! internally, it can't be used in an unevaluated context, or where + //! a constant expression is expected before C++17. //! //! //! Example diff --git a/boost/hana/fwd/sum.hpp b/boost/hana/fwd/sum.hpp index c565ecd7f7..6d7ee537b3 100644 --- a/boost/hana/fwd/sum.hpp +++ b/boost/hana/fwd/sum.hpp @@ -69,7 +69,10 @@ BOOST_HANA_NAMESPACE_BEGIN struct sum_impl : sum_impl<T, when<true>> { }; template <typename M> - struct sum_t; + struct sum_t { + template <typename Xs> + constexpr decltype(auto) operator()(Xs&& xs) const; + }; template <typename M = integral_constant_tag<int>> constexpr sum_t<M> sum{}; diff --git a/boost/hana/fwd/tap.hpp b/boost/hana/fwd/tap.hpp index 846c1d00e6..2f3809c1f3 100644 --- a/boost/hana/fwd/tap.hpp +++ b/boost/hana/fwd/tap.hpp @@ -55,7 +55,10 @@ BOOST_HANA_NAMESPACE_BEGIN struct tap_impl : tap_impl<M, when<true>> { }; template <typename M> - struct tap_t; + struct tap_t { + template <typename F> + constexpr auto operator()(F&& f) const; + }; template <typename M> constexpr tap_t<M> tap{}; diff --git a/boost/hana/fwd/tuple.hpp b/boost/hana/fwd/tuple.hpp index f51ab9ac22..9ee2e00ace 100644 --- a/boost/hana/fwd/tuple.hpp +++ b/boost/hana/fwd/tuple.hpp @@ -32,6 +32,11 @@ BOOST_HANA_NAMESPACE_BEGIN //! sequence with a key-based access, then you should consider //! `hana::map` or `hana::set` instead. //! + //! @note + //! When you use a container, remember not to make assumptions about its + //! representation, unless the documentation gives you those guarantees. + //! More details [in the tutorial](@ref tutorial-containers-types). + //! //! //! Modeled concepts //! ---------------- diff --git a/boost/hana/fwd/type.hpp b/boost/hana/fwd/type.hpp index c3c220db78..d087cee166 100644 --- a/boost/hana/fwd/type.hpp +++ b/boost/hana/fwd/type.hpp @@ -394,15 +394,13 @@ BOOST_HANA_NAMESPACE_BEGIN //! @endcode //! //! @note - //! `template_` can't be SFINAE-friendly right now because of - //! [Core issue 1430][1]. + //! In a SFINAE context, the expression `template_<f>(type_c<x>...)` is + //! valid whenever the expression `f<x...>` is valid. //! //! //! Example //! ------- //! @include example/type/template.cpp - //! - //! [1]: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1430 #ifdef BOOST_HANA_DOXYGEN_INVOKED template <template <typename ...> class F> constexpr auto template_ = [](basic_type<T>...) { @@ -426,6 +424,10 @@ BOOST_HANA_NAMESPACE_BEGIN //! decltype(metafunction<f>)::apply<x...>::type == f<x...>::type //! @endcode //! + //! @note + //! In a SFINAE context, the expression `metafunction<f>(type_c<x>...)` is + //! valid whenever the expression `f<x...>::%type` is valid. + //! //! //! Example //! ------- @@ -453,6 +455,10 @@ BOOST_HANA_NAMESPACE_BEGIN //! decltype(metafunction_class<f>)::apply<x...>::type == f::apply<x...>::type //! @endcode //! + //! @note + //! In a SFINAE context, the expression `metafunction_class<f>(type_c<x>...)` + //! is valid whenever the expression `f::apply<x...>::%type` is valid. + //! //! //! Example //! ------- @@ -464,9 +470,7 @@ BOOST_HANA_NAMESPACE_BEGIN }; #else template <typename F> - struct metafunction_class_t - : metafunction_t<F::template apply> - { }; + struct metafunction_class_t; template <typename F> constexpr metafunction_class_t<F> metafunction_class{}; @@ -498,6 +502,9 @@ BOOST_HANA_NAMESPACE_BEGIN //! boost/hana/ext/std/integral_constant.hpp header to ensure //! Hana can interoperate with the result. //! + //! - In a SFINAE context, the expression `integral(f)(t...)` is valid + //! whenever the expression `decltype(f(t...))::%type` is valid. + //! //! //! Example //! ------- diff --git a/boost/hana/fwd/zero.hpp b/boost/hana/fwd/zero.hpp index 412614786d..fcbcfcc372 100644 --- a/boost/hana/fwd/zero.hpp +++ b/boost/hana/fwd/zero.hpp @@ -35,7 +35,9 @@ BOOST_HANA_NAMESPACE_BEGIN struct zero_impl : zero_impl<M, when<true>> { }; template <typename M> - struct zero_t; + struct zero_t { + constexpr decltype(auto) operator()() const; + }; template <typename M> constexpr zero_t<M> zero{}; diff --git a/boost/hana/lift.hpp b/boost/hana/lift.hpp index b8ab3431c2..c1d7803788 100644 --- a/boost/hana/lift.hpp +++ b/boost/hana/lift.hpp @@ -20,22 +20,22 @@ Distributed under the Boost Software License, Version 1.0. BOOST_HANA_NAMESPACE_BEGIN + //! @cond template <typename A> - struct lift_t { + template <typename X> + constexpr auto lift_t<A>::operator()(X&& x) const { #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::Applicative<A>::value, "hana::lift<A> requires 'A' to be an Applicative"); #endif - template <typename X> - constexpr auto operator()(X&& x) const { - using Lift = BOOST_HANA_DISPATCH_IF(lift_impl<A>, - hana::Applicative<A>::value - ); + using Lift = BOOST_HANA_DISPATCH_IF(lift_impl<A>, + hana::Applicative<A>::value + ); - return Lift::apply(static_cast<X&&>(x)); - } - }; + return Lift::apply(static_cast<X&&>(x)); + } + //! @endcond template <typename A, bool condition> struct lift_impl<A, when<condition>> : default_ { diff --git a/boost/hana/map.hpp b/boost/hana/map.hpp index 8da5012190..7356208bc6 100644 --- a/boost/hana/map.hpp +++ b/boost/hana/map.hpp @@ -124,7 +124,7 @@ BOOST_HANA_NAMESPACE_BEGIN }; template <typename HashTable, typename Storage> - struct map_impl + struct map_impl final : detail::searchable_operators<map_impl<HashTable, Storage>> , detail::operators::adl<map_impl<HashTable, Storage>> { diff --git a/boost/hana/monadic_fold_left.hpp b/boost/hana/monadic_fold_left.hpp index e06c405604..3a1e8142a7 100644 --- a/boost/hana/monadic_fold_left.hpp +++ b/boost/hana/monadic_fold_left.hpp @@ -27,46 +27,50 @@ Distributed under the Boost Software License, Version 1.0. BOOST_HANA_NAMESPACE_BEGIN + //! @cond template <typename M> - struct monadic_fold_left_t { + template <typename Xs, typename State, typename F> + constexpr decltype(auto) monadic_fold_left_t<M>::operator()(Xs&& xs, State&& state, F&& f) const { + using S = typename hana::tag_of<Xs>::type; + using MonadicFoldLeft = BOOST_HANA_DISPATCH_IF(monadic_fold_left_impl<S>, + hana::Foldable<S>::value + ); + #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::Monad<M>::value, "hana::monadic_fold_left<M> requires 'M' to be a Monad"); - #endif - template <typename Xs, typename State, typename F> - constexpr decltype(auto) operator()(Xs&& xs, State&& state, F&& f) const { - using S = typename hana::tag_of<Xs>::type; - using MonadicFoldLeft = BOOST_HANA_DISPATCH_IF(monadic_fold_left_impl<S>, - hana::Foldable<S>::value - ); + static_assert(hana::Foldable<S>::value, + "hana::monadic_fold_left<M>(xs, state, f) requires 'xs' to be Foldable"); + #endif - #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS - static_assert(hana::Foldable<S>::value, - "hana::monadic_fold_left<M>(xs, state, f) requires 'xs' to be Foldable"); - #endif + return MonadicFoldLeft::template apply<M>(static_cast<Xs&&>(xs), + static_cast<State&&>(state), + static_cast<F&&>(f)); + } + //! @endcond - return MonadicFoldLeft::template apply<M>(static_cast<Xs&&>(xs), - static_cast<State&&>(state), - static_cast<F&&>(f)); - } + //! @cond + template <typename M> + template <typename Xs, typename F> + constexpr decltype(auto) monadic_fold_left_t<M>::operator()(Xs&& xs, F&& f) const { + using S = typename hana::tag_of<Xs>::type; + using MonadicFoldLeft = BOOST_HANA_DISPATCH_IF(monadic_fold_left_impl<S>, + hana::Foldable<S>::value + ); - template <typename Xs, typename F> - constexpr decltype(auto) operator()(Xs&& xs, F&& f) const { - using S = typename hana::tag_of<Xs>::type; - using MonadicFoldLeft = BOOST_HANA_DISPATCH_IF(monadic_fold_left_impl<S>, - hana::Foldable<S>::value - ); + #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS + static_assert(hana::Monad<M>::value, + "hana::monadic_fold_left<M> requires 'M' to be a Monad"); - #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS - static_assert(hana::Foldable<S>::value, - "hana::monadic_fold_left<M>(xs, f) requires 'xs' to be Foldable"); - #endif + static_assert(hana::Foldable<S>::value, + "hana::monadic_fold_left<M>(xs, f) requires 'xs' to be Foldable"); + #endif - return MonadicFoldLeft::template apply<M>(static_cast<Xs&&>(xs), - static_cast<F&&>(f)); - } - }; + return MonadicFoldLeft::template apply<M>(static_cast<Xs&&>(xs), + static_cast<F&&>(f)); + } + //! @endcond namespace detail { struct foldlM_helper { diff --git a/boost/hana/monadic_fold_right.hpp b/boost/hana/monadic_fold_right.hpp index 7026b058c3..c822d1d003 100644 --- a/boost/hana/monadic_fold_right.hpp +++ b/boost/hana/monadic_fold_right.hpp @@ -27,45 +27,49 @@ Distributed under the Boost Software License, Version 1.0. BOOST_HANA_NAMESPACE_BEGIN + //! @cond template <typename M> - struct monadic_fold_right_t { + template <typename Xs, typename State, typename F> + constexpr decltype(auto) monadic_fold_right_t<M>::operator()(Xs&& xs, State&& state, F&& f) const { + using S = typename hana::tag_of<Xs>::type; + using MonadicFoldRight = BOOST_HANA_DISPATCH_IF(monadic_fold_right_impl<S>, + hana::Foldable<S>::value + ); + #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::Monad<M>::value, "hana::monadic_fold_right<M> requires 'M' to be a Monad"); - #endif - template <typename Xs, typename State, typename F> - constexpr decltype(auto) operator()(Xs&& xs, State&& state, F&& f) const { - using S = typename hana::tag_of<Xs>::type; - using MonadicFoldRight = BOOST_HANA_DISPATCH_IF(monadic_fold_right_impl<S>, - hana::Foldable<S>::value - ); + static_assert(hana::Foldable<S>::value, + "hana::monadic_fold_right<M>(xs, state, f) requires 'xs' to be Foldable"); + #endif - #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS - static_assert(hana::Foldable<S>::value, - "hana::monadic_fold_right<M>(xs, state, f) requires 'xs' to be Foldable"); - #endif + return MonadicFoldRight::template apply<M>(static_cast<Xs&&>(xs), + static_cast<State&&>(state), + static_cast<F&&>(f)); + } + //! @endcond - return MonadicFoldRight::template apply<M>(static_cast<Xs&&>(xs), - static_cast<State&&>(state), - static_cast<F&&>(f)); - } + //! @cond + template <typename M> + template <typename Xs, typename F> + constexpr decltype(auto) monadic_fold_right_t<M>::operator()(Xs&& xs, F&& f) const { + using S = typename hana::tag_of<Xs>::type; + using MonadicFoldRight = BOOST_HANA_DISPATCH_IF(monadic_fold_right_impl<S>, + hana::Foldable<S>::value + ); - template <typename Xs, typename F> - constexpr decltype(auto) operator()(Xs&& xs, F&& f) const { - using S = typename hana::tag_of<Xs>::type; - using MonadicFoldRight = BOOST_HANA_DISPATCH_IF(monadic_fold_right_impl<S>, - hana::Foldable<S>::value - ); + #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS + static_assert(hana::Monad<M>::value, + "hana::monadic_fold_right<M> requires 'M' to be a Monad"); - #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS - static_assert(hana::Foldable<S>::value, - "hana::monadic_fold_right<M>(xs, f) requires 'xs' to be Foldable"); - #endif - return MonadicFoldRight::template apply<M>(static_cast<Xs&&>(xs), - static_cast<F&&>(f)); - } - }; + static_assert(hana::Foldable<S>::value, + "hana::monadic_fold_right<M>(xs, f) requires 'xs' to be Foldable"); + #endif + return MonadicFoldRight::template apply<M>(static_cast<Xs&&>(xs), + static_cast<F&&>(f)); + } + //! @endcond namespace detail { struct foldrM_helper { diff --git a/boost/hana/one.hpp b/boost/hana/one.hpp index b8d759b8c0..df27b1e834 100644 --- a/boost/hana/one.hpp +++ b/boost/hana/one.hpp @@ -23,21 +23,21 @@ Distributed under the Boost Software License, Version 1.0. BOOST_HANA_NAMESPACE_BEGIN + //! @cond template <typename R> - struct one_t { + constexpr decltype(auto) one_t<R>::operator()() const { #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::Ring<R>::value, "hana::one<R>() requires 'R' to be a Ring"); #endif - constexpr decltype(auto) operator()() const { - using One = BOOST_HANA_DISPATCH_IF(one_impl<R>, - hana::Ring<R>::value - ); + using One = BOOST_HANA_DISPATCH_IF(one_impl<R>, + hana::Ring<R>::value + ); - return One::apply(); - } - }; + return One::apply(); + } + //! @endcond template <typename R, bool condition> struct one_impl<R, when<condition>> : default_ { diff --git a/boost/hana/product.hpp b/boost/hana/product.hpp index 8d3bad9fc3..a419b15b40 100644 --- a/boost/hana/product.hpp +++ b/boost/hana/product.hpp @@ -23,28 +23,26 @@ Distributed under the Boost Software License, Version 1.0. BOOST_HANA_NAMESPACE_BEGIN + //! @cond template <typename R> - struct product_t { + template <typename Xs> + constexpr decltype(auto) product_t<R>::operator()(Xs&& xs) const { + using S = typename hana::tag_of<Xs>::type; + using Product = BOOST_HANA_DISPATCH_IF(product_impl<S>, + hana::Foldable<S>::value + ); + #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::Ring<R>::value, "hana::product<R> requires 'R' to be a Ring"); - #endif - - template <typename Xs> - constexpr decltype(auto) operator()(Xs&& xs) const { - using S = typename hana::tag_of<Xs>::type; - using Product = BOOST_HANA_DISPATCH_IF(product_impl<S>, - hana::Foldable<S>::value - ); - #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS - static_assert(hana::Foldable<S>::value, - "hana::product<R>(xs) requires 'xs' to be Foldable"); - #endif + static_assert(hana::Foldable<S>::value, + "hana::product<R>(xs) requires 'xs' to be Foldable"); + #endif - return Product::template apply<R>(static_cast<Xs&&>(xs)); - } - }; + return Product::template apply<R>(static_cast<Xs&&>(xs)); + } + //! @endcond template <typename T, bool condition> struct product_impl<T, when<condition>> : default_ { diff --git a/boost/hana/replicate.hpp b/boost/hana/replicate.hpp index f04c4d8a44..3d82712d4f 100644 --- a/boost/hana/replicate.hpp +++ b/boost/hana/replicate.hpp @@ -25,28 +25,26 @@ Distributed under the Boost Software License, Version 1.0. BOOST_HANA_NAMESPACE_BEGIN + //! @cond template <typename M> - struct replicate_t { + template <typename X, typename N> + constexpr auto replicate_t<M>::operator()(X&& x, N const& n) const { + using Replicate = BOOST_HANA_DISPATCH_IF(replicate_impl<M>, + hana::MonadPlus<M>::value && + hana::IntegralConstant<N>::value + ); + #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::MonadPlus<M>::value, "hana::replicate<M>(x, n) requires 'M' to be a MonadPlus"); - #endif - - template <typename X, typename N> - constexpr auto operator()(X&& x, N const& n) const { - using Replicate = BOOST_HANA_DISPATCH_IF(replicate_impl<M>, - hana::MonadPlus<M>::value && - hana::IntegralConstant<N>::value - ); - #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS - static_assert(hana::IntegralConstant<N>::value, - "hana::replicate<M>(x, n) requires 'n' to be an IntegralConstant"); - #endif + static_assert(hana::IntegralConstant<N>::value, + "hana::replicate<M>(x, n) requires 'n' to be an IntegralConstant"); + #endif - return Replicate::apply(static_cast<X&&>(x), n); - } - }; + return Replicate::apply(static_cast<X&&>(x), n); + } + //! @endcond template <typename M, bool condition> struct replicate_impl<M, when<condition>> : default_ { diff --git a/boost/hana/set.hpp b/boost/hana/set.hpp index 58979ed47f..53b4e8ec74 100644 --- a/boost/hana/set.hpp +++ b/boost/hana/set.hpp @@ -56,7 +56,7 @@ BOOST_HANA_NAMESPACE_BEGIN ////////////////////////////////////////////////////////////////////////// //! @cond template <typename ...Xs> - struct set + struct set final : detail::operators::adl<set<Xs...>> , detail::searchable_operators<set<Xs...>> { diff --git a/boost/hana/sum.hpp b/boost/hana/sum.hpp index 5c86dafdde..2b6f6b8219 100644 --- a/boost/hana/sum.hpp +++ b/boost/hana/sum.hpp @@ -23,28 +23,26 @@ Distributed under the Boost Software License, Version 1.0. BOOST_HANA_NAMESPACE_BEGIN + //! @cond template <typename M> - struct sum_t { + template <typename Xs> + constexpr decltype(auto) sum_t<M>::operator()(Xs&& xs) const { + using S = typename hana::tag_of<Xs>::type; + using Sum = BOOST_HANA_DISPATCH_IF(sum_impl<S>, + hana::Foldable<S>::value + ); + #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::Monoid<M>::value, "hana::sum<M> requires 'M' to be a Monoid"); - #endif - - template <typename Xs> - constexpr decltype(auto) operator()(Xs&& xs) const { - using S = typename hana::tag_of<Xs>::type; - using Sum = BOOST_HANA_DISPATCH_IF(sum_impl<S>, - hana::Foldable<S>::value - ); - #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS - static_assert(hana::Foldable<S>::value, - "hana::sum<M>(xs) requires 'xs' to be Foldable"); - #endif + static_assert(hana::Foldable<S>::value, + "hana::sum<M>(xs) requires 'xs' to be Foldable"); + #endif - return Sum::template apply<M>(static_cast<Xs&&>(xs)); - } - }; + return Sum::template apply<M>(static_cast<Xs&&>(xs)); + } + //! @endcond template <typename T, bool condition> struct sum_impl<T, when<condition>> : default_ { diff --git a/boost/hana/tap.hpp b/boost/hana/tap.hpp index 7d37318255..332f9ff83d 100644 --- a/boost/hana/tap.hpp +++ b/boost/hana/tap.hpp @@ -20,22 +20,22 @@ Distributed under the Boost Software License, Version 1.0. BOOST_HANA_NAMESPACE_BEGIN + //! @cond template <typename M> - struct tap_t { + template <typename F> + constexpr auto tap_t<M>::operator()(F&& f) const { #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::Monad<M>::value, "hana::tap<M> requires 'M' to be a Monad"); #endif - template <typename F> - constexpr auto operator()(F&& f) const { - using Tap = BOOST_HANA_DISPATCH_IF(tap_impl<M>, - hana::Monad<M>::value - ); + using Tap = BOOST_HANA_DISPATCH_IF(tap_impl<M>, + hana::Monad<M>::value + ); - return Tap::apply(static_cast<F&&>(f)); - } - }; + return Tap::apply(static_cast<F&&>(f)); + } + //! @endcond namespace detail { template <typename M> diff --git a/boost/hana/tuple.hpp b/boost/hana/tuple.hpp index 3354a84bee..ae3cba819d 100644 --- a/boost/hana/tuple.hpp +++ b/boost/hana/tuple.hpp @@ -75,7 +75,7 @@ BOOST_HANA_NAMESPACE_BEGIN // tuple ////////////////////////////////////////////////////////////////////////// template <> - struct tuple<> + struct tuple<> final : detail::operators::adl<tuple<>> , detail::iterable_operators<tuple<>> { @@ -84,7 +84,7 @@ BOOST_HANA_NAMESPACE_BEGIN }; template <typename ...Xn> - struct tuple + struct tuple final : detail::operators::adl<tuple<Xn...>> , detail::iterable_operators<tuple<Xn...>> { diff --git a/boost/hana/type.hpp b/boost/hana/type.hpp index 80a498753f..b1d3e2a308 100644 --- a/boost/hana/type.hpp +++ b/boost/hana/type.hpp @@ -14,6 +14,7 @@ Distributed under the Boost Software License, Version 1.0. #include <boost/hana/bool.hpp> #include <boost/hana/config.hpp> +#include <boost/hana/core/when.hpp> #include <boost/hana/detail/operators/adl.hpp> #include <boost/hana/detail/operators/comparable.hpp> #include <boost/hana/fwd/concept/metafunction.hpp> @@ -152,6 +153,24 @@ BOOST_HANA_NAMESPACE_BEGIN ////////////////////////////////////////////////////////////////////////// // template_ ////////////////////////////////////////////////////////////////////////// + // Note: We have to use the very complicated trick below instead of just + // mentionning `F<T...>` in a SFINAE-able context because of CWG 1430 + // (http://www.open-std.org/Jtc1/sc22/wg21/docs/cwg_active.html#1430). + namespace template_detail { + template <typename ...T> struct args; + template <typename ...> using always_void = void; + + template <template <typename ...> class F, typename Args, typename = void> + struct specialization_is_valid + : std::false_type + { }; + + template <template <typename ...> class F, typename ...T> + struct specialization_is_valid<F, args<T...>, always_void<F<T...>>> + : std::true_type + { }; + } // end namespace detail + template <template <typename ...> class F> struct template_t { template <typename ...T> @@ -159,7 +178,9 @@ BOOST_HANA_NAMESPACE_BEGIN using type = F<T...>; }; - template <typename ...T> + template <typename ...T, typename = std::enable_if_t< + template_detail::specialization_is_valid<F, template_detail::args<typename T::type...>>::value + >> constexpr auto operator()(T const& ...) const { return hana::type<F<typename T::type...>>{}; } }; @@ -178,6 +199,23 @@ BOOST_HANA_NAMESPACE_BEGIN }; ////////////////////////////////////////////////////////////////////////// + // metafunction_class + ////////////////////////////////////////////////////////////////////////// + namespace detail { + template <typename F, typename ...T> + struct always_first { using type = F; }; + } + template <typename F> + struct metafunction_class_t { + template <typename ...T> + using apply = typename detail::always_first<F, T...>::type::template apply<T...>; + + template <typename ...T> + constexpr hana::type<typename detail::always_first<F, T...>::type::template apply<typename T::type...>::type> + operator()(T const& ...) const { return {}; } + }; + + ////////////////////////////////////////////////////////////////////////// // Metafunction ////////////////////////////////////////////////////////////////////////// template <template <typename ...> class F> @@ -200,9 +238,10 @@ BOOST_HANA_NAMESPACE_BEGIN ////////////////////////////////////////////////////////////////////////// template <typename F> struct integral_t { - template <typename ...T> - constexpr auto operator()(T const& ...) const { - using Result = typename F::template apply<typename T::type...>::type; + template <typename ...T, typename Result = + typename detail::always_first<F, T...>::type::template apply<typename T::type...>::type + > + constexpr Result operator()(T const& ...) const { return Result{}; } }; diff --git a/boost/hana/version.hpp b/boost/hana/version.hpp index 70ba6fd9a1..c3a5b3982d 100644 --- a/boost/hana/version.hpp +++ b/boost/hana/version.hpp @@ -24,7 +24,7 @@ Distributed under the Boost Software License, Version 1.0. //! @ingroup group-config //! Macro expanding to the minor version of the library, i.e. the `y` in `x.y.z`. -#define BOOST_HANA_MINOR_VERSION 4 +#define BOOST_HANA_MINOR_VERSION 5 //! @ingroup group-config //! Macro expanding to the patch level of the library, i.e. the `z` in `x.y.z`. diff --git a/boost/hana/zero.hpp b/boost/hana/zero.hpp index baba9691f6..317023a1b3 100644 --- a/boost/hana/zero.hpp +++ b/boost/hana/zero.hpp @@ -23,21 +23,21 @@ Distributed under the Boost Software License, Version 1.0. BOOST_HANA_NAMESPACE_BEGIN + //! @cond template <typename M> - struct zero_t { + constexpr decltype(auto) zero_t<M>::operator()() const { #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::Monoid<M>::value, "hana::zero<M>() requires 'M' to be a Monoid"); #endif - constexpr decltype(auto) operator()() const { - using Zero = BOOST_HANA_DISPATCH_IF(zero_impl<M>, - hana::Monoid<M>::value - ); + using Zero = BOOST_HANA_DISPATCH_IF(zero_impl<M>, + hana::Monoid<M>::value + ); - return Zero::apply(); - } - }; + return Zero::apply(); + } + //! @endcond template <typename M, bool condition> struct zero_impl<M, when<condition>> : default_ { |