mp_map_find.hpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #ifndef BOOST_MP11_DETAIL_MP_MAP_FIND_HPP_INCLUDED
  2. #define BOOST_MP11_DETAIL_MP_MAP_FIND_HPP_INCLUDED
  3. // Copyright 2015 Peter Dimov.
  4. //
  5. // Distributed under the Boost Software License, Version 1.0.
  6. //
  7. // See accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt
  9. #include <boost/mp11/utility.hpp>
  10. #include <boost/mp11/detail/config.hpp>
  11. #if BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, >= 140000 )
  12. #include <boost/mp11/detail/mp_list.hpp>
  13. #include <boost/mp11/detail/mp_append.hpp>
  14. #include <boost/mp11/detail/mp_front.hpp>
  15. #endif
  16. #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1930 )
  17. // not exactly good practice, but...
  18. namespace std
  19. {
  20. template<class... _Types> class tuple;
  21. }
  22. #endif
  23. namespace boost
  24. {
  25. namespace mp11
  26. {
  27. #if BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, >= 140000 )
  28. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120161
  29. namespace detail
  30. {
  31. template<class M, class K> struct mp_map_find_impl;
  32. template<template<class...> class M, class... T, class K> struct mp_map_find_impl<M<T...>, K>
  33. {
  34. template<class U> using _f = mp_if<std::is_same<mp_front<U>, K>, mp_list<U>, mp_list<>>;
  35. using _l = mp_append<_f<T>..., mp_list<void>>;
  36. using type = mp_front<_l>;
  37. };
  38. } // namespace detail
  39. template<class M, class K> using mp_map_find = typename detail::mp_map_find_impl<M, K>::type;
  40. #else
  41. // mp_map_find
  42. namespace detail
  43. {
  44. #if !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1930 )
  45. template<class T> using mpmf_wrap = mp_identity<T>;
  46. template<class T> using mpmf_unwrap = typename T::type;
  47. #else
  48. template<class... T> struct mpmf_tuple {};
  49. template<class T> struct mpmf_wrap_impl
  50. {
  51. using type = mp_identity<T>;
  52. };
  53. template<class... T> struct mpmf_wrap_impl< std::tuple<T...> >
  54. {
  55. using type = mp_identity< mpmf_tuple<T...> >;
  56. };
  57. template<class T> using mpmf_wrap = typename mpmf_wrap_impl<T>::type;
  58. template<class T> struct mpmf_unwrap_impl
  59. {
  60. using type = typename T::type;
  61. };
  62. template<class... T> struct mpmf_unwrap_impl< mp_identity< mpmf_tuple<T...> > >
  63. {
  64. using type = std::tuple<T...>;
  65. };
  66. template<class T> using mpmf_unwrap = typename mpmf_unwrap_impl<T>::type;
  67. #endif // #if !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1930 )
  68. template<class M, class K> struct mp_map_find_impl;
  69. template<template<class...> class M, class... T, class K> struct mp_map_find_impl<M<T...>, K>
  70. {
  71. using U = mp_inherit<mpmf_wrap<T>...>;
  72. template<template<class...> class L, class... U> static mp_identity<L<K, U...>> f( mp_identity<L<K, U...>>* );
  73. static mp_identity<void> f( ... );
  74. using type = mpmf_unwrap< decltype( f( static_cast<U*>(0) ) ) >;
  75. };
  76. } // namespace detail
  77. template<class M, class K> using mp_map_find = typename detail::mp_map_find_impl<M, K>::type;
  78. #endif
  79. } // namespace mp11
  80. } // namespace boost
  81. #endif // #ifndef BOOST_MP11_DETAIL_MP_MAP_FIND_HPP_INCLUDED