Patch only partly generated through https://github.com/llvm/llvm-project/pull/204789, our static-analysis framework does not handle all headers as well as I would love it to do. Differential Revision: https://phabricator.services.mozilla.com/D307815
59 lines
2.8 KiB
C++
59 lines
2.8 KiB
C++
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef nsCycleCollectionContainerParticipant_h_
|
|
#define nsCycleCollectionContainerParticipant_h_
|
|
|
|
#include <type_traits>
|
|
|
|
/*
|
|
* To be able to implement ImplCycleCollectionIndexedContainer, we need to
|
|
* handle const vs non-const. ImplCycleCollectionTrace requires that the the
|
|
* value traced is non-const, and historically ImplCycleCollectionTraverse has
|
|
* been declared to take either const or non-const values. This poses a problem
|
|
* for containers, since it's not possible to define one
|
|
* ImplCycleCollectionIndexedContainer for both the const and non-const case
|
|
* with a templated parameter for the type contained by the container. The
|
|
* reason for this is how overload resolution works when it sees non-generic
|
|
* types with different constness. The standard solution for this is to use a
|
|
* universal reference, but we can't do this only because suddenly our
|
|
* ImplCycleCollectionIndexedContainer would be valid for any type. To make this
|
|
* work we need a way to constrain the type and we need it to be a constraint on
|
|
* the container type, not the type contained.
|
|
*
|
|
* This is pretty much the proposal for std::is_specialization_of, but with
|
|
* names from the unofficial cycle collector namespace. We use this to be able
|
|
* to do partial specialization to overload containers whose contents we wish to
|
|
* have participate in cycle collection. `template <typename Container>
|
|
* EnableCycleCollectionIf<Container, SomeContainer>` allows us to restrict an
|
|
* overload to only happen for a type SomeContainer<T>, which we then can use to
|
|
* make sure that an ImplCycleCollectionIndexedContainer overload is for a
|
|
* particular container, const or not.
|
|
*
|
|
* Example:
|
|
*
|
|
* template <typename Container, typename Callback,
|
|
* EnableCycleCollectionIf<Container, nsTHashtable> = nullptr>
|
|
* inline void ImplCycleCollectionContainer(Container&& aField,
|
|
* Callback&& aCallback) {
|
|
* // Implementation goes here
|
|
* }
|
|
*/
|
|
template <typename, template <typename...> typename>
|
|
struct ImplCycleCollectionIsContainerT : std::false_type {};
|
|
|
|
template <template <typename...> typename Container, typename... Args>
|
|
struct ImplCycleCollectionIsContainerT<Container<Args...>, Container>
|
|
: std::true_type {};
|
|
|
|
template <typename T, template <typename...> typename Container>
|
|
constexpr bool ImplCycleCollectionIsContainer =
|
|
ImplCycleCollectionIsContainerT<std::remove_cvref_t<T>, Container>::value;
|
|
|
|
template <typename T, template <typename...> typename Container>
|
|
using EnableCycleCollectionIf =
|
|
typename std::enable_if_t<ImplCycleCollectionIsContainer<T, Container>>*;
|
|
|
|
#endif // nsCycleCollectionContainerParticipant_h_
|