From a4a2a9eda4a8ddf9d13b8ee5a6ee1a8c3c63ffba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Wed, 2 Jan 2019 17:52:56 +0100 Subject: [PATCH] Reference-counting helpers - Equality operators * Added == and != operators; they can only be used if the referenced types are from the same hierarchy * Tests for the above --- include/ebcl/RefCount.hh | 13 ++++ include/ebcl/inline/RefCount.hh | 24 ++++++ tests/ref-count.cc | 130 ++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+) diff --git a/include/ebcl/RefCount.hh b/include/ebcl/RefCount.hh index d82d14f..32c50d2 100644 --- a/include/ebcl/RefCount.hh +++ b/include/ebcl/RefCount.hh @@ -159,6 +159,19 @@ class T_RcPtr // Access the object; undefined behavior if get() == nullptr. Type* operator -> ( ) const; Type& operator * ( ) const; + + // --------------------------------------------------------------------- + // Comparison operators + + template< + typename Q , + T_EnableForHierarchy< Type , Q > = true + > bool operator== ( T_RcPtr< Q > const& p ) const noexcept; + + template< + typename Q , + T_EnableForHierarchy< Type , Q > = true + > bool operator!= ( T_RcPtr< Q > const& p ) const noexcept; }; template< typename T > diff --git a/include/ebcl/inline/RefCount.hh b/include/ebcl/inline/RefCount.hh index e23feca..9b766d0 100644 --- a/include/ebcl/inline/RefCount.hh +++ b/include/ebcl/inline/RefCount.hh @@ -295,6 +295,30 @@ inline T& T_RcPtr< T >::operator * ( ) const return *target_; } +/*----------------------------------------------------------------------------*/ + +template< typename T > +template< + typename Q , + T_EnableForHierarchy< T , Q > +> inline bool T_RcPtr< T >::operator== ( + T_RcPtr< Q > const& p ) const noexcept +{ + return (char const*) this == (char const*) &p + || (char const*) p.target_ == (char const*) target_; +} + +template< typename T > +template< + typename Q , + T_EnableForHierarchy< T , Q > +> inline bool T_RcPtr< T >::operator!= ( + T_RcPtr< Q > const& p ) const noexcept +{ + return (char const*) this != (char const*) &p + && (char const*) p.target_ != (char const*) target_; +} + } // namespace ebcl #endif // _H_EBCL_INLINE_REFCOUNT diff --git a/tests/ref-count.cc b/tests/ref-count.cc index 41ab6a4..f96b0d5 100644 --- a/tests/ref-count.cc +++ b/tests/ref-count.cc @@ -47,6 +47,12 @@ class RefCountTest : public CppUnit::TestFixture CPPUNIT_TEST( testMoveAssToChildBad ); CPPUNIT_TEST( testSwap ); + + CPPUNIT_TEST( testEq ); + CPPUNIT_TEST( testEqChild ); + + CPPUNIT_TEST( testNEq ); + CPPUNIT_TEST( testNEqChild ); CPPUNIT_TEST_SUITE_END( ); public: @@ -78,6 +84,12 @@ class RefCountTest : public CppUnit::TestFixture void testMoveAssToChildBad( ); void testSwap( ); + + void testEq( ); + void testEqChild( ); + + void testNEq( ); + void testNEqChild( ); }; CPPUNIT_TEST_SUITE_REGISTRATION( RefCountTest< true > ); CPPUNIT_TEST_SUITE_REGISTRATION( RefCountTest< false > ); @@ -372,3 +384,121 @@ void RefCountTest< A >::testSwap( ) } CPPUNIT_ASSERT_EQUAL( 1u , T_Test::cDel ); } + +/*----------------------------------------------------------------------------*/ + +template< bool A > +void RefCountTest< A >::testEq( ) +{ + P_Test p1{ P_Test::New( ) }, + p2{ p1 } , + p3{ P_Test::New( ) }, + p4; + + CPPUNIT_ASSERT( ( p1 == p1 ) ); + CPPUNIT_ASSERT( ( p1 == p2 ) ); + CPPUNIT_ASSERT( !( p1 == p3 ) ); + CPPUNIT_ASSERT( !( p1 == p4 ) ); + + CPPUNIT_ASSERT( ( p2 == p1 ) ); + CPPUNIT_ASSERT( ( p2 == p2 ) ); + CPPUNIT_ASSERT( !( p2 == p3 ) ); + CPPUNIT_ASSERT( !( p2 == p4 ) ); + + CPPUNIT_ASSERT( !( p3 == p1 ) ); + CPPUNIT_ASSERT( !( p3 == p2 ) ); + CPPUNIT_ASSERT( ( p3 == p3 ) ); + CPPUNIT_ASSERT( !( p3 == p4 ) ); + + CPPUNIT_ASSERT( !( p4 == p1 ) ); + CPPUNIT_ASSERT( !( p4 == p2 ) ); + CPPUNIT_ASSERT( !( p4 == p3 ) ); + CPPUNIT_ASSERT( ( p4 == p4 ) ); +} + +template< bool A > +void RefCountTest< A >::testEqChild( ) +{ + P_Child p1{ P_Child::New( ) } , + p2{ P_Child::New( ) }; + P_Test p3{ p1 } , p4{ p2 }; + + CPPUNIT_ASSERT( ( p1 == p1 ) ); + CPPUNIT_ASSERT( !( p1 == p2 ) ); + CPPUNIT_ASSERT( ( p1 == p3 ) ); + CPPUNIT_ASSERT( !( p1 == p4 ) ); + + CPPUNIT_ASSERT( !( p2 == p1 ) ); + CPPUNIT_ASSERT( ( p2 == p2 ) ); + CPPUNIT_ASSERT( !( p2 == p3 ) ); + CPPUNIT_ASSERT( ( p2 == p4 ) ); + + CPPUNIT_ASSERT( ( p3 == p1 ) ); + CPPUNIT_ASSERT( !( p3 == p2 ) ); + CPPUNIT_ASSERT( ( p3 == p3 ) ); + CPPUNIT_ASSERT( !( p3 == p4 ) ); + + CPPUNIT_ASSERT( !( p4 == p1 ) ); + CPPUNIT_ASSERT( ( p4 == p2 ) ); + CPPUNIT_ASSERT( !( p4 == p3 ) ); + CPPUNIT_ASSERT( ( p4 == p4 ) ); +} + +/*----------------------------------------------------------------------------*/ + +template< bool A > +void RefCountTest< A >::testNEq( ) +{ + P_Test p1{ P_Test::New( ) }, + p2{ p1 } , + p3{ P_Test::New( ) }, + p4; + + CPPUNIT_ASSERT( !( p1 != p1 ) ); + CPPUNIT_ASSERT( !( p1 != p2 ) ); + CPPUNIT_ASSERT( ( p1 != p3 ) ); + CPPUNIT_ASSERT( ( p1 != p4 ) ); + + CPPUNIT_ASSERT( !( p2 != p1 ) ); + CPPUNIT_ASSERT( !( p2 != p2 ) ); + CPPUNIT_ASSERT( ( p2 != p3 ) ); + CPPUNIT_ASSERT( ( p2 != p4 ) ); + + CPPUNIT_ASSERT( ( p3 != p1 ) ); + CPPUNIT_ASSERT( ( p3 != p2 ) ); + CPPUNIT_ASSERT( !( p3 != p3 ) ); + CPPUNIT_ASSERT( ( p3 != p4 ) ); + + CPPUNIT_ASSERT( ( p4 != p1 ) ); + CPPUNIT_ASSERT( ( p4 != p2 ) ); + CPPUNIT_ASSERT( ( p4 != p3 ) ); + CPPUNIT_ASSERT( !( p4 != p4 ) ); +} + +template< bool A > +void RefCountTest< A >::testNEqChild( ) +{ + P_Child p1{ P_Child::New( ) } , + p2{ P_Child::New( ) }; + P_Test p3{ p1 } , p4{ p2 }; + + CPPUNIT_ASSERT( !( p1 != p1 ) ); + CPPUNIT_ASSERT( ( p1 != p2 ) ); + CPPUNIT_ASSERT( !( p1 != p3 ) ); + CPPUNIT_ASSERT( ( p1 != p4 ) ); + + CPPUNIT_ASSERT( ( p2 != p1 ) ); + CPPUNIT_ASSERT( !( p2 != p2 ) ); + CPPUNIT_ASSERT( ( p2 != p3 ) ); + CPPUNIT_ASSERT( !( p2 != p4 ) ); + + CPPUNIT_ASSERT( !( p3 != p1 ) ); + CPPUNIT_ASSERT( ( p3 != p2 ) ); + CPPUNIT_ASSERT( !( p3 != p3 ) ); + CPPUNIT_ASSERT( ( p3 != p4 ) ); + + CPPUNIT_ASSERT( ( p4 != p1 ) ); + CPPUNIT_ASSERT( !( p4 != p2 ) ); + CPPUNIT_ASSERT( ( p4 != p3 ) ); + CPPUNIT_ASSERT( !( p4 != p4 ) ); +}