is_virtual_base_of.hpp: simplify and use clang version for all compilers.

This commit is contained in:
jzmaddock
2018-05-11 17:19:44 +01:00
parent fbc50bfd12
commit 7bba2acbcc

View File

@ -27,11 +27,22 @@ namespace boost {
#if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) && !defined(BOOST_NO_CXX11_NULLPTR) && !BOOST_WORKAROUND(BOOST_GCC, < 40800)
#ifdef __clang__
// Implementation based on the standard's rules of explicit type conversions.
// A pointer to an object of *derived* class type may be explicitly converted to a pointer to an *unambiguous* *base* class type.
// 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.
// Therefore Derived has a virtual base Base if and only if
// (1) a Derived* can be converted to Base* (so the base class is unambiguous, which comes necessarily from virtual inheritance)
// (2) a Base* cannot be converted to Derived* (so the base class is either ambiguous or virtual)
// With both conditions true, Base must be a virtual base of Derived.
// The "is_base_of" is only needed so the compiler can (but is not required to) error out if the types are incomplete.
// This is in league with the the expected behaviour.
template<class T, class U>
constexpr bool is_virtual_base_impl(...) { return true; }
// C-style casts have the power to ignore inheritance visibility while still act as a static_cast.
// They can also fall back to the behaviour of reinterpret_cast, which allows is_virtual_base_of to work on non-class types too.
// Note that because we are casting pointers there can be no user-defined operators to interfere.
template<class T, class U,
boost::void_t<decltype((U*)(std::declval<T*>()))>* =
nullptr>
@ -48,49 +59,6 @@ namespace boost {
!detail::is_virtual_base_impl<U, T>(0)
> {};
#else
template<class Base, class Derived>
struct is_virtual_base_of_impl
{
template<class From, class To>
struct can_cast
{
typedef char YES;
typedef struct { char x[2]; } NO;
// C-style casts have the power to ignore inheritance visibility while still act as a static_cast.
// They can also fall back to the behaviour of reinterpret_cast, which allows is_virtual_base_of to work on non-class types too.
// Note that because we are casting pointers there can be no user-defined operators to interfere.
template<unsigned = sizeof((To*)((From*)(0)))> static YES test(int*);
static NO test(...);
BOOST_STATIC_CONSTANT(bool, value = (sizeof(test(nullptr)) == sizeof(YES)));
};
// Implementation based on the standard's rules of explicit type conversions.
// A pointer to an object of *derived* class type may be explicitly converted to a pointer to an *unambiguous* *base* class type.
// 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.
// Therefore Derived has a virtual base Base if and only if
// (1) a Derived* can be converted to Base* (so the base class is unambiguous, which comes necessarily from virtual inheritance)
// (2) a Base* cannot be converted to Derived* (so the base class is either ambiguous or virtual)
// With both conditions true, Base must be a virtual base of Derived.
// The "is_base_of" is only needed so the compiler can (but is not required to) error out if the types are incomplete.
// This is in league with the the expected behaviour.
BOOST_STATIC_CONSTANT(bool, value = (boost::is_base_of<Base, Derived>::value && can_cast<Derived, Base>::value && !can_cast<Base, Derived>::value));
};
#ifdef BOOST_MSVC
#pragma warning( pop )
#endif
} // namespace detail
template <class Base, class Derived> struct is_virtual_base_of : public integral_constant<bool, (::boost::detail::is_virtual_base_of_impl<Base, Derived>::value)>{};
#endif // __clang__
#else
template<typename Base, typename Derived, typename tag>