1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_O3TL_LAZY_UPDATE_HXX
21 #define INCLUDED_O3TL_LAZY_UPDATE_HXX
23 #include <sal/types.h>
24 #include <boost/function.hpp>
28 /** Update output object lazily
30 This template collects data in input type, and updates the
31 output type with the given update functor, but only if the
32 output is requested. UsefĂșl if updating is expensive, or input
33 changes frequently, but output is only comparatively seldom
38 LazyUpdate<InType,OutType,LAZYUPDATE_DIRECT_TAG> myValue;
40 myValue->updateInput( this, that, those );
46 output( myValue.getOutValue() );
48 if the compiler does not recognize the const context.
50 template< typename InputType
, typename OutputType
, typename Tag
> class LazyUpdate
;
52 /// LazyUpdate specialization takes boost::function argument
53 struct LAZYUPDATE_FUNCTOR_TAG
{};
54 /// LazyUpdate specialization takes OutputType (*FunctionType)( InputType const& ) argument
55 struct LAZYUPDATE_FUNCTION_TAG
{};
56 /// LazyUpdate specialization can directly convert, OutputType ctor must take InputType argument
57 struct LAZYUPDATE_DIRECT_TAG
{};
59 // -----------------------------------------------------------------------------------------------------
64 template< typename InputType
, typename OutputType
, typename Functor
> class LazyUpdateImpl
: private Functor
67 typedef OutputType output_type
;
68 typedef InputType input_type
;
74 template< typename ParamType
> explicit LazyUpdateImpl( ParamType
const& rParm
) :
79 enum UnaryConstructorTag
{ UNARY_CONSTRUCTOR_TAG
};
80 LazyUpdateImpl( const input_type
& rInput
, UnaryConstructorTag
) :
84 template< typename ParamType
> LazyUpdateImpl( ParamType
const& rParm
,
85 const input_type
& rInput
) :
90 // default copy ctor/assignment operator are ok
91 // LazyUpdate( const LazyUpdate& );
92 // LazyUpdate& operator=( const LazyUpdate& );
94 void setInValue( input_type
const& rIn
) { Functor::m_bCacheDirty
= true; m_aInput
= rIn
; }
95 input_type
const& getInValue() const { return m_aInput
; }
96 output_type
const& getOutValue() const { return this->implUpdateValue(m_aInput
); }
98 input_type
& operator*() { Functor::m_bCacheDirty
= true; return m_aInput
; }
99 input_type
* operator->() { Functor::m_bCacheDirty
= true; return &m_aInput
; }
101 output_type
const& operator*() const { return this->implUpdateValue(m_aInput
); }
102 output_type
const* operator->() const { return &(this->implUpdateValue(m_aInput
)); }
108 template< typename InputType
, typename OutputType
> struct DefaultFunctor
111 typedef OutputType output_type
;
112 typedef InputType input_type
;
119 OutputType
const& implUpdateValue( input_type
const& rIn
) const
123 m_aOutput
= output_type( rIn
);
124 m_bCacheDirty
= false;
130 mutable output_type m_aOutput
;
131 mutable bool m_bCacheDirty
; // when true, m_aOutput needs update
134 template< typename InputType
, typename OutputType
, typename FunctionType
> struct FunctionPointer
137 typedef OutputType output_type
;
138 typedef InputType input_type
;
139 typedef FunctionType function_type
;
148 explicit FunctionPointer( function_type
const& pFunc
) :
155 output_type
const& implUpdateValue( input_type
const& rIn
) const
159 m_aOutput
= m_pFunc( rIn
);
160 m_bCacheDirty
= false;
166 function_type m_pFunc
;
167 mutable output_type m_aOutput
;
168 mutable bool m_bCacheDirty
; // when true, m_aOutput needs update
172 // -----------------------------------------------------------------------------------------------------
174 // partial specializations for the three LAZYUPDATE_* tags
176 template< typename InputType
, typename OutputType
> class LazyUpdate
<InputType
,
178 LAZYUPDATE_DIRECT_TAG
> :
179 public detail::LazyUpdateImpl
<InputType
,
181 detail::DefaultFunctor
<InputType
, OutputType
> >
185 explicit LazyUpdate( InputType
const& rIn
) :
186 detail::LazyUpdateImpl
<InputType
,
188 detail::DefaultFunctor
<InputType
, OutputType
> >(
190 detail::LazyUpdateImpl
<
193 detail::DefaultFunctor
<InputType
, OutputType
> >::UNARY_CONSTRUCTOR_TAG
)
197 // -----------------------------------------------------------------------------------------------------
199 template< typename InputType
, typename OutputType
> class LazyUpdate
<InputType
,
201 LAZYUPDATE_FUNCTION_TAG
> :
202 public detail::LazyUpdateImpl
<InputType
,
204 detail::FunctionPointer
<
207 OutputType (*)( InputType
const& ) > >
210 explicit LazyUpdate( OutputType (*pFunc
)( InputType
const& ) ) :
211 detail::LazyUpdateImpl
<InputType
,
213 detail::FunctionPointer
<
216 OutputType (*)( InputType
const& )> >(pFunc
)
218 LazyUpdate( OutputType (*pFunc
)( InputType
const& ),
219 InputType
const& rIn
) :
220 detail::LazyUpdateImpl
<InputType
,
222 detail::FunctionPointer
<
225 OutputType (*)( InputType
const& )> >(pFunc
,rIn
)
229 // -----------------------------------------------------------------------------------------------------
231 template< typename InputType
, typename OutputType
> class LazyUpdate
<InputType
,
233 LAZYUPDATE_FUNCTOR_TAG
> :
234 public detail::LazyUpdateImpl
<InputType
,
236 detail::FunctionPointer
<
239 boost::function1
<OutputType
,InputType
> > >
242 explicit LazyUpdate( boost::function1
<OutputType
,InputType
> const& rFunc
) :
243 detail::LazyUpdateImpl
<InputType
,
245 detail::FunctionPointer
<
248 boost::function1
<OutputType
,InputType
> > >(rFunc
)
250 LazyUpdate( boost::function1
<OutputType
,InputType
> const& rFunc
,
251 InputType
const& rIn
) :
252 detail::LazyUpdateImpl
<InputType
,
254 detail::FunctionPointer
<
257 boost::function1
<OutputType
,InputType
> > >(rFunc
,rIn
)
263 #endif /* INCLUDED_O3TL_LAZY_UPDATE_HXX */
265 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */