has_duplicates.hpp 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. /*!
  2. @file
  3. Defines `boost::hana::detail::has_duplicates`.
  4. @copyright Louis Dionne 2013-2017
  5. Distributed under the Boost Software License, Version 1.0.
  6. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  7. */
  8. #ifndef BOOST_HANA_DETAIL_HAS_DUPLICATES_HPP
  9. #define BOOST_HANA_DETAIL_HAS_DUPLICATES_HPP
  10. #include <boost/hana/config.hpp>
  11. #include <boost/hana/detail/fast_and.hpp>
  12. #include <boost/hana/equal.hpp>
  13. #include <cstddef>
  14. #include <utility>
  15. BOOST_HANA_NAMESPACE_BEGIN namespace detail {
  16. template <typename T, typename ...U>
  17. constexpr std::size_t pack_count() {
  18. std::size_t c = 0;
  19. std::size_t expand[] = {0, // avoid empty array
  20. (decltype(hana::equal(std::declval<T>(), std::declval<U>()))::value
  21. ? ++c
  22. : c)...
  23. };
  24. (void)expand;
  25. return c;
  26. }
  27. //! @ingroup group-details
  28. //! Returns whether any of the `T`s are duplicate w.r.t. `hana::equal`.
  29. //!
  30. //! In particular, this does not check whether all of the `T`s are unique
  31. //! as _types_, but rather whether they are unique when compared as
  32. //! `hana::equal(std::declval<T>(), std::declval<U>())`. This assumes
  33. //! the comparison to return an `IntegralConstant` that can be explicitly
  34. //! converted to `bool`.
  35. //!
  36. //! @note
  37. //! Since this utility is mostly used in assertions to check that there
  38. //! are no duplicates in a sequence, we expect it to return `false` most
  39. //! of the time (otherwise we will assert). Hence, this implementation is
  40. //! biased towards the fact that we __will__ have to compare every pair of
  41. //! elements in most cases, and it does not try to be lazy.
  42. //!
  43. //! @todo
  44. //! This implementation is O(n^2). We could do it in O(n), but that would
  45. //! require a more elaborate setup including storage with O(1) lookup
  46. //! (which could be based on a compile-time hash). If we implement such
  47. //! storage for associative sequences, we could use it to optimize this.
  48. template <typename ...T>
  49. struct has_duplicates {
  50. static constexpr bool value =
  51. sizeof...(T) > 0 &&
  52. !detail::fast_and<(detail::pack_count<T, T...>() == 1)...>::value
  53. ;
  54. };
  55. } BOOST_HANA_NAMESPACE_END
  56. #endif // !BOOST_HANA_DETAIL_HAS_DUPLICATES_HPP