Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

experimental.hpp

Go to the documentation of this file.
00001 #ifndef s11n_EXPERIMENTAL_HPP_INCLUDED
00002 #define s11n_EXPERIMENTAL_HPP_INCLUDED 1
00003 // Experimental code for s11n, with an emphasis on the "mental" part.
00004 // None of this code is intended for use by clients.
00005 namespace s11n {
00006 
00007     /**
00008        Holds a [const] reference to an object. For use in template
00009        metaprogramming. Don't use this type directly: it is intended
00010        to be subclassed by reference_f<> types.
00011 
00012        T must not be pointer-qualified. Const is fine.
00013 
00014        Added in 1.1.3.
00015     */
00016     template <typename T>
00017     struct reference_base_f
00018     {
00019         typedef T type;
00020         type & value;
00021         explicit reference_base_f( type & _ref ) : value(_ref)
00022         {}
00023 
00024         /**
00025            Returns a copy of the object this one refers to.
00026         */
00027         inline operator T() const
00028         {
00029             return this->value;
00030         }
00031 
00032         /**
00033            Returns a [const] reference to the object this one
00034            refers to.
00035         */
00036         inline type & operator()() const
00037         {
00038             return this->value;
00039         }
00040 
00041     };
00042 
00043     /**
00044        Holds a reference to an object. For use in template
00045        metaprogramming.
00046 
00047        Added in 1.1.3.
00048     */
00049     template <typename T>
00050     struct reference_f : reference_base_f<T>
00051     {
00052         typedef typename reference_base_f<T>::type type;
00053         explicit reference_f( type & _ref ) : reference_base_f<T>(_ref)
00054         {}
00055 
00056         template <typename X>
00057         inline const reference_f & operator=( const X & val ) const
00058         {
00059             this->value = val;
00060             return *this;
00061         }
00062     };
00063 
00064     /**
00065        Holds a const reference to an object. For use in template
00066        metaprogramming.
00067 
00068        Added in 1.1.3.
00069     */
00070     template <typename T>
00071     struct reference_f<T const> : reference_base_f<T const>
00072     {
00073         typedef typename reference_base_f<T const>::type type;
00074         explicit reference_f( type & _ref ) : reference_base_f<T const>(_ref)
00075         {}
00076     };
00077 
00078     /**
00079        Added in 1.1.3.
00080     */
00081     template <typename T>
00082     struct reference_f<T *> : reference_base_f<T>
00083     {
00084         /** _ref must not be 0. */
00085         typedef typename reference_base_f<T>::type type;
00086         explicit reference_f( type * _ref ) : reference_base_f<T>(*_ref)
00087         {}
00088     };
00089 
00090     /**
00091        Added in 1.1.3.
00092     */
00093     template <typename T>
00094     struct reference_f<T const *> : reference_base_f<T const>
00095     {
00096         /** _ref must not be 0. */
00097         typedef typename reference_base_f<T const>::type type;
00098         explicit reference_f( type * _ref ) : reference_base_f<T const>(*_ref)
00099         {}
00100     };
00101 
00102 
00103     /**
00104        Convenience function to return reference_f<T>(ref).
00105 
00106        Added in 1.1.3.
00107     */
00108     template <typename T>
00109     inline reference_f<T> ref( T & ref )
00110     {
00111         return reference_f<T>(ref);
00112     }
00113 
00114 
00115     /**
00116        Pointer equivalent of reference_base_f.
00117 
00118        Added in 1.1.3.
00119 
00120        T may be const or not, but should not have a pointer
00121        qualification. Specializations of pointer_f take care of
00122        getting rid of the extra const/pointer/reference
00123        qualifiers.
00124     */
00125     template <typename T>
00126     struct pointer_base_f
00127     {
00128         /** Same as T, possibly const-qualified. */
00129         typedef T type;
00130         type * value;
00131         explicit pointer_base_f( type * _ref ) : value(_ref)
00132         {}
00133         explicit pointer_base_f( type & _ref ) : value(&_ref)
00134         {}
00135         /**
00136            Returns a [const] pointer to the object this one
00137            refers to.
00138         */
00139         inline type * operator()() const
00140         {
00141             return this->value;
00142         }
00143 
00144         /** For convention's sake... */
00145         inline type * get() const
00146         {
00147             return this->value;
00148         }
00149 
00150         inline type * operator->() const
00151         {
00152             return this->value;
00153         }
00154 
00155         inline bool empty() const
00156         {
00157             return 0 != this->value;
00158         }
00159     };
00160 
00161     /**
00162        Pointer equivalent of reference_f.
00163        Added in 1.1.3.
00164     */
00165     template <typename T>
00166     struct pointer_f : pointer_base_f<T>
00167     {
00168         typedef typename pointer_base_f<T>::type type;
00169         explicit pointer_f( type & _ref ) : pointer_base_f<T>(&_ref)
00170         {}
00171         explicit pointer_f( type * _ref ) : pointer_base_f<T>(_ref)
00172         {}
00173     };
00174 
00175     /**
00176        Pointer equivalent of reference_f.
00177        Added in 1.1.3.
00178     */
00179     template <typename T>
00180     struct pointer_f<T const> : pointer_base_f<T const>
00181     {
00182         typedef typename pointer_base_f<T const>::type type;
00183         explicit pointer_f( type & _ref ) : pointer_base_f<T const>(&_ref)
00184         {}
00185         explicit pointer_f( type * _ref ) : pointer_base_f<T const>(_ref)
00186         {}
00187 
00188     };
00189 
00190     /**
00191        Pointer equivalent of reference_f.
00192        Added in 1.1.3.
00193     */
00194     template <typename T>
00195     struct pointer_f<T *> : pointer_base_f<T>
00196     {
00197         typedef typename pointer_base_f<T>::type type;
00198         explicit pointer_f( type * _ref ) : pointer_base_f<T>(_ref)
00199         {}
00200         explicit pointer_f( type & _ref ) : pointer_base_f<T>(&_ref)
00201         {}
00202     };
00203 
00204     /**
00205        Pointer equivalent of reference_f.
00206        Added in 1.1.3.
00207     */
00208     template <typename T>
00209     struct pointer_f<T const *> : pointer_base_f<T const>
00210     {
00211         typedef typename pointer_base_f<T const>::type type;
00212         explicit pointer_f( type * _ref ) : pointer_base_f<T const>(_ref)
00213         {}
00214         explicit pointer_f( type & _ref ) : pointer_base_f<T const>(&_ref)
00215         {}
00216     };
00217 
00218 //  /** Returns pointer_f<T>(v). */
00219 //  template <typename T>
00220 //  inline pointer_f<T> pointer( typename type_traits<T>::type & v )
00221 //  {
00222 //      return pointer_f<T>(v);
00223 //  }
00224 
00225 //      template <typename T>
00226 //      inline pointer_f<T> pointer( typename type_traits<T>::type * v )
00227 //      {
00228 //          return pointer_f<T>(v);
00229 //      }
00230 
00231 //      template <typename T>
00232 //      inline pointer_f<T const> pointer( typename type_traits<T const>::type const & v )
00233 //      {
00234 //          return pointer_f<T const>(v);
00235 //      }
00236 
00237 //      template <typename T>
00238 //      inline pointer_f<T const> pointer( typename type_traits<T const>::type const * v )
00239 //      {
00240 //          return pointer_f<T const>(v);
00241 //      }
00242 
00243 
00244     /**
00245        Holds a value. For use in template metaprogramming.
00246 
00247        Added in 1.1.3.
00248     */
00249     template <typename T>
00250     struct value_f
00251     {
00252         typedef T type;
00253         type value;
00254         value_f( type const & _ref ) : value(_ref)
00255         {}
00256 
00257         /** Returns a copy of this->value. */
00258         inline operator T() const
00259         {
00260             return this->value;
00261         }
00262 
00263         /** Returns a copy of this->value. */
00264         inline type operator()() const
00265         {
00266             return this->value;
00267         }
00268     };
00269 
00270     /** Quasi-bogus specialization. */
00271     template <typename T>
00272     struct value_f<T const> : value_f<T> {};
00273 
00274     /** Quasi-bogus specialization. */
00275     template <typename T>
00276     struct value_f<T &> : value_f<T> {};
00277 
00278     /** Quasi-bogus specialization. */
00279     template <typename T>
00280     struct value_f<T const &> : value_f<T> {};
00281 
00282 
00283     /** Returns value_f<T>(v). */
00284     template <typename T>
00285     inline value_f<T> val( const T & v )
00286     {
00287         return value_f<T>(v);
00288     }
00289 
00290 
00291     /**
00292        Experimental. Added in 1.1.3.
00293 
00294        A Serializable functor intended for some metaprogramming
00295        experimentation, to allow lazy s11n of a Serializable.
00296 
00297        FunctorT requires this signature:
00298 
00299        bool operator()( NodeType & dest, const SerializableT & src )
00300      */
00301     template <typename SerializableT, typename FunctorT = serialize_f>
00302     struct serializable_f
00303     {
00304         typedef SerializableT const type;
00305         reference_f<type> reference;
00306         mutable /*<--- i don't like that!*/ FunctorT functor;
00307 
00308         /**
00309            Sets this->reference(_ref).
00310          */
00311         explicit serializable_f( type & _ref ) : reference(_ref), functor()
00312         {
00313         }
00314 
00315         serializable_f( type & _ref, FunctorT f ) : reference(_ref), functor(f)
00316         {
00317         }
00318 
00319         /**
00320            Returns serialize( dest, this->ref ).
00321 
00322            Calling after this->ref has been destroyed
00323            yields undefined behaviour.
00324         */
00325         template <typename NodeType>
00326         inline bool operator()( NodeType & dest ) const
00327         {
00328             return this->functor( dest, this->reference() );
00329         }
00330 
00331         /** Retyurns a const reference to this object's referenced Serializable. */
00332         inline type & operator()() const
00333         {
00334             return this->reference();
00335         }
00336     };
00337 
00338     /**
00339        Experimental. Added in 1.1.3.
00340 
00341        Returns serializable_f<SerializableT>( ref ).
00342 
00343        ref must outlive the object returned by this function!
00344     */
00345     template <typename SerializableT>
00346     inline serializable_f<SerializableT>
00347     ser_f( SerializableT const & ref )
00348     {
00349         return serializable_f<SerializableT>( ref );
00350     }
00351 
00352     /**
00353        Experimental. Added in 1.1.3.
00354 
00355        Returns serializable_f<SerializableT,FunctorT>( ref, f ).
00356 
00357        ref must outlive the object returned by this function!
00358     */
00359     template <typename SerializableT,typename FunctorT>
00360     inline serializable_f<SerializableT,FunctorT>
00361     ser_ff( SerializableT const & ref, FunctorT f )
00362     {
00363         return serializable_f<SerializableT,FunctorT>( ref, f );
00364     }
00365 
00366     /**
00367        Experimental. Added in 1.1.3.
00368 
00369        A Serializable functor intended for some metaprogramming
00370        experimentation, to allow lazy de-s11n of a Serializable.
00371 
00372        FunctorT requires this signature:
00373 
00374        bool operator()( const NodeType & src, SerializableT & dest )
00375 
00376     */
00377     template <typename DeserializableT, typename FunctorT = deserialize_f>
00378     struct deserializable_f
00379     {
00380         typedef DeserializableT type;
00381         reference_f<type> reference;
00382         mutable /*<--- i don't like that!*/ FunctorT functor;
00383 
00384         /**
00385            Sets this->ref = _ref.
00386          */
00387         explicit deserializable_f( type & _ref ) : reference(_ref),functor()
00388         {
00389         }
00390 
00391         deserializable_f( type & _ref, FunctorT f ) : reference(_ref),functor(f)
00392         {
00393         }
00394         /**
00395            Returns deserialize( src, this->ref ).
00396 
00397            Calling after this->ref has been destroyed
00398            yields undefined behaviour.
00399          */
00400         template <typename NodeType>
00401         inline bool operator()( const NodeType & src ) const
00402         {
00403             return this->functor( src, this->reference() );
00404         }
00405 
00406         /** Retyurns a reference to this object's referenced Serializable. */
00407         inline type & operator()() const
00408         {
00409             return this->reference();
00410         }
00411     };
00412 
00413 
00414     /**
00415        Experimental. Added in 1.1.3.
00416 
00417        Returns deserializable_f<DeserializableT>( ref ).
00418 
00419        ref must outlive the object returned by this function!
00420     */
00421     template <typename DeserializableT>
00422     inline deserializable_f<DeserializableT>
00423     deser_f( DeserializableT & ref )
00424     {
00425         return deserializable_f<DeserializableT>( ref );
00426     }
00427 
00428     /**
00429        Experimental. Added in 1.1.3.
00430 
00431        Returns deserializable_f<DeserializableT,FunctorT>( ref, f ).
00432 
00433        ref must outlive the object returned by this function!
00434     */
00435     template <typename DeserializableT,typename FunctorT>
00436     inline deserializable_f<DeserializableT,FunctorT>
00437     deser_ff( DeserializableT & ref, FunctorT f )
00438     {
00439         return deserializable_f<DeserializableT,FunctorT>( ref, f );
00440     }
00441 
00442     /**
00443        A functor to allow us to easily walk a list of S-Nodes and
00444        deserialize each one into a target container.
00445 
00446 
00447        The optional FunctorT defines the functor to use
00448        to deserialize each object. The default simply routes
00449        through the s11n::deserialize() API.
00450 
00451        SerializableType is unforuntately required: we can't
00452        derive it from the output iterator.
00453 
00454        SerializableType MAY NOT yet be pointer-qualified. That's on
00455        the to-fix list somewhere. It would inherently cause a leak
00456        or be very incorrect in some uses, though, like using an
00457        ostream_iterator(). It could be made to function, but would not
00458        be leak-proof.
00459 
00460        Also, we create and copy SerializableTypes here, so that type
00461        should be cheap to do that with.
00462 
00463        FunctorT must conform to the interface defined by
00464        deserialize_f.
00465 
00466        Example, assuming NTR is a node_traits type:
00467 
00468        <pre>
00469        std::for_each( NTR::children(node).begin(),
00470                   NTR::children(node).end(),
00471                   deser_to_outiter_f<MyType>( std::back_inserter(myvector) ) );
00472        </pre>
00473     */
00474     template <typename SerializableType, typename OutIterator, typename FunctorT = deserialize_f>
00475     struct deserialize_to_output_iter_f
00476     {
00477         typedef OutIterator type;
00478         type iterator;
00479         mutable /*<--- i don't like that!*/ FunctorT functor;
00480         typedef SerializableType serializable_type;
00481         // typedef typename std::iterator_traits<OutIterator>::value_type serializable_type;
00482         // ^^^ why is this void?
00483 
00484         /**
00485            Sets this object's output iterator.
00486         */
00487         explicit deserialize_to_output_iter_f( type target ) : iterator(target), functor()
00488         {}
00489 
00490         /**
00491            Sets this object's output iterator and copies the
00492            given functor.
00493         */
00494         deserialize_to_output_iter_f( type target, FunctorT f ) : iterator(target), functor(f)
00495         {}
00496 
00497         /**
00498            Creates a new object of serializable_type and deserializes it.
00499            On success iterator is assigned and incremented and true is returned.
00500            On error false is returned or an exception is propagated.
00501 
00502            If src is (!src), false is returned.
00503         */
00504         template <typename NodeType>
00505         bool operator()( NodeType * const & src )
00506         {
00507             if( src )
00508             {
00509                 serializable_type dest;
00510                 if( this->functor( *src, dest ) )
00511                 {
00512                     *(iterator++) = dest;
00513                     return true;
00514                 }
00515             }
00516             return false;
00517         }
00518     };
00519 
00520     /**
00521        Convenience function returning:
00522 
00523        deserialize_to_output_iter_f<SerializableType,OutIterator,FunctorT>( target, f )
00524     */
00525     template <typename SerializableType,typename OutIterator, typename FunctorT>
00526     inline deserialize_to_output_iter_f<SerializableType,OutIterator,FunctorT>
00527     deser_to_outiter_ff( OutIterator target, FunctorT f )
00528     {
00529         return deserialize_to_output_iter_f<SerializableType,OutIterator,FunctorT>( target, f );
00530     }
00531 
00532     /**
00533        Convenience function returning:
00534 
00535        deserialize_to_output_iter_f<SerializableType,OutIterator>( target )
00536     */
00537     template <typename SerializableType, typename OutIterator>
00538     inline deserialize_to_output_iter_f<SerializableType,OutIterator>
00539     deser_to_outiter_f( OutIterator target )
00540     {
00541         return deserialize_to_output_iter_f<SerializableType,OutIterator>( target );
00542     }
00543 
00544 
00545 
00546 
00547 
00548 
00549     /**
00550        Experimental. Added in 1.1.3.
00551 
00552        FunctorT must have:
00553 
00554        bool operator()( NodeType & dest, const SerializableT & src )
00555 
00556     */
00557     template <typename NodeType, typename FunctorT = serialize_subnode_f>
00558     struct serialize_to_subnode_f
00559     {
00560         reference_f<NodeType> node;
00561         std::string name;
00562         mutable FunctorT functor;
00563         serialize_to_subnode_f( NodeType & parent, const std::string & subnodename )
00564             : node(parent), name(subnodename),functor()
00565         {
00566         }
00567 
00568         serialize_to_subnode_f( NodeType & parent, const std::string & subnodename, FunctorT f )
00569             : node(parent), name(subnodename),functor(f)
00570         {
00571         }
00572 
00573         template <typename SerializableT>
00574         bool operator()( SerializableT const & dest ) const
00575         {
00576             typedef node_traits<NodeType> NTR;
00577             std::auto_ptr<NodeType> nap( NTR::create( this->name ) );
00578             if( this->functor( *nap, dest ) )
00579             {
00580                 NTR::children(this->node()).push_back( nap.release() );
00581             }
00582             return 0 == nap.get();
00583         }
00584     };
00585 
00586     /**
00587        Experimental. Added in 1.1.3.
00588 
00589        Returns serialize_to_subnode_f<NodeType>( parent, subnodename ).
00590 
00591        Example:
00592        <pre>
00593        std::for_each( vec.begin(),
00594                vec.end(),
00595                ser_to_subnode_f( mynode, "child" )
00596                );
00597        </pre>
00598 
00599     */
00600     template <typename NodeType>
00601     inline serialize_to_subnode_f<NodeType>
00602     ser_to_subnode_f( NodeType & parent, const std::string & subnodename )
00603     {
00604         return serialize_to_subnode_f<NodeType>( parent, subnodename );
00605     }
00606 
00607     /**
00608        Experimental. Added in 1.1.3.
00609 
00610        Returns serialize_to_subnode_f<NodeType,FunctorT>( parent, subnodename, f ).
00611 
00612        Example:
00613 
00614        <pre>
00615        std::for_each( vec.begin(),
00616                vec.end(),
00617                ser_to_subnode_ff( mynode, "child", my_serialize_to_subnode_functor() )
00618                );
00619        </pre>
00620 
00621     */
00622     template <typename NodeType, typename FunctorT>
00623     inline serialize_to_subnode_f<NodeType,FunctorT>
00624     ser_to_subnode_ff( NodeType & parent, const std::string & subnodename, FunctorT f )
00625     {
00626         return serialize_to_subnode_f<NodeType,FunctorT>( parent, subnodename, f );
00627     }
00628 
00629     
00630 
00631     /**
00632        Experimental. Added in 1.1.3.
00633 
00634        FunctorT requires this signature:
00635 
00636        bool operator()( const NodeType & src, const std::string & subnodename, SerializableT & dest )
00637 
00638     */
00639     template <typename NodeType, typename FunctorT = deserialize_subnode_f>
00640     struct deserialize_from_subnode_f
00641     {
00642         reference_f<NodeType const> node;
00643         std::string name;
00644         mutable FunctorT functor;
00645         deserialize_from_subnode_f( const NodeType & parent, const std::string & subnodename )
00646             : node(parent), name(subnodename),functor()
00647         {
00648         }
00649 
00650         deserialize_from_subnode_f( const NodeType & parent, const std::string & subnodename, FunctorT f )
00651             : node(parent), name(subnodename),functor(f)
00652         {
00653         }
00654 
00655         // TODO: add &* handling.
00656         template <typename SerializableT>
00657         inline bool operator()( SerializableT & src ) const
00658         {
00659             return this->functor( this->node(), this->name, src );
00660         }
00661     };
00662 
00663     /**
00664        Experimental. Added in 1.1.3.
00665 
00666        Returns deserialize_from_subnode_f<NodeType>( parent, subnodename ).
00667     */
00668     template <typename NodeType>
00669     inline deserialize_from_subnode_f<NodeType>
00670     deser_from_subnode_f( const NodeType & parent, const std::string & subnodename )
00671     {
00672         return deserialize_from_subnode_f<NodeType>( parent, subnodename );
00673     }
00674     /**
00675        Experimental. Added in 1.1.3.
00676 
00677        Returns deserialize_from_subnode_f<NodeType,FunctorT>( parent, subnodename, f ).
00678     */
00679     template <typename NodeType, typename FunctorT>
00680     inline deserialize_from_subnode_f<NodeType,FunctorT>
00681     deser_from_subnode_ff( const NodeType & parent, const std::string & subnodename, FunctorT f )
00682     {
00683         return deserialize_from_subnode_f<NodeType,FunctorT>( parent, subnodename, f );
00684     }
00685 
00686 } // namespace s11n
00687 
00688 
00689 #endif // s11n_EXPERIMENTAL_HPP_INCLUDED

Generated on Thu Sep 29 20:01:14 2005 for libs11n-1.1.3-dev by  doxygen 1.4.1