C++ (Qt)void SetIndex( SomeClass & cnt, int index, int value ){ Data & data = cnt.data(); // поведение QSharedPointer data[index] = value; // поведение implicit sharing}
C++ (Qt)#include <vector>#include <QByteArray> class Action{public: virtual ~Action () {} virtual void undo () = 0; virtual void redo () = 0;}; class Actions{ using OwnAction = ::std::unique_ptr< Action >; using OwnActions = ::std::vector< OwnAction >; OwnActions m_actions; OwnActions::size_type m_cursor = 0; public: static Actions & instance () { static Actions singletone; return singletone; } template < typename _Action, typename ... _Arguments > static void apply ( _Arguments && ... arguments ) { auto & actions = instance().m_actions; auto & cursor = instance().m_cursor; actions.resize( cursor++ ); actions.push_back( ::std::make_unique< _Action >( ::std::forward< _Arguments >( arguments ) ... ) ); actions.back()->redo(); } static bool undo () { auto & actions = instance().m_actions; auto & cursor = instance().m_cursor; if ( actions.empty() || cursor == 0 ) return false; actions[ --cursor ]->undo(); return true; } static bool redo () { auto & actions = instance().m_actions; auto & cursor = instance().m_cursor; if ( cursor >= actions.size() ) return false; actions[ cursor++ ]->redo(); return true; }}; struct SomeClass{ using Data = QByteArray; Data implicit_shared_data;}; class SetIndexAction : public Action{ SomeClass & m_object; // состояния до и после SomeClass::Data m_state_before; SomeClass::Data m_state_after; public: SetIndexAction( SomeClass & cnt, int index, int value ) : m_object( cnt ) , m_state_before( cnt.implicit_shared_data ) { SomeClass::Data & data = cnt.implicit_shared_data; data[ index ] = value; // detach and copy m_state_after = cnt.implicit_shared_data; } void undo () final { m_object.implicit_shared_data = m_state_before; } void redo () final { m_object.implicit_shared_data = m_state_after; }}; void SetIndex ( SomeClass & cnt, int index, int value ){ Actions::apply< SetIndexAction >( cnt, index, value ); // применили действие Actions::undo(); // отменили Actions::redo(); // повторили}
void SetIndex( SomeClass & target, int index, int value ){// получаем локальную копию шареных данных Data data = target.CopyDown();// меняем локальную копию // возможно изменений будет много data[index] = value; // заряжаем измененные данные// если они уже имеются, то шарятся target.CopyUp(data);}