[fusion] Wrapping a Fusion sequence
I'm looking for a way to create a Fusion sequence wrapper that is itself a Fusion sequence and forwards all 'calls' to its wrapped sequence. Something in the lines of template< typename Sequence > struct sequence_wrapper { explicit sequence_wrapper( Sequence const& s ) : seq( s ){} Sequence seq; }; where sequence_wrapper< Sequence > is a Fusion sequence as well, and works just as Sequence would. The reason I need this is that I have several functions that operate on Fusion sequences (where all elements satisfy some special requirements), and I would like to add some syntax sugar for which I need a custom type to add overloaded operators to. I do not need the result of operations on a sequence_wrapper to return a sequence_wrapper as well, only the syntax sugar related calls would return a (manually) wrapped sequence. For instance, appending elements to a sequence using the comma operator (somewhat of a Boost.Assign for Fusion sequences): template< typename Sequence, typename T > sequence_wrapper< typename boost::fusion::result_of::push_back< Sequence const& , T >::type > operator,( Sequence const& seq, T const& v ) { return sequence_wrapper< typename boost::fusion::result_of::push_back< Sequence const& , T >::type >( boost::fusion::push_back( seq, v ) ) ; } What would be the best way to achieve this (if it is indeed supported by the library)? I'm particularly trying to avoid creating a Fusion sequence from scratch, as I would like to use whatever sequence is returned by Fusion operations. Would inheritance + specialization of `tag_of` to return the tag of the wrapped sequence just work? Or will I need to define a tag of my own and implement all required functions to just forward the call? Thank you in advance. Agustín K-ballo Bergé.- http://fusionfenix.com
On 8/29/2012 7:10 AM, Agustín K-ballo Bergé wrote:
I'm looking for a way to create a Fusion sequence wrapper that is itself a Fusion sequence and forwards all 'calls' to its wrapped sequence. Something in the lines of
template< typename Sequence > struct sequence_wrapper { explicit sequence_wrapper( Sequence const& s ) : seq( s ){}
Sequence seq; };
where sequence_wrapper< Sequence > is a Fusion sequence as well, and works just as Sequence would. The reason I need this is that I have several functions that operate on Fusion sequences (where all elements satisfy some special requirements), and I would like to add some syntax sugar for which I need a custom type to add overloaded operators to. I do not need the result of operations on a sequence_wrapper to return a sequence_wrapper as well, only the syntax sugar related calls would return a (manually) wrapped sequence. For instance, appending elements to a sequence using the comma operator (somewhat of a Boost.Assign for Fusion sequences):
template< typename Sequence, typename T > sequence_wrapper< typename boost::fusion::result_of::push_back< Sequence const& , T >::type > operator,( Sequence const& seq, T const& v ) { return sequence_wrapper< typename boost::fusion::result_of::push_back< Sequence const& , T >::type >( boost::fusion::push_back( seq, v ) ) ; }
What would be the best way to achieve this (if it is indeed supported by the library)? I'm particularly trying to avoid creating a Fusion sequence from scratch, as I would like to use whatever sequence is returned by Fusion operations. Would inheritance + specialization of `tag_of` to return the tag of the wrapped sequence just work? Or will I need to define a tag of my own and implement all required functions to just forward the call?
I do not know an easy way other than using the Sequence Facade: http://tinyurl.com/8k5wq5p Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com
On 31/08/2012 12:05 a.m., Joel de Guzman wrote:
On 8/29/2012 7:10 AM, Agustín K-ballo Bergé wrote:
I'm looking for a way to create a Fusion sequence wrapper that is itself a Fusion sequence and forwards all 'calls' to its wrapped sequence.
What would be the best way to achieve this (if it is indeed supported by the library)? I'm particularly trying to avoid creating a Fusion sequence from scratch, as I would like to use whatever sequence is returned by Fusion operations. Would inheritance + specialization of `tag_of` to return the tag of the wrapped sequence just work? Or will I need to define a tag of my own and implement all required functions to just forward the call?
I do not know an easy way other than using the Sequence Facade: http://tinyurl.com/8k5wq5p
Regards,
Thank you for your answer. I was hoping there was a simpler way given that, as far as I understand, most (all?) Fusion containers are implemented as wrappers over vector. Also, its still a bit unclear to me how does sequence_facade relate to the full extension mechanism. Here is my first attempt at a sequence wrapper: template< typename Derived , typename Sequence , typename TraversalTag = typename boost::fusion::traits::category_of< Sequence >::type , typename IsView = typename boost::fusion::traits::is_view< Sequence >::type > class sequence_wrapper : public boost::fusion::sequence_facade< Derived, TraversalTag, IsView > { typedef Sequence base_sequence_type; public: explicit sequence_wrapper( base_sequence_type const& sequence ) : _seq( sequence ) {} base_sequence_type const& base() const { return _seq; } base_sequence_type& base() { return _seq; } public: template< typename Seq > struct begin { typedef typename boost::fusion::result_of::begin< base_sequence_type >::type type; static type call( Seq s ){ return boost::fusion::begin( s._seq ); } }; template< typename Seq > struct end { typedef typename boost::fusion::result_of::end< base_sequence_type >::type type; static type call( Seq s ){ return boost::fusion::end( s._seq ); } }; template< typename Seq > struct size { typedef typename boost::fusion::result_of::size< base_sequence_type >::type type; static type call( Seq s ){ return boost::fusion::size( s._seq ); } }; template< typename Seq > struct empty { typedef typename boost::fusion::result_of::empty< base_sequence_type >::type type; static type call( Seq s ){ return boost::fusion::empty( s._seq ); } }; template< typename Seq, typename N > struct at { typedef typename boost::fusion::result_of::at< base_sequence_type, N >::type type; static type call( Seq s ){ return boost::fusion::at( s._seq ); } }; template< typename Seq, typename N > struct value_at { typedef typename boost::fusion::result_of::value_at< base_sequence_type, N >::type type; }; private: base_sequence_type _seq; }; It seems to be working as expected. When I find some spare time I will try reimplementing some of the existing containers in terms of vector, and then check them against Fusion tests. Agustín K-ballo Bergé.- http://fusionfenix.com
On 9/1/2012 10:02 AM, Agustín K-ballo Bergé wrote:
Thank you for your answer. I was hoping there was a simpler way given that, as far as I understand, most (all?) Fusion containers are implemented as wrappers over vector.
Nope. Only set and map.
Also, its still a bit unclear to me how does sequence_facade relate to the full extension mechanism.
The sequence facade is built on top of the full extension mechanism but provides a simpler (albeit intrusive) interface. Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com
On 31/08/2012 11:02 p.m., Agustín K-ballo Bergé wrote:
On 31/08/2012 12:05 a.m., Joel de Guzman wrote:
On 8/29/2012 7:10 AM, Agustín K-ballo Bergé wrote:
I'm looking for a way to create a Fusion sequence wrapper that is itself a Fusion sequence and forwards all 'calls' to its wrapped sequence.
What would be the best way to achieve this (if it is indeed supported by the library)? I'm particularly trying to avoid creating a Fusion sequence from scratch, as I would like to use whatever sequence is returned by Fusion operations. Would inheritance + specialization of `tag_of` to return the tag of the wrapped sequence just work? Or will I need to define a tag of my own and implement all required functions to just forward the call?
I do not know an easy way other than using the Sequence Facade: http://tinyurl.com/8k5wq5p
Regards,
Thank you for your answer. I was hoping there was a simpler way given that, as far as I understand, most (all?) Fusion containers are implemented as wrappers over vector. Also, its still a bit unclear to me how does sequence_facade relate to the full extension mechanism.
Here is my first attempt at a sequence wrapper:
Here is my second attempt, using references where appropriate and propagating constness: template< typename Derived , typename Sequence , typename TraversalTag = typename boost::fusion::traits::category_of< Sequence >::type , typename IsView = typename boost::fusion::traits::is_view< Sequence >::type > class fusion_sequence_wrapper : public boost::fusion::sequence_facade< Derived, TraversalTag, IsView > { typedef Sequence base_sequence_type; public: explicit fusion_sequence_wrapper( base_sequence_type const& sequence ) : _seq( sequence ) {} base_sequence_type const& base() const { return _seq; } base_sequence_type& base() { return _seq; } public: template< typename Seq > struct begin { typedef typename boost::fusion::result_of::begin< typename boost::mpl::if_< boost::is_const< Seq > , base_sequence_type const , base_sequence_type >::type >::type type; static type call( Seq& s ){ return boost::fusion::begin( s._seq ); } }; template< typename Seq > struct end { typedef typename boost::fusion::result_of::end< typename boost::mpl::if_< boost::is_const< Seq > , base_sequence_type const , base_sequence_type >::type >::type type; static type call( Seq& s ){ return boost::fusion::end( s._seq ); } }; template< typename Seq > struct size { typedef typename boost::fusion::result_of::size< typename boost::mpl::if_< boost::is_const< Seq > , base_sequence_type const , base_sequence_type >::type >::type type; static type call( Seq& s ){ return boost::fusion::size( s._seq ); } }; template< typename Seq > struct empty { typedef typename boost::fusion::result_of::empty< typename boost::mpl::if_< boost::is_const< Seq > , base_sequence_type const , base_sequence_type >::type >::type type; static type call( Seq& s ){ return boost::fusion::empty( s._seq ); } }; template< typename Seq, typename N > struct at { typedef typename boost::fusion::result_of::at< typename boost::mpl::if_< boost::is_const< Seq > , base_sequence_type const , base_sequence_type >::type , N >::type type; static type call( Seq& s ){ return boost::fusion::at( s._seq ); } }; template< typename Seq, typename N > struct value_at { typedef typename boost::fusion::result_of::value_at< typename boost::mpl::if_< boost::is_const< Seq > , base_sequence_type const , base_sequence_type >::type , N >::type type; }; private: base_sequence_type _seq; }; Agustín K-ballo Bergé.- http://fusionfenix.com
participants (2)
-
Agustín K-ballo Bergé
-
Joel de Guzman