diff --git a/include/boost/unordered/detail/foa.hpp b/include/boost/unordered/detail/foa.hpp index 82ebc4cb..66026009 100644 --- a/include/boost/unordered/detail/foa.hpp +++ b/include/boost/unordered/detail/foa.hpp @@ -975,6 +975,40 @@ public: static constexpr auto pocma= alloc_traits::propagate_on_container_move_assignment::value; + /* Avoid using nested lambdas with a `this` capture as it seems to trigger + * a bug in GCC: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80947 + * + * Rather than directly attempting to manipulate the visibility of the + * table class, it's easier to work around the bug by simply un-nesting the + * lambdas + */ + auto const move_element=[this](value_type* p){ + unchecked_insert(std::move(*p)); + }; + + auto const elementwise_move=[&,this]{ + /* The check above is redundant: we're setting up a compile-time + * barrier so that the compiler is convinced we're not throwing + * under noexcept(true) conditions. + */ + + reserve(x.size()); + BOOST_TRY{ + /* This works because subsequent x.clear() does not depend on the + * elements' values. + */ + + x.for_all_elements(move_element); + } + BOOST_CATCH(...){ + x.clear(); + BOOST_RETHROW + } + BOOST_CATCH_END + x.clear(); + }; + if(this!=&x){ clear(); h()=std::move(x.h()); @@ -987,29 +1021,8 @@ public: swap(arrays,x.arrays); swap(ml,x.ml); } - else if_constexpr([&,this]{ - /* The check above is redundant: we're setting up a compile-time - * barrier so that the compiler is convinced we're not throwing - * under noexcept(true) conditions. - */ - - reserve(x.size()); - BOOST_TRY{ - /* This works because subsequent x.clear() does not depend on the - * elements' values. - */ - - x.for_all_elements([this](value_type* p){ - unchecked_insert(type_policy::move(*p)); - }); - } - BOOST_CATCH(...){ - x.clear(); - BOOST_RETHROW - } - BOOST_CATCH_END - x.clear(); - }); + else if_constexpr( + elementwise_move); } return *this; }