diff --git a/pxr/usd/usd/prim.h b/pxr/usd/usd/prim.h index 9e8fdcb031..679ed3e1a4 100644 --- a/pxr/usd/usd/prim.h +++ b/pxr/usd/usd/prim.h @@ -43,8 +43,7 @@ #include "pxr/usd/sdf/path.h" -#include - +#include #include #include #include @@ -72,10 +71,10 @@ class UsdVariantSet; class SdfPayload; class UsdPrimSiblingIterator; -typedef boost::iterator_range UsdPrimSiblingRange; +class UsdPrimSiblingRange; class UsdPrimSubtreeIterator; -typedef boost::iterator_range UsdPrimSubtreeRange; +class UsdPrimSubtreeRange; /// \class UsdPrim /// @@ -2223,72 +2222,6 @@ class UsdPrim : public UsdObject _ProtoToInstancePathMap _GetProtoToInstancePathMap() const; }; -#ifdef doxygen -/// Forward iterator range of sibling ::UsdPrim s. This range type contains a -/// pair of UsdPrimSiblingIterator s, denoting a half-open range of UsdPrim -/// siblings. It provides a subset of container-like API, such as begin(), -/// end(), front(), empty(), etc. -class UsdPrimSiblingRange { -public: - /// Iterator type. - typedef UsdPrimSiblingIterator iterator; - /// Const iterator type. - typedef UsdPrimSiblingIterator const_iterator; - /// Iterator difference type. - typedef unspecified-integral-type difference_type; - /// Iterator value_type. - typedef iterator::value_type value_type; - /// Iterator reference_type. - typedef iterator::reference reference; - - /// Construct with a pair of iterators. - UsdPrimSiblingRange(UsdPrimSiblingIterator begin, - UsdPrimSiblingIterator end); - - /// Construct/convert from another compatible range type. - template - UsdPrimSiblingRange(const ForwardRange &r); - - /// Assign from another compatible range type. - template - UsdPrimSiblingRange &operator=(const ForwardRange &r); - - /// First iterator. - iterator begin() const; - - /// Past-the-end iterator. - iterator end() const; - - /// Return !empty(). - operator unspecified_bool_type() const; - - /// Equality compare. - bool equal(const iterator_range&) const; - - /// Return *begin(). This range must not be empty. - reference front() const; - - /// Advance this range's begin iterator. - iterator_range& advance_begin(difference_type n); - - /// Advance this range's end iterator. - iterator_range& advance_end(difference_type n); - - ; /// Return begin() == end(). - bool empty() const; - -private: - /// Equality comparison. - friend bool operator==(const UsdPrimSiblingRange &lhs, - const UsdPrimSiblingRange &rhs); - /// Inequality comparison. - friend bool operator!=(const UsdPrimSiblingRange &lhs, - const UsdPrimSiblingRange &rhs); -}; - -#else - - /// Forward traversal iterator of sibling ::UsdPrim s. This is a /// standard-compliant iterator that may be used with STL algorithms, etc. /// Filters according to a supplied predicate. @@ -2379,8 +2312,122 @@ class UsdPrimSiblingIterator { Usd_PrimFlagsPredicate _predicate; }; -// Typedef iterator range. -typedef boost::iterator_range UsdPrimSiblingRange; +/// Forward iterator range of sibling ::UsdPrim s. This range type contains a +/// pair of UsdPrimSiblingIterator s, denoting a half-open range of UsdPrim +/// siblings. It provides a subset of container-like API, such as begin(), +/// end(), front(), empty(), etc. +class UsdPrimSiblingRange { +public: + /// Iterator type. + typedef UsdPrimSiblingIterator iterator; + /// Const iterator type. + typedef UsdPrimSiblingIterator const_iterator; + /// Iterator difference type. + typedef std::ptrdiff_t difference_type; + /// Iterator value_type. + typedef iterator::value_type value_type; + /// Iterator reference_type. + typedef iterator::reference reference; + + UsdPrimSiblingRange() = default; + + /// Construct with a pair of iterators. + UsdPrimSiblingRange(UsdPrimSiblingIterator begin, + UsdPrimSiblingIterator end) : _begin(begin), + _end(end) {} + + /// First iterator. + iterator begin() const { return _begin; } + + /// First iterator. + const_iterator cbegin() const { return _begin; } + + /// Past-the-end iterator. + iterator end() const { return _end; } + + /// Past-the-end iterator. + const_iterator cend() const { return _end; } + + /// Return !empty(). + explicit operator bool() const { return !empty(); } + + /// Equality compare. + bool equal(const UsdPrimSiblingRange& other) const { + return _begin == other._begin && _end == other._end; + } + + /// Return *begin(). This range must not be empty. + reference front() const { + TF_DEV_AXIOM(!empty()); + return *begin(); + } + + /// Advance this range's begin iterator. + UsdPrimSiblingRange& advance_begin(difference_type n) { + std::advance(_begin, n); + return *this; + } + + /// Advance this range's end iterator. + UsdPrimSiblingRange& advance_end(difference_type n) { + std::advance(_end, n); + return *this; + } + + /// Return begin() == end(). + bool empty() const { return begin() == end(); } + +private: + /// Equality comparison. + friend bool operator==(const UsdPrimSiblingRange &lhs, + const UsdPrimSiblingRange &rhs) { + return lhs.equal(rhs); + } + + /// Equality comparison. + template + friend bool operator==(const UsdPrimSiblingRange& lhs, + const ForwardRange& rhs) { + static_assert( + std::is_same::value, + "rhs must be a forward iterator." + ); + return (std::distance(std::cbegin(lhs), std::cend(lhs)) == + std::distance(std::cbegin(rhs), std::cend(rhs))) && + std::equal(std::cbegin(lhs), std::cend(lhs), std::cbegin(rhs)); + } + + /// Equality comparison. + template + friend bool operator==(const ForwardRange& lhs, + const UsdPrimSiblingRange& rhs) { + return rhs == lhs; + } + + /// Inequality comparison. + friend bool operator!=(const UsdPrimSiblingRange &lhs, + const UsdPrimSiblingRange &rhs) { + return !lhs.equal(rhs); + } + + /// Inequality comparison. + template + friend bool operator!=(const ForwardRange& lhs, + const UsdPrimSiblingRange& rhs) { + return !(lhs == rhs); + } + + /// Inequality comparison. + template + friend bool operator!=(const UsdPrimSiblingRange& lhs, + const ForwardRange& rhs) { + return !(lhs == rhs); + } + + iterator _begin; + iterator _end; +}; // Inform TfIterator it should feel free to make copies of the range type. template <> @@ -2390,9 +2437,6 @@ template <> struct Tf_ShouldIterateOverCopy< const UsdPrimSiblingRange> : std::true_type {}; -#endif // doxygen - - UsdPrimSiblingRange UsdPrim::GetFilteredChildren(const Usd_PrimFlagsPredicate &pred) const { @@ -2427,72 +2471,6 @@ UsdPrim::_MakeSiblingRange(const Usd_PrimFlagsPredicate &pred) const { SiblingIterator(nullptr, SdfPath(), pred)); } -#ifdef doxygen - -/// Forward iterator range of sibling ::UsdPrim s. This range type contains a -/// pair of UsdPrimSubtreeIterator s, denoting a half-open range of UsdPrim -/// siblings. It provides a subset of container-like API, such as begin(), -/// end(), front(), empty(), etc. -class UsdPrimSubtreeRange { -public: - /// Iterator type. - typedef UsdPrimSubtreeIterator iterator; - /// Const iterator type. - typedef UsdPrimSubtreeIterator const_iterator; - /// Iterator difference type. - typedef unspecified-integral-type difference_type; - /// Iterator value_type. - typedef iterator::value_type value_type; - /// Iterator reference_type. - typedef iterator::reference reference; - - /// Construct with a pair of iterators. - UsdPrimSubtreeRange(UsdPrimSubtreeIterator begin, - UsdPrimSubtreeIterator end); - - /// Construct/convert from another compatible range type. - template - UsdPrimSubtreeRange(const ForwardRange &r); - - /// Assign from another compatible range type. - template - UsdPrimSubtreeRange &operator=(const ForwardRange &r); - - /// First iterator. - iterator begin() const; - - /// Past-the-end iterator. - iterator end() const; - - /// Return !empty(). - operator unspecified_bool_type() const; - - /// Equality compare. - bool equal(const iterator_range&) const; - - /// Return *begin(). This range must not be empty. - reference front() const; - - /// Advance this range's begin iterator. - iterator_range& advance_begin(difference_type n); - - /// Advance this range's end iterator. - iterator_range& advance_end(difference_type n); - - /// Return begin() == end(). - bool empty() const; - -private: - /// Equality comparison. - friend bool operator==(const UsdPrimSubtreeRange &lhs, - const UsdPrimSubtreeRange &rhs); - /// Inequality comparison. - friend bool operator!=(const UsdPrimSubtreeRange &lhs, - const UsdPrimSubtreeRange &rhs); -}; - -#else - /// Forward traversal iterator of sibling ::UsdPrim s. This is a /// standard-compliant iterator that may be used with STL algorithms, etc. /// Filters according to a supplied predicate. @@ -2591,8 +2569,125 @@ class UsdPrimSubtreeIterator { Usd_PrimFlagsPredicate _predicate; }; -// Typedef iterator range. -typedef boost::iterator_range UsdPrimSubtreeRange; +/// Forward iterator range of sibling ::UsdPrim s. This range type contains a +/// pair of UsdPrimSubtreeIterator s, denoting a half-open range of UsdPrim +/// siblings. It provides a subset of container-like API, such as begin(), +/// end(), front(), empty(), etc. +class UsdPrimSubtreeRange { +public: + /// Iterator type. + typedef UsdPrimSubtreeIterator iterator; + /// Const iterator type. + typedef UsdPrimSubtreeIterator const_iterator; + /// Iterator difference type. + typedef std::ptrdiff_t difference_type; + /// Iterator value_type. + typedef iterator::value_type value_type; + /// Iterator reference_type. + typedef iterator::reference reference; + + UsdPrimSubtreeRange() = default; + + /// Construct with a pair of iterators. + UsdPrimSubtreeRange(UsdPrimSubtreeIterator begin, + UsdPrimSubtreeIterator end) : _begin(begin), + _end(end) {} + + /// First iterator. + iterator begin() const { return _begin; } + + /// First iterator. + const_iterator cbegin() const { return _begin; } + + /// Past-the-end iterator. + iterator end() const { return _end; } + + /// Past-the-end iterator. + const_iterator cend() const { return _end; } + + /// Return !empty(). + explicit operator bool() const { + return !empty(); + } + + /// Equality compare. + bool equal(const UsdPrimSubtreeRange& other) const { + return _begin == other._begin && _end == other._end; + } + + /// Return *begin(). This range must not be empty. + reference front() const { + TF_DEV_AXIOM(!empty()); + return *begin(); + } + + /// Advance this range's begin iterator. + UsdPrimSubtreeRange& advance_begin(difference_type n) { + std::advance(_begin, n); + return *this; + } + + /// Advance this range's end iterator. + UsdPrimSubtreeRange& advance_end(difference_type n) { + std::advance(_end, n); + return *this; + } + + /// Return begin() == end(). + bool empty() const { return begin() == end(); } + +private: + /// Equality comparison. + friend bool operator==(const UsdPrimSubtreeRange &lhs, + const UsdPrimSubtreeRange &rhs) { + return lhs.equal(rhs); + } + + /// Equality comparison. + template + friend bool operator==(const UsdPrimSubtreeRange& lhs, + const ForwardRange& rhs) { + static_assert( + std::is_convertible< + typename decltype(std::cbegin(rhs))::iterator_category, + std::forward_iterator_tag>::value, + "rhs must be a forward iterator." + ); + return (std::distance(std::cbegin(lhs), std::cend(lhs)) == + std::distance(std::cbegin(rhs), std::cend(rhs))) && + std::equal(std::cbegin(lhs), std::cend(lhs), std::cbegin(rhs)); + } + + /// Equality comparison. + template + friend bool operator==(const ForwardRange& lhs, + const UsdPrimSubtreeRange& rhs) { + return rhs == lhs; + } + + /// Inequality comparison. + friend bool operator!=(const UsdPrimSubtreeRange &lhs, + const UsdPrimSubtreeRange &rhs) { + return !lhs.equal(rhs); + } + + /// Inequality comparison. + template + friend bool operator!=(const ForwardRange& lhs, + const UsdPrimSubtreeRange& rhs) { + return !(lhs == rhs); + } + + /// Inequality comparison. + template + friend bool operator!=(const UsdPrimSubtreeRange& lhs, + const ForwardRange& rhs) { + return !(lhs == rhs); + } + + iterator _begin; + iterator _end; +}; // Inform TfIterator it should feel free to make copies of the range type. template <> @@ -2602,8 +2697,6 @@ template <> struct Tf_ShouldIterateOverCopy< const UsdPrimSubtreeRange> : std::true_type {}; -#endif // doxygen - UsdPrimSubtreeRange UsdPrim::GetFilteredDescendants(const Usd_PrimFlagsPredicate &pred) const { diff --git a/pxr/usd/usd/primData.h b/pxr/usd/usd/primData.h index 3a5165c5fb..4bdba2bf8e 100644 --- a/pxr/usd/usd/primData.h +++ b/pxr/usd/usd/primData.h @@ -40,7 +40,6 @@ #include "pxr/usd/sdf/path.h" -#include #include #include @@ -305,19 +304,11 @@ class Usd_PrimData _flags[Usd_PrimClipsFlag] = hasClips; } - typedef boost::iterator_range< - class Usd_PrimDataSiblingIterator> SiblingRange; - inline class Usd_PrimDataSiblingIterator _ChildrenBegin() const; inline class Usd_PrimDataSiblingIterator _ChildrenEnd() const; - inline SiblingRange _GetChildrenRange() const; - - typedef boost::iterator_range< - class Usd_PrimDataSubtreeIterator> SubtreeRange; inline class Usd_PrimDataSubtreeIterator _SubtreeBegin() const; inline class Usd_PrimDataSubtreeIterator _SubtreeEnd() const; - inline SubtreeRange _GetSubtreeRange() const; // Data members. UsdStage *_stage; @@ -401,18 +392,6 @@ class Usd_PrimDataSiblingIterator { _UnderylingIterator _underlyingIterator = nullptr; }; -// Sibling range. -typedef boost::iterator_range< - class Usd_PrimDataSiblingIterator> Usd_PrimDataSiblingRange; - -// Inform TfIterator it should feel free to make copies of the range type. -template <> -struct Tf_ShouldIterateOverCopy< - Usd_PrimDataSiblingRange> : std::true_type {}; -template <> -struct Tf_ShouldIterateOverCopy< - const Usd_PrimDataSiblingRange> : std::true_type {}; - Usd_PrimDataSiblingIterator Usd_PrimData::_ChildrenBegin() const { @@ -425,13 +404,6 @@ Usd_PrimData::_ChildrenEnd() const return Usd_PrimDataSiblingIterator(0); } -Usd_PrimData::SiblingRange -Usd_PrimData::_GetChildrenRange() const -{ - return Usd_PrimData::SiblingRange(_ChildrenBegin(), _ChildrenEnd()); -} - - // Tree iterator class. class Usd_PrimDataSubtreeIterator { using _UnderlyingIterator = Usd_PrimData*; @@ -485,18 +457,6 @@ class Usd_PrimDataSubtreeIterator { _UnderlyingIterator _underlyingIterator = nullptr; }; -// Tree range. -typedef boost::iterator_range< - class Usd_PrimDataSubtreeIterator> Usd_PrimDataSubtreeRange; - -// Inform TfIterator it should feel free to make copies of the range type. -template <> -struct Tf_ShouldIterateOverCopy< - Usd_PrimDataSubtreeRange> : std::true_type {}; -template <> -struct Tf_ShouldIterateOverCopy< - const Usd_PrimDataSubtreeRange> : std::true_type {}; - Usd_PrimDataSubtreeIterator Usd_PrimData::_SubtreeBegin() const { @@ -510,12 +470,6 @@ Usd_PrimData::_SubtreeEnd() const return Usd_PrimDataSubtreeIterator(GetNextPrim()); } -Usd_PrimData::SubtreeRange -Usd_PrimData::_GetSubtreeRange() const -{ - return Usd_PrimData::SubtreeRange(_SubtreeBegin(), _SubtreeEnd()); -} - // Helpers for instance proxies. // Return true if the prim with prim data \p p and proxy prim path diff --git a/pxr/usd/usd/testenv/testUsdPrimGetDescendants.cpp b/pxr/usd/usd/testenv/testUsdPrimGetDescendants.cpp index 2881f44884..0c44cdda9f 100644 --- a/pxr/usd/usd/testenv/testUsdPrimGetDescendants.cpp +++ b/pxr/usd/usd/testenv/testUsdPrimGetDescendants.cpp @@ -33,6 +33,84 @@ PXR_NAMESPACE_USING_DIRECTIVE +static void +TestRangeEqualityOperators() +{ + const std::string layerFile = "test.usda"; + UsdStageRefPtr stage = UsdStage::Open(layerFile, UsdStage::LoadNone); + TF_AXIOM(stage->GetPseudoRoot().GetAllDescendants()); + TF_AXIOM(!stage->GetPseudoRoot().GetAllDescendants().empty()); + + // Test UsdPrimSubtreeRange equality operator + TF_AXIOM(UsdPrimSubtreeRange() == UsdPrimSubtreeRange()); + TF_AXIOM(stage->GetPseudoRoot().GetAllDescendants() == + stage->GetPseudoRoot().GetAllDescendants()); + + // Test UsdPrimSubtreeRange templated equality operator + TF_AXIOM(UsdPrimSubtreeRange() == std::vector()); + TF_AXIOM(std::vector() == UsdPrimSubtreeRange()); + { + const auto allDescendants = stage->GetPseudoRoot().GetAllDescendants(); + std::vector allPrims( + std::begin(allDescendants), + std::end(allDescendants) + ); + TF_AXIOM(!allPrims.empty()); + TF_AXIOM(stage->GetPseudoRoot().GetAllDescendants() == allPrims); + TF_AXIOM(allPrims == stage->GetPseudoRoot().GetAllDescendants()); + } + + // Test UsdPrimSubtreeRange inequality operator + TF_AXIOM(stage->GetPseudoRoot().GetAllDescendants() != + stage->GetPseudoRoot().GetFilteredDescendants(UsdPrimIsModel)); + + // Test UsdPrimSubtreeRange templated inequality operator + TF_AXIOM(stage->GetPseudoRoot().GetAllDescendants() != + std::vector()); + TF_AXIOM(std::vector() != + stage->GetPseudoRoot().GetAllDescendants()); + { + const auto allDescendants = stage->GetPseudoRoot().GetAllDescendants(); + std::vector allDescendantsPlusOne( + std::begin(allDescendants), + std::end(allDescendants) + ); + allDescendantsPlusOne.push_back(UsdPrim()); + TF_AXIOM(allDescendantsPlusOne.size() > 1); + TF_AXIOM(stage->GetPseudoRoot().GetAllDescendants() != + allDescendantsPlusOne); + TF_AXIOM(allDescendantsPlusOne != + stage->GetPseudoRoot().GetAllDescendants()); + } + { + const auto allDescendants = stage->GetPseudoRoot().GetAllDescendants(); + std::vector allDescendantsMinusOne( + std::begin(allDescendants), + std::end(allDescendants) + ); + TF_AXIOM(!allDescendantsMinusOne.empty()); + allDescendantsMinusOne.pop_back(); + TF_AXIOM(stage->GetPseudoRoot().GetAllDescendants() != + allDescendantsMinusOne); + TF_AXIOM(allDescendantsMinusOne != + stage->GetPseudoRoot().GetAllDescendants()); + } + { + const auto allDescendants = stage->GetPseudoRoot().GetAllDescendants(); + std::vector allDescendantsBackReplaced( + std::begin(allDescendants), + std::end(allDescendants) + ); + TF_AXIOM(!allDescendantsBackReplaced.empty()); + TF_AXIOM(allDescendantsBackReplaced.back() != UsdPrim()); + allDescendantsBackReplaced.back() = UsdPrim(); + TF_AXIOM(stage->GetPseudoRoot().GetAllDescendants() != + allDescendantsBackReplaced); + TF_AXIOM(allDescendantsBackReplaced != + stage->GetPseudoRoot().GetAllDescendants()); + } +} + static void TestGetDescendants() { @@ -249,6 +327,7 @@ TestGetDescendantsAsInstanceProxies() int main(int argc, char** argv) { + TestRangeEqualityOperators(); TestGetDescendants(); TestGetDescendantsAsInstanceProxies();