From b80c937dc6b8d3a6a511f5fc82b0ab7e2172c9d1 Mon Sep 17 00:00:00 2001 From: Jens-Heiner Rechtien
+LazyUpdate+ or +myValue; +*myValue = newInput; +myValue->updateInput( this, that, those ); + +output( *myValue ); +
+output( myValue.getOutValue() ); ++ if the compiler does not recognize the const context. + */ + template< typename InputType, typename OutputType, typename Tag > class LazyUpdate; + + /// LazyUpdate specialization takes boost::function argument + struct LAZYUPDATE_FUNCTOR_TAG {}; + /// LazyUpdate specialization takes OutputType (*FunctionType)( InputType const& ) argument + struct LAZYUPDATE_FUNCTION_TAG {}; + /// LazyUpdate specialization can directly convert, OutputType ctor must take InputType argument + struct LAZYUPDATE_DIRECT_TAG {}; + + // ----------------------------------------------------------------------------------------------------- + + namespace detail + { + /// @internal + template< typename InputType, typename OutputType, typename Functor > class LazyUpdateImpl : private Functor + { + public: + typedef OutputType output_type; + typedef InputType input_type; + + LazyUpdateImpl() : + m_aInput() + {} + + template< typename ParamType > explicit LazyUpdateImpl( ParamType const& rParm ) : + Functor(rParm), + m_aInput() + {} + + enum UnaryConstructorTag{ UNARY_CONSTRUCTOR_TAG }; + LazyUpdateImpl( const input_type& rInput, UnaryConstructorTag ) : + m_aInput(rInput) + {} + + template< typename ParamType > LazyUpdateImpl( ParamType const& rParm, + const input_type& rInput ) : + Functor(rParm), + m_aInput(rInput) + {} + + // default copy ctor/assignment operator are ok + // LazyUpdate( const LazyUpdate& ); + // LazyUpdate& operator=( const LazyUpdate& ); + + void setInValue( input_type const& rIn ) { Functor::m_bCacheDirty = true; m_aInput = rIn; } + input_type const& getInValue() const { return m_aInput; } + output_type const& getOutValue() const { return implUpdateValue(m_aInput); } + + input_type& operator*() { Functor::m_bCacheDirty = true; return m_aInput; } + input_type* operator->() { Functor::m_bCacheDirty = true; return &m_aInput; } + + output_type const& operator*() const { return implUpdateValue(m_aInput); } + output_type const* operator->() const { return &implUpdateValue(m_aInput); } + + private: + input_type m_aInput; + }; + + template< typename InputType, typename OutputType > struct DefaultFunctor + { + protected: + typedef OutputType output_type; + typedef InputType input_type; + + DefaultFunctor() : + m_aOutput(), + m_bCacheDirty(true) + {} + + OutputType const& implUpdateValue( input_type const& rIn ) const + { + if( m_bCacheDirty ) + { + m_aOutput = output_type( rIn ); + m_bCacheDirty = false; + } + + return m_aOutput; + } + + mutable output_type m_aOutput; + mutable bool m_bCacheDirty; // when true, m_aOutput needs update + }; + + template< typename InputType, typename OutputType, typename FunctionType > struct FunctionPointer + { + protected: + typedef OutputType output_type; + typedef InputType input_type; + typedef FunctionType function_type; + + FunctionPointer() : + m_pFunc(), + m_aOutput(), + m_bCacheDirty(true) + + {} + + explicit FunctionPointer( function_type const& pFunc ) : + m_pFunc(pFunc), + m_aOutput(), + m_bCacheDirty(true) + + {} + + output_type const& implUpdateValue( input_type const& rIn ) const + { + if( m_bCacheDirty ) + { + m_aOutput = m_pFunc( rIn ); + m_bCacheDirty = false; + } + + return m_aOutput; + } + + function_type m_pFunc; + mutable output_type m_aOutput; + mutable bool m_bCacheDirty; // when true, m_aOutput needs update + }; + } + + // ----------------------------------------------------------------------------------------------------- + + // partial specializations for the three LAZYUPDATE_* tags + + template< typename InputType, typename OutputType > class LazyUpdate