From 390a35e5815d1cb4e40e87d332df711de379a852 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Wed, 22 Jun 2022 22:56:28 -0700 Subject: [PATCH] work around strange gcc bug causing constraint recursion in ranges::any --- include/range/v3/detail/config.hpp | 8 ++--- include/range/v3/utility/any.hpp | 58 +++++++++++++++++------------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/include/range/v3/detail/config.hpp b/include/range/v3/detail/config.hpp index f8015f436..d29dada10 100644 --- a/include/range/v3/detail/config.hpp +++ b/include/range/v3/detail/config.hpp @@ -351,9 +351,6 @@ namespace ranges #define RANGES_WORKAROUND_CLANG_43400 // template friend is redefinition of itself #endif #else // __GNUC__ -#if __GNUC__ < 6 -#define RANGES_WORKAROUND_GCC_UNFILED0 /* Workaround old GCC name lookup bug */ -#endif #if __GNUC__ == 7 || __GNUC__ == 8 #define RANGES_WORKAROUND_GCC_91525 /* Workaround strange GCC ICE */ #endif @@ -724,8 +721,9 @@ namespace ranges #endif #endif // RANGES_CONSTEXPR_IF -#if !defined(RANGES_BROKEN_CPO_LOOKUP) && !defined(RANGES_DOXYGEN_INVOKED) && \ - (defined(RANGES_WORKAROUND_GCC_UNFILED0) || defined(RANGES_WORKAROUND_MSVC_895622)) +#if !defined(RANGES_BROKEN_CPO_LOOKUP) && \ + !defined(RANGES_DOXYGEN_INVOKED) && \ + defined(RANGES_WORKAROUND_MSVC_895622) #define RANGES_BROKEN_CPO_LOOKUP 1 #endif #ifndef RANGES_BROKEN_CPO_LOOKUP diff --git a/include/range/v3/utility/any.hpp b/include/range/v3/utility/any.hpp index 5feb2f8cd..7a3807499 100644 --- a/include/range/v3/utility/any.hpp +++ b/include/range/v3/utility/any.hpp @@ -61,25 +61,9 @@ namespace ranges template T const * any_cast(any const *) noexcept; - struct any + namespace _any_ { - private: - template - friend meta::if_c() || (bool)copyable, T> any_cast(any &); - - template - friend meta::if_c() || (bool)copyable, T> any_cast( - any const &); - - template - friend meta::if_c() || (bool)copyable, T> any_cast( - any &&); - - template - friend T * any_cast(any *) noexcept; - - template - friend T const * any_cast(any const *) noexcept; + struct _base {}; struct interface { @@ -117,15 +101,39 @@ namespace ranges return typeid(T); } }; + } // namespace _any_ + + struct any + #if RANGES_BROKEN_CPO_LOOKUP + : private _any_::_base + #endif + { + private: + template + friend meta::if_c() || (bool)copyable, T> any_cast(any &); + + template + friend meta::if_c() || (bool)copyable, T> any_cast( + any const &); + + template + friend meta::if_c() || (bool)copyable, T> any_cast( + any &&); + + template + friend T * any_cast(any *) noexcept; + + template + friend T const * any_cast(any const *) noexcept; - std::unique_ptr ptr_; + std::unique_ptr<_any_::interface> ptr_; public: any() noexcept = default; template(typename TRef, typename T = detail::decay_t)( requires (!same_as) AND copyable) // any(TRef && t) - : ptr_(new impl(static_cast(t))) + : ptr_(new _any_::impl(static_cast(t))) {} any(any &&) noexcept = default; any(any const & that) @@ -185,7 +193,7 @@ namespace ranges { if(x.type() != typeid(detail::decay_t)) throw bad_any_cast{}; - return static_cast> *>(x.ptr_.get())->get(); + return static_cast<_any_::impl> *>(x.ptr_.get())->get(); } /// \overload @@ -194,7 +202,7 @@ namespace ranges { if(x.type() != typeid(detail::decay_t)) throw bad_any_cast{}; - return static_cast> const *>(x.ptr_.get())->get(); + return static_cast<_any_::impl> const *>(x.ptr_.get())->get(); } /// \overload @@ -203,7 +211,7 @@ namespace ranges { if(x.type() != typeid(detail::decay_t)) throw bad_any_cast{}; - return static_cast> *>(x.ptr_.get())->get(); + return static_cast<_any_::impl> *>(x.ptr_.get())->get(); } /// \overload @@ -211,7 +219,7 @@ namespace ranges T * any_cast(any * p) noexcept { if(p && p->ptr_) - if(any::impl * q = dynamic_cast *>(p->ptr_.get())) + if(_any_::impl * q = dynamic_cast<_any_::impl *>(p->ptr_.get())) return &q->get(); return nullptr; } @@ -221,7 +229,7 @@ namespace ranges T const * any_cast(any const * p) noexcept { if(p && p->ptr_) - if(any::impl const * q = dynamic_cast const *>(p->ptr_.get())) + if(_any_::impl const * q = dynamic_cast<_any_::impl const *>(p->ptr_.get())) return &q->get(); return nullptr; }