summaryrefslogtreecommitdiff
path: root/boost/hana/detail/has_duplicates.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/hana/detail/has_duplicates.hpp')
-rw-r--r--boost/hana/detail/has_duplicates.hpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/boost/hana/detail/has_duplicates.hpp b/boost/hana/detail/has_duplicates.hpp
new file mode 100644
index 0000000000..191f1e744e
--- /dev/null
+++ b/boost/hana/detail/has_duplicates.hpp
@@ -0,0 +1,65 @@
+/*!
+@file
+Defines `boost::hana::detail::has_duplicates`.
+
+@copyright Louis Dionne 2013-2016
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_HANA_DETAIL_HAS_DUPLICATES_HPP
+#define BOOST_HANA_DETAIL_HAS_DUPLICATES_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/fast_and.hpp>
+#include <boost/hana/equal.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN namespace detail {
+ template <typename T, typename ...U>
+ constexpr std::size_t pack_count() {
+ std::size_t c = 0;
+ std::size_t expand[] = {0, // avoid empty array
+ (decltype(hana::equal(std::declval<T>(), std::declval<U>()))::value
+ ? ++c
+ : c)...
+ };
+ (void)expand;
+
+ return c;
+ }
+
+ //! @ingroup group-details
+ //! Returns whether any of the `T`s are duplicate w.r.t. `hana::equal`.
+ //!
+ //! In particular, this does not check whether all of the `T`s are unique
+ //! as _types_, but rather whether they are unique when compared as
+ //! `hana::equal(std::declval<T>(), std::declval<U>())`. This assumes
+ //! the comparison to return an `IntegralConstant` that can be explicitly
+ //! converted to `bool`.
+ //!
+ //! @note
+ //! Since this utility is mostly used in assertions to check that there
+ //! are no duplicates in a sequence, we expect it to return `false` most
+ //! of the time (otherwise we will assert). Hence, this implementation is
+ //! biased towards the fact that we __will__ have to compare every pair of
+ //! elements in most cases, and it does not try to be lazy.
+ //!
+ //! @todo
+ //! This implementation is O(n^2). We could do it in O(n), but that would
+ //! require a more elaborate setup including storage with O(1) lookup
+ //! (which could be based on a compile-time hash). If we implement such
+ //! storage for associative sequences, we could use it to optimize this.
+ template <typename ...T>
+ struct has_duplicates {
+ static constexpr bool value =
+ sizeof...(T) > 0 &&
+ !detail::fast_and<(detail::pack_count<T, T...>() == 1)...>::value
+ ;
+ };
+} BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_DETAIL_HAS_DUPLICATES_HPP