is_virtual_base_of.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // (C) Copyright Daniel Frey and Robert Ramey 2009.
  2. // (C) Copyright Balint Cserni 2017
  3. // Use, modification and distribution are subject to the Boost Software License,
  4. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt).
  6. //
  7. // See http://www.boost.org/libs/type_traits for most recent version including documentation.
  8. #ifndef BOOST_TT_IS_VIRTUAL_BASE_OF_HPP_INCLUDED
  9. #define BOOST_TT_IS_VIRTUAL_BASE_OF_HPP_INCLUDED
  10. #include <boost/type_traits/is_base_of.hpp>
  11. #include <boost/type_traits/is_same.hpp>
  12. #include <boost/type_traits/make_void.hpp>
  13. #include <utility>
  14. namespace boost {
  15. namespace detail {
  16. #ifdef BOOST_MSVC
  17. #pragma warning( push )
  18. #pragma warning( disable : 4584 4250 4594)
  19. #elif defined(__GNUC__) && (__GNUC__ >= 4)
  20. #pragma GCC system_header
  21. #endif
  22. #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) && !defined(BOOST_NO_CXX11_NULLPTR) && !BOOST_WORKAROUND(BOOST_GCC, < 40800)
  23. // Implementation based on the standard's rules of explicit type conversions.
  24. // A pointer to an object of *derived* class type may be explicitly converted to a pointer to an *unambiguous* *base* class type.
  25. // A pointer to an object of an *unambiguous* *non-virtual* *base* class type may be explicitly converted to a pointer of a *derived* class type.
  26. // Therefore Derived has a virtual base Base if and only if
  27. // (1) a Derived* can be converted to Base* (so the base class is unambiguous, which comes necessarily from virtual inheritance)
  28. // (2) a Base* cannot be converted to Derived* (so the base class is either ambiguous or virtual)
  29. // With both conditions true, Base must be a virtual base of Derived.
  30. // The "is_base_of" is only needed so the compiler can (but is not required to) error out if the types are incomplete.
  31. // This is in league with the the expected behaviour.
  32. template<class T, class U>
  33. constexpr bool is_virtual_base_impl(...) { return true; }
  34. // C-style casts have the power to ignore inheritance visibility while still act as a static_cast.
  35. // They can also fall back to the behaviour of reinterpret_cast, which allows is_virtual_base_of to work on non-class types too.
  36. // Note that because we are casting pointers there can be no user-defined operators to interfere.
  37. template<class T, class U,
  38. typename boost::make_void<decltype((U*)(std::declval<T*>()))>::type* =
  39. nullptr>
  40. constexpr bool is_virtual_base_impl(int) { return false; }
  41. } // namespace detail
  42. template<class T, class U>
  43. struct is_virtual_base_of : public
  44. boost::integral_constant<
  45. bool,
  46. boost::is_base_of<T, U>::value &&
  47. detail::is_virtual_base_impl<T, U>(0) &&
  48. !detail::is_virtual_base_impl<U, T>(0)
  49. > {};
  50. #else
  51. template<typename Base, typename Derived, typename tag>
  52. struct is_virtual_base_of_impl
  53. {
  54. BOOST_STATIC_CONSTANT(bool, value = false);
  55. };
  56. template<typename Base, typename Derived>
  57. struct is_virtual_base_of_impl<Base, Derived, true_type>
  58. {
  59. union max_align
  60. {
  61. unsigned u;
  62. unsigned long ul;
  63. void* v;
  64. double d;
  65. long double ld;
  66. #ifndef BOOST_NO_LONG_LONG
  67. long long ll;
  68. #endif
  69. };
  70. #ifdef __BORLANDC__
  71. struct boost_type_traits_internal_struct_X : public virtual Derived, public virtual Base
  72. {
  73. boost_type_traits_internal_struct_X();
  74. boost_type_traits_internal_struct_X(const boost_type_traits_internal_struct_X&);
  75. boost_type_traits_internal_struct_X& operator=(const boost_type_traits_internal_struct_X&);
  76. ~boost_type_traits_internal_struct_X()throw();
  77. max_align data[4];
  78. };
  79. struct boost_type_traits_internal_struct_Y : public virtual Derived
  80. {
  81. boost_type_traits_internal_struct_Y();
  82. boost_type_traits_internal_struct_Y(const boost_type_traits_internal_struct_Y&);
  83. boost_type_traits_internal_struct_Y& operator=(const boost_type_traits_internal_struct_Y&);
  84. ~boost_type_traits_internal_struct_Y()throw();
  85. max_align data[4];
  86. };
  87. #else
  88. struct boost_type_traits_internal_struct_X : public Derived, virtual Base
  89. {
  90. boost_type_traits_internal_struct_X();
  91. boost_type_traits_internal_struct_X(const boost_type_traits_internal_struct_X&);
  92. boost_type_traits_internal_struct_X& operator=(const boost_type_traits_internal_struct_X&);
  93. ~boost_type_traits_internal_struct_X()throw();
  94. max_align data[16];
  95. };
  96. struct boost_type_traits_internal_struct_Y : public Derived
  97. {
  98. boost_type_traits_internal_struct_Y();
  99. boost_type_traits_internal_struct_Y(const boost_type_traits_internal_struct_Y&);
  100. boost_type_traits_internal_struct_Y& operator=(const boost_type_traits_internal_struct_Y&);
  101. ~boost_type_traits_internal_struct_Y()throw();
  102. max_align data[16];
  103. };
  104. #endif
  105. BOOST_STATIC_CONSTANT(bool, value = (sizeof(boost_type_traits_internal_struct_X) == sizeof(boost_type_traits_internal_struct_Y)));
  106. };
  107. template<typename Base, typename Derived>
  108. struct is_virtual_base_of_impl2
  109. {
  110. typedef boost::integral_constant<bool, (boost::is_base_of<Base, Derived>::value && !boost::is_same<Base, Derived>::value)> tag_type;
  111. typedef is_virtual_base_of_impl<Base, Derived, tag_type> imp;
  112. BOOST_STATIC_CONSTANT(bool, value = imp::value);
  113. };
  114. } // namespace detail
  115. template <class Base, class Derived> struct is_virtual_base_of : public integral_constant<bool, (::boost::detail::is_virtual_base_of_impl2<Base, Derived>::value)> {};
  116. #endif
  117. template <class Base, class Derived> struct is_virtual_base_of<Base&, Derived> : public false_type{};
  118. template <class Base, class Derived> struct is_virtual_base_of<Base, Derived&> : public false_type{};
  119. template <class Base, class Derived> struct is_virtual_base_of<Base&, Derived&> : public false_type{};
  120. #ifdef BOOST_MSVC
  121. #pragma warning( pop )
  122. #endif
  123. } // namespace boost
  124. #endif