From cfbbf7899ed998bc5571fecd59df3c865e0d04bb Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Mon, 3 Sep 2018 09:31:56 +0200 Subject: [PATCH] implementation and use of callback output iterator --- .../src/core/components/setComponents.hpp | 10 +-- alib2common/test-src/core/ComponentsTest.cpp | 11 +++ alib2std/src/extensions/iterator.hpp | 75 +++++++++++++++++++ alib2std/test-src/extensions/IteratorTest.cpp | 8 ++ alib2std/test-src/extensions/IteratorTest.h | 2 + 5 files changed, 98 insertions(+), 8 deletions(-) diff --git a/alib2common/src/core/components/setComponents.hpp b/alib2common/src/core/components/setComponents.hpp index 8a0d5b0f64..a0e81b6875 100644 --- a/alib2common/src/core/components/setComponents.hpp +++ b/alib2common/src/core/components/setComponents.hpp @@ -149,14 +149,8 @@ public: * CommonException if one of the added elements is not available in context of datatype where the set is used */ void set ( SetComponentType data ) { - SetComponentType removed; - std::set_difference ( m_data.begin ( ), m_data.end ( ), data.begin ( ), data.end ( ), std::inserter ( removed, removed.end ( ) ) ); - - for ( const ComponentType & element : removed ) - checkRemove ( element ); - - for ( const ComponentType & element : data ) - checkAdd ( element ); + std::set_difference ( m_data.begin ( ), m_data.end ( ), data.begin ( ), data.end ( ), ext::make_callback_iterator < const ComponentType & > ( std::bind ( & SetComponent::checkRemove, this, std::placeholders::_1 ) ) ); + std::set_difference ( data.begin ( ), data.end ( ), m_data.begin ( ), m_data.end ( ), ext::make_callback_iterator < const ComponentType & > ( std::bind ( & SetComponent::checkAdd, this, std::placeholders::_1 ) ) ); m_data = std::move ( data ); } diff --git a/alib2common/test-src/core/ComponentsTest.cpp b/alib2common/test-src/core/ComponentsTest.cpp index 661918b1a9..cadcbe0ac7 100644 --- a/alib2common/test-src/core/ComponentsTest.cpp +++ b/alib2common/test-src/core/ComponentsTest.cpp @@ -130,6 +130,17 @@ void ComponentsTest::testRemove ( ) { tmp.accessComponent < GeneralAlphabet > ( ).add ( "1" ); tmp.accessComponent < NonlinearAlphabet > ( ).add ( "1" ); CPPUNIT_ASSERT_THROW ( tmp.accessComponent < GeneralAlphabet > ( ).remove ( "1" ), exception::CommonException ); + CPPUNIT_ASSERT_THROW ( tmp.accessComponent < GeneralAlphabet > ( ).remove ( ext::linear_set < std::string > { "1" } ), exception::CommonException ); + CPPUNIT_ASSERT_NO_THROW ( tmp.accessComponent < GeneralAlphabet > ( ).set ( ext::linear_set < std::string > { "1", "2", "aaa", "3" } ) ); + CPPUNIT_ASSERT_THROW ( tmp.accessComponent < GeneralAlphabet > ( ).set ( ext::linear_set < std::string > { } ), exception::CommonException ); + + CPPUNIT_ASSERT ( tmp.accessComponent < GeneralAlphabet > ( ).get ( ).size ( ) == 4 ); + + CPPUNIT_ASSERT_NO_THROW ( tmp.accessComponent < NonlinearAlphabet > ( ).set ( ext::linear_set < std::string > { "1", "3" } ) ); + CPPUNIT_ASSERT_THROW ( tmp.accessComponent < NonlinearAlphabet > ( ).set ( ext::linear_set < std::string > { "1", "4" } ), exception::CommonException ); + tmp.accessComponent < NonlinearAlphabet > ( ).remove ( "1" ); tmp.accessComponent < GeneralAlphabet > ( ).remove ( "1" ); + + } diff --git a/alib2std/src/extensions/iterator.hpp b/alib2std/src/extensions/iterator.hpp index 9c4cf7c8da..cee8d5a4fd 100644 --- a/alib2std/src/extensions/iterator.hpp +++ b/alib2std/src/extensions/iterator.hpp @@ -25,6 +25,7 @@ #define __ITERATOR_HPP_ #include <iterator> +#include <functional> namespace ext { @@ -1025,6 +1026,80 @@ constexpr T * end ( T ( & arr ) [ N ] ) noexcept { return arr + N; } +/** + * \brief + * Output iterator calling a callback function on assignment + * + * \tparam the type of value accepted by the callback. The type must include the reference and cv-qualification if needed. + */ +template < class T > +class callback_iterator : public std::iterator < std::output_iterator_tag, void, void, void, void > { + /** + * The callback. + */ + std::function < void ( T ) > m_callback; + +public: + /** + * Constructor of the callback iterator based on callback + * + * \param callback the function to call on asignment + */ + explicit callback_iterator ( std::function < void ( T ) > callback ) : m_callback ( callback ) { + } + + /** + * Asignment operator calling the calback with the accepted parameter. + * + * \param value the value to pass to the callback + * + * \return reference to this iterator + */ + callback_iterator & operator = ( T value ) { + m_callback ( std::forward < T > ( value ) ); + return * this; + } + + /** + * Typical implementation of output iterator dereference operator producing itself. + * + * \return reference to this output iterator + */ + callback_iterator &operator * ( ) { + return * this; + } + + /** + * Increment operator implementation as no operation. + * + * \return reference to this output iterator + */ + callback_iterator &operator ++ ( ) { + return * this; + } + + /** + * Increment operator implementation as no operation. + * + * \return reference to this output iterator + */ + callback_iterator operator ++ ( int ) { + return * this; + } +}; + +/** + * Function to create callback iterator from the callback. + * + * \param T the type of value accepted by the callback. + * + * \return the callback iterator + */ +template < class T > +callback_iterator < T > make_callback_iterator ( const std::function < void ( T ) > & callback ) { + return callback_iterator < T > ( callback ); +} + } /* namespace ext */ #endif /* __ITERATOR_HPP_ */ diff --git a/alib2std/test-src/extensions/IteratorTest.cpp b/alib2std/test-src/extensions/IteratorTest.cpp index ac11e103d2..12b0636704 100644 --- a/alib2std/test-src/extensions/IteratorTest.cpp +++ b/alib2std/test-src/extensions/IteratorTest.cpp @@ -69,3 +69,11 @@ void IteratorTest::testReverser() { CPPUNIT_ASSERT ( data2 == trans ); } + +void IteratorTest::testCallbackIterator ( ) { + int expected; + ext::callback_iterator < int > out = ext::make_callback_iterator < int > ( [ & ] ( int value ) -> void { CPPUNIT_ASSERT ( value == expected ); } ); + + expected = 10; + * out = 10; +} diff --git a/alib2std/test-src/extensions/IteratorTest.h b/alib2std/test-src/extensions/IteratorTest.h index 1cff4cd97e..93d4bc4947 100644 --- a/alib2std/test-src/extensions/IteratorTest.h +++ b/alib2std/test-src/extensions/IteratorTest.h @@ -8,6 +8,7 @@ class IteratorTest : public CppUnit::TestFixture CPPUNIT_TEST_SUITE( IteratorTest ); CPPUNIT_TEST( testIterator ); CPPUNIT_TEST( testReverser ); + CPPUNIT_TEST( testCallbackIterator ); CPPUNIT_TEST_SUITE_END(); public: @@ -16,6 +17,7 @@ public: void testIterator(); void testReverser(); + void testCallbackIterator(); }; #endif // ITERATOR_TEST_H_ -- GitLab