summaryrefslogtreecommitdiff
path: root/boost/hana/map.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/hana/map.hpp')
-rw-r--r--boost/hana/map.hpp142
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)