diff options
Diffstat (limited to 'boost/hana/map.hpp')
-rw-r--r-- | boost/hana/map.hpp | 142 |
1 files changed, 126 insertions, 16 deletions
diff --git a/boost/hana/map.hpp b/boost/hana/map.hpp index 3161d9b777..cccf6cf3b9 100644 --- a/boost/hana/map.hpp +++ b/boost/hana/map.hpp @@ -2,7 +2,7 @@ @file Defines `boost::hana::map`. -@copyright Louis Dionne 2013-2016 +@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) */ @@ -27,6 +27,7 @@ Distributed under the Boost Software License, Version 1.0. #include <boost/hana/detail/fast_and.hpp> #include <boost/hana/detail/has_duplicates.hpp> #include <boost/hana/detail/hash_table.hpp> +#include <boost/hana/detail/intrinsics.hpp> #include <boost/hana/detail/operators/adl.hpp> #include <boost/hana/detail/operators/comparable.hpp> #include <boost/hana/detail/operators/searchable.hpp> @@ -73,6 +74,51 @@ BOOST_HANA_NAMESPACE_BEGIN ////////////////////////////////////////////////////////////////////////// //! @cond namespace detail { + template <typename ...> + struct storage_is_default_constructible; + template <typename ...T> + struct storage_is_default_constructible<hana::basic_tuple<T...>> { + static constexpr bool value = detail::fast_and< + BOOST_HANA_TT_IS_CONSTRUCTIBLE(T)... + >::value; + }; + + template <typename ...> + struct storage_is_copy_constructible; + template <typename ...T> + struct storage_is_copy_constructible<hana::basic_tuple<T...>> { + static constexpr bool value = detail::fast_and< + BOOST_HANA_TT_IS_CONSTRUCTIBLE(T, T const&)... + >::value; + }; + + template <typename ...> + struct storage_is_move_constructible; + template <typename ...T> + struct storage_is_move_constructible<hana::basic_tuple<T...>> { + static constexpr bool value = detail::fast_and< + BOOST_HANA_TT_IS_CONSTRUCTIBLE(T, T&&)... + >::value; + }; + + template <typename ...> + struct storage_is_copy_assignable; + template <typename ...T> + struct storage_is_copy_assignable<hana::basic_tuple<T...>> { + static constexpr bool value = detail::fast_and< + BOOST_HANA_TT_IS_ASSIGNABLE(T, T const&)... + >::value; + }; + + template <typename ...> + struct storage_is_move_assignable; + template <typename ...T> + struct storage_is_move_assignable<hana::basic_tuple<T...>> { + static constexpr bool value = detail::fast_and< + BOOST_HANA_TT_IS_ASSIGNABLE(T, T&&)... + >::value; + }; + template <typename HashTable, typename Storage> struct map_impl : detail::searchable_operators<map_impl<HashTable, Storage>> @@ -99,16 +145,62 @@ BOOST_HANA_NAMESPACE_BEGIN : storage(static_cast<Storage&&>(xs)) { } - constexpr map_impl() = default; - constexpr map_impl(map_impl const& other) = default; - constexpr map_impl(map_impl&& other) = default; + template <typename ...Dummy, typename = typename std::enable_if< + detail::storage_is_default_constructible<Storage, Dummy...>::value + >::type> + constexpr map_impl() + : storage() + { } + + template <typename ...Dummy, typename = typename std::enable_if< + detail::storage_is_copy_constructible<Storage, Dummy...>::value + >::type> + constexpr map_impl(map_impl const& other) + : storage(other.storage) + { } + + template <typename ...Dummy, typename = typename std::enable_if< + detail::storage_is_move_constructible<Storage, Dummy...>::value + >::type> + constexpr map_impl(map_impl&& other) + : storage(static_cast<Storage&&>(other.storage)) + { } + + template <typename ...Dummy, typename = typename std::enable_if< + detail::storage_is_move_assignable<Storage, Dummy...>::value + >::type> + constexpr map_impl& operator=(map_impl&& other) { + storage = static_cast<Storage&&>(other.storage); + return *this; + } + + template <typename ...Dummy, typename = typename std::enable_if< + detail::storage_is_copy_assignable<Storage, Dummy...>::value + >::type> + constexpr map_impl& operator=(map_impl const& other) { + storage = other.storage; + return *this; + } + + // Prevent the compiler from defining the default copy and move + // constructors, which interfere with the SFINAE above. + ~map_impl() = default; }; //! @endcond template <typename Storage> struct KeyAtIndex { template <std::size_t i> - using apply = decltype(hana::first(hana::get_impl<i>(std::declval<Storage>()))); + using apply = decltype(hana::first(hana::at_c<i>(std::declval<Storage>()))); + }; + + template <typename ...Pairs> + struct make_map_type { + using Storage = hana::basic_tuple<Pairs...>; + using HashTable = typename detail::make_hash_table< + detail::KeyAtIndex<Storage>::template apply, sizeof...(Pairs) + >::type; + using type = detail::map_impl<HashTable, Storage>; }; } @@ -146,14 +238,8 @@ BOOST_HANA_NAMESPACE_BEGIN "hana::make_map({keys, values}...) requires all the keys to have different hashes"); #endif - using Storage = hana::basic_tuple<typename detail::decay<Pairs>::type...>; - using HashTable = typename detail::make_hash_table< - detail::KeyAtIndex<Storage>::template apply, sizeof...(Pairs) - >::type; - - return detail::map_impl<HashTable, Storage>{ - hana::make_basic_tuple(static_cast<Pairs&&>(pairs)...) - }; + using Map = typename detail::make_map_type<typename detail::decay<Pairs>::type...>::type; + return Map{hana::make_basic_tuple(static_cast<Pairs&&>(pairs)...)}; } }; @@ -251,10 +337,20 @@ BOOST_HANA_NAMESPACE_BEGIN } template <typename Map, typename Key> - static constexpr auto apply(Map&& map, Key const& key) { - constexpr bool contains = hana::value<decltype(hana::contains(map, key))>(); + static constexpr auto apply_impl(Map&& map, Key const& key, hana::false_) { return erase_key_helper(static_cast<Map&&>(map), key, - hana::bool_c<contains>); + hana::contains(map, key)); + } + + template <typename Map, typename Key> + static constexpr auto apply_impl(Map&& map, Key const&, hana::true_) { + return static_cast<Map&&>(map); + } + + template <typename Map, typename Key> + static constexpr auto apply(Map&& map, Key const& key) { + constexpr bool is_empty = decltype(hana::length(map))::value == 0; + return apply_impl(static_cast<Map&&>(map), key, hana::bool_<is_empty>{}); } }; @@ -326,6 +422,20 @@ BOOST_HANA_NAMESPACE_BEGIN }; template <> + struct contains_impl<map_tag> { + template <typename Map, typename Key> + static constexpr auto apply(Map const&, Key const&) { + using RawMap = typename std::remove_reference<Map>::type; + using HashTable = typename RawMap::hash_table_type; + using Storage = typename RawMap::storage_type; + using MaybeIndex = typename detail::find_index< + HashTable, Key, detail::KeyAtIndex<Storage>::template apply + >::type; + return hana::bool_<!decltype(hana::is_nothing(MaybeIndex{}))::value>{}; + } + }; + + template <> struct any_of_impl<map_tag> { template <typename M, typename Pred> static constexpr auto apply(M const& map, Pred const& pred) |