Skip to content

Commit

Permalink
Merge pull request #1716 from ericniebler/moar-constraint-recursion
Browse files Browse the repository at this point in the history
work around strange gcc bug causing constraint recursion in ranges::any
  • Loading branch information
ericniebler authored Jun 23, 2022
2 parents 77bf1e3 + 390a35e commit 96d6712
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 30 deletions.
8 changes: 3 additions & 5 deletions include/range/v3/detail/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
58 changes: 33 additions & 25 deletions include/range/v3/utility/any.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,25 +61,9 @@ namespace ranges
template<typename T>
T const * any_cast(any const *) noexcept;

struct any
namespace _any_
{
private:
template<typename T>
friend meta::if_c<std::is_reference<T>() || (bool)copyable<T>, T> any_cast(any &);

template<typename T>
friend meta::if_c<std::is_reference<T>() || (bool)copyable<T>, T> any_cast(
any const &);

template<typename T>
friend meta::if_c<std::is_reference<T>() || (bool)copyable<T>, T> any_cast(
any &&);

template<typename T>
friend T * any_cast(any *) noexcept;

template<typename T>
friend T const * any_cast(any const *) noexcept;
struct _base {};

struct interface
{
Expand Down Expand Up @@ -117,15 +101,39 @@ namespace ranges
return typeid(T);
}
};
} // namespace _any_

struct any
#if RANGES_BROKEN_CPO_LOOKUP
: private _any_::_base
#endif
{
private:
template<typename T>
friend meta::if_c<std::is_reference<T>() || (bool)copyable<T>, T> any_cast(any &);

template<typename T>
friend meta::if_c<std::is_reference<T>() || (bool)copyable<T>, T> any_cast(
any const &);

template<typename T>
friend meta::if_c<std::is_reference<T>() || (bool)copyable<T>, T> any_cast(
any &&);

template<typename T>
friend T * any_cast(any *) noexcept;

template<typename T>
friend T const * any_cast(any const *) noexcept;

std::unique_ptr<interface> ptr_;
std::unique_ptr<_any_::interface> ptr_;

public:
any() noexcept = default;
template(typename TRef, typename T = detail::decay_t<TRef>)(
requires (!same_as<T, any>) AND copyable<T>) //
any(TRef && t)
: ptr_(new impl<T>(static_cast<TRef &&>(t)))
: ptr_(new _any_::impl<T>(static_cast<TRef &&>(t)))
{}
any(any &&) noexcept = default;
any(any const & that)
Expand Down Expand Up @@ -185,7 +193,7 @@ namespace ranges
{
if(x.type() != typeid(detail::decay_t<T>))
throw bad_any_cast{};
return static_cast<any::impl<detail::decay_t<T>> *>(x.ptr_.get())->get();
return static_cast<_any_::impl<detail::decay_t<T>> *>(x.ptr_.get())->get();
}

/// \overload
Expand All @@ -194,7 +202,7 @@ namespace ranges
{
if(x.type() != typeid(detail::decay_t<T>))
throw bad_any_cast{};
return static_cast<any::impl<detail::decay_t<T>> const *>(x.ptr_.get())->get();
return static_cast<_any_::impl<detail::decay_t<T>> const *>(x.ptr_.get())->get();
}

/// \overload
Expand All @@ -203,15 +211,15 @@ namespace ranges
{
if(x.type() != typeid(detail::decay_t<T>))
throw bad_any_cast{};
return static_cast<any::impl<detail::decay_t<T>> *>(x.ptr_.get())->get();
return static_cast<_any_::impl<detail::decay_t<T>> *>(x.ptr_.get())->get();
}

/// \overload
template<typename T>
T * any_cast(any * p) noexcept
{
if(p && p->ptr_)
if(any::impl<T> * q = dynamic_cast<any::impl<T> *>(p->ptr_.get()))
if(_any_::impl<T> * q = dynamic_cast<_any_::impl<T> *>(p->ptr_.get()))
return &q->get();
return nullptr;
}
Expand All @@ -221,7 +229,7 @@ namespace ranges
T const * any_cast(any const * p) noexcept
{
if(p && p->ptr_)
if(any::impl<T> const * q = dynamic_cast<any::impl<T> const *>(p->ptr_.get()))
if(_any_::impl<T> const * q = dynamic_cast<_any_::impl<T> const *>(p->ptr_.get()))
return &q->get();
return nullptr;
}
Expand Down

0 comments on commit 96d6712

Please sign in to comment.