maybe.hpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // Copyright Daniel Wallin 2006.
  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. // 2009.10.21 TDS remove depenency on boost::python::detail::referent_storage
  7. //
  8. #ifndef BOOST_PARAMETER_MAYBE_091021_HPP
  9. #define BOOST_PARAMETER_MAYBE_091021_HPP
  10. namespace boost { namespace parameter { namespace aux {
  11. template <typename T>
  12. struct referent_size;
  13. }}} // namespace boost::parameter::aux
  14. #include <boost/parameter/config.hpp>
  15. namespace boost { namespace parameter { namespace aux {
  16. template <typename T>
  17. struct referent_size<T&>
  18. {
  19. BOOST_STATIC_CONSTANT(::std::size_t, value = sizeof(T));
  20. };
  21. }}} // namespace boost::parameter::aux
  22. #include <boost/type_traits/aligned_storage.hpp>
  23. namespace boost { namespace parameter { namespace aux {
  24. // A metafunction returning a POD type which can store U, where T == U&.
  25. // If T is not a reference type, returns a POD which can store T.
  26. template <typename T>
  27. struct referent_storage
  28. : ::boost::aligned_storage<
  29. ::boost::parameter::aux::referent_size<T>::value
  30. >
  31. {
  32. };
  33. }}} // namespace boost::parameter::aux
  34. #include <boost/parameter/aux_/is_maybe.hpp>
  35. #include <boost/optional/optional.hpp>
  36. #if defined(BOOST_PARAMETER_CAN_USE_MP11)
  37. #include <type_traits>
  38. #else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
  39. #include <boost/type_traits/add_lvalue_reference.hpp>
  40. #include <boost/type_traits/remove_cv.hpp>
  41. #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564))
  42. #include <boost/type_traits/add_const.hpp>
  43. #endif
  44. #endif // BOOST_PARAMETER_CAN_USE_MP11
  45. namespace boost { namespace parameter { namespace aux {
  46. template <typename T>
  47. struct maybe : ::boost::parameter::aux::maybe_base
  48. {
  49. #if defined(BOOST_PARAMETER_CAN_USE_MP11)
  50. typedef typename ::std::add_lvalue_reference<
  51. typename ::std::add_const<T>::type
  52. #else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
  53. typedef typename ::boost::add_lvalue_reference<
  54. #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564))
  55. T const
  56. #else
  57. typename ::boost::add_const<T>::type
  58. #endif
  59. #endif // BOOST_PARAMETER_CAN_USE_MP11
  60. >::type reference;
  61. #if defined(BOOST_PARAMETER_CAN_USE_MP11)
  62. typedef typename ::std::remove_cv<
  63. typename ::std::remove_reference<reference>::type
  64. #else
  65. typedef typename ::boost::remove_cv<
  66. BOOST_DEDUCED_TYPENAME ::boost::remove_reference<reference>::type
  67. #endif
  68. >::type non_cv_value;
  69. inline explicit maybe(T value_) : value(value_), constructed(false)
  70. {
  71. }
  72. inline maybe() : value(), constructed(false)
  73. {
  74. }
  75. ~maybe()
  76. {
  77. if (this->constructed)
  78. {
  79. this->destroy();
  80. }
  81. }
  82. inline reference construct(reference value_) const
  83. {
  84. return value_;
  85. }
  86. template <typename U>
  87. reference construct2(U const& value_) const
  88. {
  89. new (this->m_storage.address()) non_cv_value(value_);
  90. this->constructed = true;
  91. return *reinterpret_cast<non_cv_value*>(
  92. this->m_storage.address()
  93. );
  94. }
  95. template <typename U>
  96. inline reference construct(U const& value_) const
  97. {
  98. return this->construct2(value_);
  99. }
  100. void destroy()
  101. {
  102. reinterpret_cast<non_cv_value*>(
  103. this->m_storage.address()
  104. )->~non_cv_value();
  105. }
  106. typedef reference(
  107. ::boost::parameter::aux::maybe<T>::*safe_bool
  108. )() const;
  109. inline operator safe_bool() const
  110. {
  111. return this->value ? &::boost::parameter::aux::maybe<T>::get : 0;
  112. }
  113. inline reference get() const
  114. {
  115. return this->value.get();
  116. }
  117. private:
  118. ::boost::optional<T> value;
  119. mutable bool constructed;
  120. mutable typename ::boost::parameter::aux
  121. ::referent_storage<reference>::type m_storage;
  122. };
  123. }}} // namespace boost::parameter::aux
  124. #endif // include guard