From a753f703d1e532dbec5f89c6af834ccd72581ca9 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Sat, 19 Jan 2008 03:58:00 +0000 Subject: [PATCH] Made 'profiling' of objects in a FoldingSet trait-based using FoldingSetTrait instead of always assuming that the stored objects had a method called 'Profile'. The default behavior is to dispatch to a 'Profile' method (as before), but via template specialization this behavior can now be overridden by clients. Added templated class 'FoldingSetNodeWrapper', a generic wrapper class that allows one to insert objects into a FoldingSet that do not directly inherit from FoldingSetNode. This is useful for inserting objects that do not always need to pay the overhead of inheriting from FoldingSetNode, or were designed with that behavior in mind. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@46186 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/FoldingSet.h | 54 ++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index 9f4fb05d7f0..da1f16c60b3 100644 --- a/include/llvm/ADT/FoldingSet.h +++ b/include/llvm/ADT/FoldingSet.h @@ -225,6 +225,19 @@ typedef FoldingSetImpl::NodeID FoldingSetNodeID; template class FoldingSetIterator; +//===----------------------------------------------------------------------===// +/// FoldingSetTrait - This trait class is used to define behavior of how +/// to "profile" (in the FoldingSet parlance) an object of a given type. +/// The default behavior is to invoke a 'Profile' method on an object, but +/// through template specialization the behavior can be tailored for specific +/// types. Combined with the FoldingSetNodeWrapper classs, one can add objects +/// to FoldingSets that were not originally designed to have that behavior. +/// +template struct FoldingSetTrait { + static inline void Profile(const T& X, FoldingSetNodeID& ID) { X.Profile(ID);} + static inline void Profile(T& X, FoldingSetNodeID& ID) { X.Profile(ID); } +}; + //===----------------------------------------------------------------------===// /// FoldingSet - This template class is used to instantiate a specialized /// implementation of the folding set to the node class T. T must be a @@ -236,7 +249,7 @@ private: /// way to convert nodes into a unique specifier. virtual void GetNodeProfile(NodeID &ID, Node *N) const { T *TN = static_cast(N); - TN->Profile(ID); + FoldingSetTrait::Profile(*TN,ID); } public: @@ -307,6 +320,45 @@ public: FoldingSetIterator tmp = *this; ++*this; return tmp; } }; + +//===----------------------------------------------------------------------===// +/// FoldingSetNodeWrapper - This template class is used to "wrap" arbitrary +/// types in an enclosing object so that they can be inserted into FoldingSets. +template +class FoldingSetNodeWrapper : public FoldingSetNode { + T data; +public: + FoldingSetNodeWrapper(const T& x) : data(x) {} + virtual ~FoldingSetNodeWrapper(); + + template + explicit FoldingSetNodeWrapper(const A1& a1) + : data(a1) {} + + template + explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2) + : data(a1,a2) {} + + template + explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2, const A3& a3) + : data(a1,a2,a3) {} + + template + explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2, const A3& a3, + const A4& a4) + : data(a1,a2,a3,a4) {} + + template + explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2, const A3& a3, + const A4& a4, const A5& a5) + : data(a1,a2,a3,a4,a5) {} + + + void Profile(FoldingSetNodeID& ID) { FoldingSetTrait::Profile(data, ID); } + + operator T&() { return data; } + operator const T&() const { return data; } +}; } // End of namespace llvm. -- 2.34.1