xoptional_meta.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /***************************************************************************
  2. * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
  3. * Martin Renou *
  4. * Copyright (c) QuantStack *
  5. * *
  6. * Distributed under the terms of the BSD 3-Clause License. *
  7. * *
  8. * The full license is in the file LICENSE, distributed with this software. *
  9. ****************************************************************************/
  10. #ifndef XTL_OPTIONAL_META_HPP
  11. #define XTL_OPTIONAL_META_HPP
  12. #include <type_traits>
  13. #include "xmasked_value_meta.hpp"
  14. #include "xmeta_utils.hpp"
  15. #include "xtype_traits.hpp"
  16. namespace xtl
  17. {
  18. template <class CT, class CB = bool>
  19. class xoptional;
  20. namespace detail
  21. {
  22. template <class E>
  23. struct is_xoptional_impl : std::false_type
  24. {
  25. };
  26. template <class CT, class CB>
  27. struct is_xoptional_impl<xoptional<CT, CB>> : std::true_type
  28. {
  29. };
  30. template <class CT, class CTO, class CBO>
  31. using converts_from_xoptional = disjunction<
  32. std::is_constructible<CT, const xoptional<CTO, CBO>&>,
  33. std::is_constructible<CT, xoptional<CTO, CBO>&>,
  34. std::is_constructible<CT, const xoptional<CTO, CBO>&&>,
  35. std::is_constructible<CT, xoptional<CTO, CBO>&&>,
  36. std::is_convertible<const xoptional<CTO, CBO>&, CT>,
  37. std::is_convertible<xoptional<CTO, CBO>&, CT>,
  38. std::is_convertible<const xoptional<CTO, CBO>&&, CT>,
  39. std::is_convertible<xoptional<CTO, CBO>&&, CT>
  40. >;
  41. template <class CT, class CTO, class CBO>
  42. using assigns_from_xoptional = disjunction<
  43. std::is_assignable<std::add_lvalue_reference_t<CT>, const xoptional<CTO, CBO>&>,
  44. std::is_assignable<std::add_lvalue_reference_t<CT>, xoptional<CTO, CBO>&>,
  45. std::is_assignable<std::add_lvalue_reference_t<CT>, const xoptional<CTO, CBO>&&>,
  46. std::is_assignable<std::add_lvalue_reference_t<CT>, xoptional<CTO, CBO>&&>
  47. >;
  48. template <class... Args>
  49. struct common_optional_impl;
  50. template <class T>
  51. struct common_optional_impl<T>
  52. {
  53. using type = std::conditional_t<is_xoptional_impl<T>::value, T, xoptional<T>>;
  54. };
  55. template <class T>
  56. struct identity
  57. {
  58. using type = T;
  59. };
  60. template <class T>
  61. struct get_value_type
  62. {
  63. using type = typename T::value_type;
  64. };
  65. template<class T1, class T2>
  66. struct common_optional_impl<T1, T2>
  67. {
  68. using decay_t1 = std::decay_t<T1>;
  69. using decay_t2 = std::decay_t<T2>;
  70. using type1 = xtl::mpl::eval_if_t<xtl::is_fundamental<decay_t1>, identity<decay_t1>, get_value_type<decay_t1>>;
  71. using type2 = xtl::mpl::eval_if_t<xtl::is_fundamental<decay_t2>, identity<decay_t2>, get_value_type<decay_t2>>;
  72. using type = xoptional<std::common_type_t<type1, type2>>;
  73. };
  74. template <class T1, class T2, class B2>
  75. struct common_optional_impl<T1, xoptional<T2, B2>>
  76. : common_optional_impl<T1, T2>
  77. {
  78. };
  79. template <class T1, class B1, class T2>
  80. struct common_optional_impl<xoptional<T1, B1>, T2>
  81. : common_optional_impl<T1, T2>
  82. {
  83. };
  84. template <class T1, class B1, class T2, class B2>
  85. struct common_optional_impl<xoptional<T1, B1>, xoptional<T2, B2>>
  86. : common_optional_impl<T1, T2>
  87. {
  88. };
  89. template <class T1, class T2, class... Args>
  90. struct common_optional_impl<T1, T2, Args...>
  91. {
  92. using type = typename common_optional_impl<
  93. typename common_optional_impl<T1, T2>::type,
  94. Args...
  95. >::type;
  96. };
  97. }
  98. template <class E>
  99. using is_xoptional = detail::is_xoptional_impl<E>;
  100. template <class E, class R = void>
  101. using disable_xoptional = std::enable_if_t<!is_xoptional<E>::value, R>;
  102. template <class... Args>
  103. struct at_least_one_xoptional : disjunction<is_xoptional<Args>...>
  104. {
  105. };
  106. template <class... Args>
  107. struct common_optional : detail::common_optional_impl<Args...>
  108. {
  109. };
  110. template <class... Args>
  111. using common_optional_t = typename common_optional<Args...>::type;
  112. template <class E>
  113. struct is_not_xoptional_nor_xmasked_value : negation<disjunction<is_xoptional<E>, is_xmasked_value<E>>>
  114. {
  115. };
  116. }
  117. #endif