no_duplicate_tags.hpp 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /* Copyright 2003-2013 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/multi_index for library home page.
  7. */
  8. #ifndef BOOST_MULTI_INDEX_DETAIL_NO_DUPLICATE_TAGS_HPP
  9. #define BOOST_MULTI_INDEX_DETAIL_NO_DUPLICATE_TAGS_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  14. #include <boost/mpl/fold.hpp>
  15. #include <boost/mpl/set/set0.hpp>
  16. namespace boost{
  17. namespace multi_index{
  18. namespace detail{
  19. /* no_duplicate_tags check at compile-time that a tag list
  20. * has no duplicate tags.
  21. * The algorithm deserves some explanation: tags
  22. * are sequentially inserted into a mpl::set if they were
  23. * not already present. Due to the magic of mpl::set
  24. * (mpl::has_key is contant time), this operation takes linear
  25. * time, and even MSVC++ 6.5 handles it gracefully (other obvious
  26. * solutions are quadratic.)
  27. */
  28. struct duplicate_tag_mark{};
  29. struct duplicate_tag_marker
  30. {
  31. template <typename MplSet,typename Tag>
  32. struct apply
  33. {
  34. typedef mpl::s_item<
  35. typename mpl::if_<mpl::has_key<MplSet,Tag>,duplicate_tag_mark,Tag>::type,
  36. MplSet
  37. > type;
  38. };
  39. };
  40. template<typename TagList>
  41. struct no_duplicate_tags
  42. {
  43. typedef typename mpl::fold<
  44. TagList,
  45. mpl::set0<>,
  46. duplicate_tag_marker
  47. >::type aux;
  48. BOOST_STATIC_CONSTANT(
  49. bool,value=!(mpl::has_key<aux,duplicate_tag_mark>::value));
  50. };
  51. /* Variant for an index list: duplication is checked
  52. * across all the indices.
  53. */
  54. struct duplicate_tag_list_marker
  55. {
  56. template <typename MplSet,typename Index>
  57. struct apply:mpl::fold<
  58. BOOST_DEDUCED_TYPENAME Index::tag_list,
  59. MplSet,
  60. duplicate_tag_marker>
  61. {
  62. };
  63. };
  64. template<typename IndexList>
  65. struct no_duplicate_tags_in_index_list
  66. {
  67. typedef typename mpl::fold<
  68. IndexList,
  69. mpl::set0<>,
  70. duplicate_tag_list_marker
  71. >::type aux;
  72. BOOST_STATIC_CONSTANT(
  73. bool,value=!(mpl::has_key<aux,duplicate_tag_mark>::value));
  74. };
  75. } /* namespace multi_index::detail */
  76. } /* namespace multi_index */
  77. } /* namespace boost */
  78. #endif