C++ (Qt)#include <memory> class AbstractHolder{public: using SharedAbstractHolder = std::shared_ptr< AbstractHolder >; public: virtual ~AbstractHolder () {} virtual SharedAbstractHolder clone () const = 0;}; template < typename _Type >class Holder : public AbstractHolder{ using ThisType = Holder< _Type >; using ParentType = AbstractHolder; public: using ValueType = _Type; private: ValueType m_value; public: template < typename ... _Arguments > Holder ( _Arguments && ... args ) : m_value( std::forward< _Arguments >( args ) ... ) { } const _Type & readable () const { return m_value; } _Type & writable () { return m_value; } virtual SharedAbstractHolder clone () const { return std::make_shared< ThisType >( m_value ); }}; template < typename _Type >class ImplicitWrapper{private: using ThisType = ImplicitWrapper< _Type >; using HolderType = Holder< _Type >; using SharedHolder = std::shared_ptr< AbstractHolder >; using SharedAbstractHolder = std::shared_ptr< AbstractHolder >; template < typename _OtherType > friend class ImplicitWrapper; private: SharedHolder m_shared_holder; private: ImplicitWrapper ( const SharedHolder & holder ) : m_shared_holder( holder ) { } void detach () { if ( m_shared_holder.use_count() > 1 ) m_shared_holder = m_shared_holder->clone(); } public: ImplicitWrapper () : m_shared_holder() { } template < typename _OtherType > ImplicitWrapper ( const ImplicitWrapper< _OtherType > & other ) : m_shared_holder( other.m_shared_holder ) { static_assert( std::is_base_of< _Type, _OtherType >::value, "The types are not compatibile." ); } bool isNull () const { return !m_shared_holder; } const _Type & readable () const { return std::static_pointer_cast< HolderType >( m_shared_holder )->readable(); } _Type & writable () { detach(); return std::static_pointer_cast< HolderType >( m_shared_holder )->writable(); } public: template < typename ... _Arguments > static ThisType make ( _Arguments && ... args ) { return ThisType( std::make_shared< Holder< _Type > >( std::forward< _Arguments >( args ) ... ) ); }}; #include <iostream> struct Test{ Test () { std::cout << "Constructor of Test" << std::endl; } Test ( const Test & ) { std::cout << "Copy of Test" << std::endl; } Test ( Test && ) { std::cout << "Move of Test" << std::endl; } virtual ~Test () { std::cout << "Destructor of Test" << std::endl; } virtual void method () { std::cout << "Mutable method of Test" << std::endl; } virtual void method () const { std::cout << "Constant method of Test" << std::endl; }}; struct DerivedTest : public Test{ DerivedTest () { std::cout << "Constructor of DerivedTest" << std::endl; } DerivedTest ( const DerivedTest & other ) : Test( other ) { std::cout << "Copy of DerivedTest" << std::endl; } DerivedTest ( DerivedTest && other ) : Test( std::forward< Test >( other ) ) { std::cout << "Move of DerivedTest" << std::endl; } virtual ~DerivedTest () { std::cout << "Destructor of DerivedTest" << std::endl; } virtual void method () { std::cout << "Mutable method of DerivedTest" << std::endl; } virtual void method () const { std::cout << "Constant method of DerivedTest" << std::endl; }}; struct OtherTest{ OtherTest () { std::cout << "Constructor of OtherTest" << std::endl; } ~OtherTest () { std::cout << "Destructor of OtherTest" << std::endl; } void method () { std::cout << "Mutable method of OtherTest" << std::endl; } void method () const { std::cout << "Constant method of OtherTest" << std::endl; }}; int main ( int, char ** ){ // OK { ImplicitWrapper< Test > test_value = ImplicitWrapper< Test >::make(); test_value.readable().method(); test_value.writable().method(); } // OK { ImplicitWrapper< Test > test_value = ImplicitWrapper< DerivedTest >::make(); test_value.readable().method(); test_value.writable().method(); } // ERROR// {// ImplicitWrapper< Test > test_value = ImplicitWrapper< OtherTest >::make();// test_value.readable().method();// test_value.writable().method();// } // OK { ImplicitWrapper< DerivedTest > first_value = ImplicitWrapper< DerivedTest >::make(); ImplicitWrapper< Test > second_value = first_value; second_value.readable().method(); // not detached second_value.writable().method(); // detached } // OK { ImplicitWrapper< Test > second_value = ImplicitWrapper< DerivedTest >::make( DerivedTest() ); second_value.readable().method(); second_value.writable().method(); } return 0;}
C++ (Qt)template<class T>class MyPtr{ T *d; MyPtr(const MyPtr &other) : d(other.d->clone()) {}};
C++ (Qt)ImplicitWrapper< Test > mutable_value = ImplicitWrapper< Test >::make();mutable_value->method(); // всегда mutable метод ImplicitWrapper< const Test > const_value = mutable_value;const_value->method(); // всегда cosnt
C++ (Qt)// value не предоставляет доступ к TestImplicitWrapper< Test > value = ImplicitWrapper< Test >::make(); WriteAccessor< Test > writer( value );writer->method(); // всегда mutable методwriter.value().method(); // всегда mutable метод ReadAccessor< Test > reader( value );reader->method(); // всегда const методreader.value().method(); // всегда const метод
C++ (Qt)// value не предоставляет доступ к TestImplicitWrapper< Test > value = ImplicitWrapper< Test >::make(); writable( value ).method(); // всегда mutable методreadable( value ).method(); // всегда const метод
C++ (Qt)ImplicitWrapper< Test > value = ImplicitWrapper< Test >::make(); value.writable().method(); // всегда mutable методvalue.readable().method(); // всегда const метод
C++ (Qt)#include <memory>#include <QSharedPointer> class AbstractHolder{public: typedef QSharedPointer< AbstractHolder > SharedAbstractHolder; public: virtual ~AbstractHolder () {} virtual SharedAbstractHolder clone () const = 0;}; template < typename _Type >QSharedPointer< _Type > makeShared(){ return QSharedPointer< _Type >( new _Type );} template < typename _Type, typename _Arg0 >QSharedPointer< _Type > makeShared( const _Arg0 & arg0 ){ return QSharedPointer< _Type >( new _Type( arg0 ) );} // etc ... _Arg1, _Arg2 ... template < typename _Type >class Holder : public AbstractHolder{ typedef Holder< _Type > ThisType; typedef AbstractHolder ParentType; public: typedef _Type ValueType; private: ValueType m_value; public: Holder () : m_value() { } template < typename _Arg0 > Holder ( const _Arg0 & arg0 ) : m_value( arg0 ) { } // etc ... _Arg1, _Arg2 ... const _Type & readable () const { return m_value; } _Type & writable () { return m_value; } virtual SharedAbstractHolder clone () const { return makeShared< ThisType >( m_value ); }}; template < typename _Type >class ImplicitWrapper{private: typedef ImplicitWrapper< _Type > ThisType; typedef Holder< _Type > HolderType; typedef QSharedPointer< AbstractHolder > SharedAbstractHolder; template < typename _OtherType > friend class ImplicitWrapper; private: SharedAbstractHolder m_shared_holder; private: ImplicitWrapper ( const SharedAbstractHolder & holder ) : m_shared_holder( holder ) { } void detach () { // Hack!!! Qt4 protected, Qt5 private struct HackValue { struct Data { QBasicAtomicInt weakref; QBasicAtomicInt strongref; }; AbstractHolder * m_type; Data * m_data; }; HackValue * hack = reinterpret_cast< HackValue * >( &m_shared_holder ); if ( hack->m_data->strongref > 1 ) m_shared_holder = m_shared_holder->clone(); } public: ImplicitWrapper () : m_shared_holder() { } template < typename _OtherType > ImplicitWrapper ( const ImplicitWrapper< _OtherType > & other ) : m_shared_holder( other.m_shared_holder ) { Q_ASSERT( !other.m_shared_holder || static_cast< _Type * >( const_cast< _OtherType * >( &other.readable() ) ) ); } bool isNull () const { return !m_shared_holder; } const _Type & readable () const { return m_shared_holder.staticCast< HolderType >()->readable(); } _Type & writable () { detach(); return m_shared_holder.staticCast< HolderType >()->writable(); } public: static ThisType make () { return ThisType( makeShared< Holder< _Type > >() ); } template < typename _Arg0 > static ThisType make ( const _Arg0 & arg0 ) { return ThisType( makeShared< Holder< _Type > >( arg0 ) ); } // etc ... _Arg1, _Arg2 ...}; #include <iostream> struct Test{ Test () { std::cout << "Constructor of Test" << std::endl; } Test ( const Test & ) { std::cout << "Copy of Test" << std::endl; } virtual ~Test () { std::cout << "Destructor of Test" << std::endl; } virtual void method () { std::cout << "Mutable method of Test" << std::endl; } virtual void method () const { std::cout << "Constant method of Test" << std::endl; }}; struct DerivedTest : public Test{ DerivedTest () { std::cout << "Constructor of DerivedTest" << std::endl; } DerivedTest ( const DerivedTest & other ) : Test( other ) { std::cout << "Copy of DerivedTest" << std::endl; } virtual ~DerivedTest () { std::cout << "Destructor of DerivedTest" << std::endl; } virtual void method () { std::cout << "Mutable method of DerivedTest" << std::endl; } virtual void method () const { std::cout << "Constant method of DerivedTest" << std::endl; }}; struct OtherTest{ OtherTest () { std::cout << "Constructor of OtherTest" << std::endl; } ~OtherTest () { std::cout << "Destructor of OtherTest" << std::endl; } void method () { std::cout << "Mutable method of OtherTest" << std::endl; } void method () const { std::cout << "Constant method of OtherTest" << std::endl; }}; int main ( int, char ** ){ int test_number = 0; // OK { std::cout << "Test - " << (test_number++) << std::endl; ImplicitWrapper< Test > test_value = ImplicitWrapper< Test >::make(); test_value.readable().method(); test_value.writable().method(); } // OK { std::cout << "Test - " << (test_number++) << std::endl; ImplicitWrapper< Test > test_value = ImplicitWrapper< DerivedTest >::make(); test_value.readable().method(); test_value.writable().method(); } // OK { std::cout << "Test - " << (test_number++) << std::endl; ImplicitWrapper< const Test > test_value = ImplicitWrapper< DerivedTest >::make(); test_value.readable().method(); test_value.writable().method(); } // ERROR// {// std::cout << "Test - " << (test_number++) << std::endl;// ImplicitWrapper< Test > test_value = ImplicitWrapper< OtherTest >::make();// test_value.readable().method();// test_value.writable().method();// } // OK { std::cout << "Test - " << (test_number++) << std::endl; ImplicitWrapper< DerivedTest > first_value = ImplicitWrapper< DerivedTest >::make(); ImplicitWrapper< Test > second_value = first_value; second_value.readable().method(); // not detached second_value.writable().method(); // detached } // OK { std::cout << "Test - " << (test_number++) << std::endl; ImplicitWrapper< Test > second_value = ImplicitWrapper< DerivedTest >::make( DerivedTest() ); second_value.readable().method(); second_value.writable().method(); } return 0;}
QVector<int> vec;...int test = vec[0]; // detach (хотя никакой необходимости не было)