
On 8/23/2012 11:04 AM, Eric Niebler wrote:
On 8/22/2012 7:45 PM, Joel de Guzman wrote:
On 8/23/2012 4:38 AM, Eric Niebler wrote:
Say I have a valid fusion sequence. I want to use an mpl algorithm on it. I include boost/fusion/mpl.hpp and put a nested tag type in my sequence that is an alias for fusion::fusion_sequence_tag. So far, so good. Then I try to call mpl::pop_back on this sequence, and I find that, despite fulfilling all the documented requirements for Fusion ForwardSequence, the code fails to compile. That's because of this in boost/fusion/mpl/pop_back.hpp:
template <> struct pop_back_impl<fusion::fusion_sequence_tag> { template <typename Sequence> struct apply { typedef typename fusion::result_of::pop_back<Sequence>::type result;
typedef typename fusion::result_of::convert< typename fusion::detail::tag_of<Sequence>::type, result>::type type; }; };
My code doesn't compile because I haven't implemented the fusion::convert customization point. Where is that documented and what does it do?
The basic problem is that MPL has this Extensible Sequence concept that Fusion does not have. Keep in mind that mpl::pop_back requires a Front Extensible Sequence and Fusion only guarantees adaptation of an MPL Forward, Bidirectional or Random Access Sequence (http://tinyurl.com/c7tmyfj). In this regard, we are actually going beyond what's guaranteed by Fusion.
That being said, I am really considering adding extensible sequences into Fusion. The Deque, for example is a good example.
The point remains: there is a required Fusion customization point that is not documented. (Or is it?)
No, it is not.
So, should convert generate an mpl sequence? Or a Fusion sequence?
A Fusion sequence.
Is there any post-condition regarding the tag type (or fusion_tag type?) of the resulting sequence?
The actual (undocumented) extension mechanism is: namespace extension { template <typename Tag> struct convert_impl; } which result_of::convert calls. Here's an example for vector: struct vector_tag; namespace extension { template <typename T> struct convert_impl; template <> struct convert_impl<vector_tag> { template <typename Sequence> struct apply { typedef typename detail::as_vector<result_of::size<Sequence>::value> gen; typedef typename gen:: template apply<typename result_of::begin<Sequence>::type>::type type; static type call(Sequence& seq) { return gen::call(fusion::begin(seq)); } }; }; } Pretty much straightforward. I think it is safe to use this extension mechanism. It has been stable for a long time now. Surely, that is not an excuse for it being undocumented though. At any rate, I added this in my TODO list. Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com