Make fallback is_complete implementation more robust.

When all else fails, at least indicate the types that we always know to
be incomplete: cv void and boundless arrays.

Also cleanup formatting a bit.
This commit is contained in:
Andrey Semashev
2023-05-21 15:05:13 +03:00
parent 448ac57c32
commit 14560070ca
2 changed files with 45 additions and 12 deletions

View File

@ -27,11 +27,10 @@
* DO NOT MAKE GENERAL USE OF THIS TRAIT, AS THE COMPLETENESS OF A TYPE
* VARIES ACROSS TRANSLATION UNITS AS WELL AS WITHIN A SINGLE UNIT.
*
*/
*/
namespace boost {
//
// We will undef this if the trait isn't fully functional:
//
@ -39,7 +38,7 @@ namespace boost {
#if !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40600)
namespace detail{
namespace detail {
template <std::size_t N>
struct ok_tag { double d; char c[N]; };
@ -48,15 +47,15 @@ namespace boost {
ok_tag<sizeof(T)> check_is_complete(int);
template <class T>
char check_is_complete(...);
}
} // namespace detail
template <class T> struct is_complete
: public integral_constant<bool, ::boost::is_function<typename boost::remove_reference<T>::type>::value || (sizeof(boost::detail::check_is_complete<T>(0)) != sizeof(char))> {};
#elif !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500)
namespace detail
{
namespace detail {
template <class T>
struct is_complete_imp
@ -70,7 +69,7 @@ namespace boost {
static const bool value = sizeof(check<T>(0)) == sizeof(type_traits::yes_type);
};
} // namespace detail
} // namespace detail
template <class T>
@ -78,11 +77,33 @@ namespace boost {
{};
template <class T>
struct is_complete<T&> : boost::is_complete<T> {};
#else
template <class T> struct is_complete
: public boost::integral_constant<bool, true> {};
namespace detail {
template <class T>
struct is_complete_impl : public boost::true_type {};
template < >
struct is_complete_impl<void> : public boost::false_type {};
template <class T>
struct is_complete_impl<T[]> : public boost::false_type {};
template <class T>
struct is_complete_impl<T&> : public is_complete_impl<T>::type {};
} // namespace detail
template <class T>
struct is_complete : public detail::is_complete_impl<T>::type {};
template <class T>
struct is_complete<const T> : public detail::is_complete_impl<T>::type {};
template <class T>
struct is_complete<volatile T> : public detail::is_complete_impl<T>::type {};
template <class T>
struct is_complete<const volatile T> : public detail::is_complete_impl<T>::type {};
#undef BOOST_TT_HAS_WORKING_IS_COMPLETE

View File

@ -14,6 +14,15 @@
TT_TEST_BEGIN(is_complete)
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<void>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<void const>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<void volatile>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<void const volatile>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<void*>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<void const*>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<void volatile*>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<void const volatile*>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<int>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<int const>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<int volatile>::value, true);
@ -31,9 +40,11 @@ BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<int[2]>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<int const[3]>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<int volatile[2][3]>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<int const volatile[4][5][6]>::value, true);
#ifdef BOOST_TT_HAS_WORKING_IS_COMPLETE
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<int[]>::value, false);
#endif
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<int const[]>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<int volatile[]>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<int const volatile[]>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<enum_UDT>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<UDT>::value, true);
@ -46,6 +57,7 @@ BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<test_abc1>::value, true);
#ifdef BOOST_TT_HAS_WORKING_IS_COMPLETE
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<incomplete_type>::value, false);
#endif
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<incomplete_type*>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<polymorphic_base>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<virtual_inherit6>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_complete<foo0_t>::value, true);