Boost logo

Boost Users :

Subject: Re: [Boost-users] [fusion] memory layout of fusion::vector vs boost::tuple/boost::array
From: Alfredo Correa (correaa_at_[hidden])
Date: 2010-10-09 14:14:48


On Sat, Oct 9, 2010 at 7:53 AM, OvermindDL1 <overminddl1_at_[hidden]> wrote:
> On Sat, Oct 9, 2010 at 4:11 AM, alfC <alfredo.correa_at_[hidden]> wrote:
>>
>>
>> On Oct 9, 2:24 am, alfC <alfredo.cor..._at_[hidden]> wrote:
>>> On Oct 8, 8:00 pm, OvermindDL1 <overmind..._at_[hidden]> wrote:
>>>
>>>
>>>
>>> > On Fri, Oct 8, 2010 at 6:57 PM, Joel de Guzman
>>>
>>> > <j..._at_[hidden]> wrote:
>>> > > On 10/9/2010 2:44 AM, alfC wrote:
>>>
>>> > >> On Oct 6, 5:33 pm, Joel de Guzman<j..._at_[hidden]>  wrote:
>>>
>>> > >>> On 10/7/2010 3:53 AM, alfC wrote:
>>>
>>> > >>>> Hi,
>>>
>>> > >>>>   I am trying to convert a boost::array into a fusion::vector.
>>> > >>>> reinterpreting the memory from boost::array. It works for tuples but
>>> > >>>> not fusion::vector, why is that. Is there a way to make it work? ( I
>>> > >>>> was hoping that the memory layout is the same to make conversion from
>>> > >>>> one to the other very easy.)
>>>
>>> > >>> Don't do that. It will *never* be guaranteed to work even if it works
>>> > >>> now. The memory layout of fusion::vector is an internal implementation
>>> > >>> detail and can change anytime.
>>>
>>> > >> The question is: is it guaranteed for boost::tuples<double,
>>> > >> double, ...>?
>>> > >> (it seems so, just by the PODness of tuples of PODs in its stated
>>> > >> design.) If so, then it is a *feature* of boost::tuple.
>>>
>>> > > No it is not. 1) It is not documented 2) It is not a POD
>>> > > 3) Anything with a reinterpret_cast is not guaranteed to work
>>> > > (you can only rely on reinterpret_cast only when casting
>>> > > back from a lost type e.g. through type erasure).
>>>
>>> > > Disregarding any of that is playing with fire.
>>>
>>> > The previous posts a few posts ago seems overly complicated, I would
>>> > just do this (suitably wrapped into a function to handle it, maybe
>>> > named copy):
>>>
>>> > // Proper includes here...
>>>
>>> > struct set1stTo2nd
>>> > {
>>> >     template<typename T>
>>> >     void operator()(T& t) const
>>> >     {
>>> >         using namespace boost::fusion;
>>> >         deref(begin(t)) = deref(next(begin(t)));
>>> >     }};
>>>
>>> > typedef boost::array<int,3> arrType;
>>> > typedef boost::fusion::vector<int,int,int> vecType;
>>> > typedef boost::fusion::vector<arrType&,vecType&> zipSeqType;
>>>
>>> > arrType arr(1,1,1);
>>> > vecType vec(5,5,5);
>>>
>>> > for_each(zipSeqType(arr,vec), set1stTo2nd());
>>> > assert(arr == make_vector(5,5,5));
>>
>> FINALLY! I got it. I feel better now.
>>
>> It turns out that the correct line of code is
>>
>> for_each(
>>        boost::fusion::zip_view<zipSeqType>(zipSeqType(arr2,vec1)),
>>        set1stTo2nd()
>> );
>>
>> you wrote the correct typedef but then didn't apply the zip_view
>> function.
>>
>>
>> (Although, related to the original question, I am still a bit worried
>> about too much unnecessary copy which seems unavoidable since the
>> memory layout of array<double, N> and fusion::vector<double*N> is
>> different.)
>>
>> below is the full program that *works*:
>>
>> #include<boost/array.hpp>
>> #include <boost/fusion/container.hpp>
>> #include <boost/fusion/include/container.hpp>
>> #include <boost/fusion/adapted/boost_array.hpp>
>> #include <boost/fusion/include/boost_array.hpp>
>> #include <boost/fusion/algorithm/iteration/for_each.hpp>
>> #include <boost/fusion/include/for_each.hpp>
>> #include <boost/fusion/algorithm/transformation/zip.hpp>
>> #include <boost/fusion/include/zip.hpp>
>> #include <boost/fusion/view/zip_view.hpp>
>> #include <boost/fusion/include/zip_view.hpp>
>>
>> #include<iostream>
>> using std::clog; using std::endl;
>>
>> using namespace boost::fusion;
>> struct set1stTo2nd
>> {
>>    template<typename T>
>>    void operator()(T t) const
>>    {
>>        deref(boost::fusion::begin(t)) =
>> deref(boost::fusion::next(boost::fusion::begin(t)));
>>    }
>> };
>>
>> typedef boost::array<double,3> arrType;
>> typedef boost::fusion::vector<double,double,double> vecType;
>> typedef boost::fusion::vector<arrType&,vecType&> zipSeqType;
>>
>> int main(){
>>        boost::array<double, 3> arr1={{1.0, 2.1, 3.2}};
>>        clog << "arr1: " << arr1[0] << ", " <<  arr1[1] << ", " << arr1[2] <<
>> endl;
>>
>>  boost::fusion::vector<double, double, double> vec1(arr1);
>>        clog << "vec1: " << at_c<0>(vec1) << ", "<< at_c<1>(vec1) << ", " <<
>> at_c<2>(vec1) << endl;
>>
>>        boost::array<double, 3> arr2;
>>        for_each(
>>                boost::fusion::zip_view<zipSeqType>(zipSeqType(arr2,vec1)),
>>                set1stTo2nd()
>>        );
>>        clog << "arr2: " << at_c<0>(arr2) << ", "<< at_c<1>(arr2) << ", " <<
>> at_c<2>(arr2) << endl;
>>        return 0;
>> }
>>
>> prints:
>> arr1: 1, 2.1, 3.2
>> vec1: 1, 2.1, 3.2
>> arr2: 1, 2.1, 3.2
>>
>> Have a good weekend,
>> Alfredo
>
>
> Yeah, my mistake, busy at work and not paying attention, I meant to
> have the fusion::zip there.  :)

another subtlety is that the correct signature is

struct set1stTo2nd
{
   template<typename T>
   void operator()(T t) const // not T& t) const
    ...

> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>
> --
> Sie haben diese Nachricht erhalten, da Sie der Google Groups-Gruppe Boost Users beigetreten sind.
> Wenn Sie Nachrichten in dieser Gruppe posten möchten, senden Sie eine E-Mail an boostusers_at_googlegroups.com.
> Wenn Sie aus dieser Gruppe austreten möchten, senden Sie eine E-Mail an boostusers+unsubscribe_at_googlegroups.com.
> Besuchen Sie die Gruppe unter http://groups.google.com/group/boostusers?hl=de, um weitere Optionen zu erhalten.
>
>


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net