[fusion] more trouble with transform
Hi, Now I am trying to perform transform which mutates: ------ #include <boost/fusion/container/list/list.hpp> #include <boost/fusion/container/list/convert.hpp> #include <boost/fusion/container/generation/make_list.hpp> #include <boost/fusion/algorithm/transformation/transform.hpp> namespace fusion=boost::fusion; struct C {}; struct B { C make_c() { return C(); } }; struct make_c { template<typename Sig> struct result; template <typename T> struct result<make_c(T&)> { typedef C type; }; template <typename T> struct result<make_c(T)> { typedef C type; }; template <typename T> C operator()(T& t) const { return t.make_c(); } }; int main() { B b1, b2; auto z1 = fusion::make_list( b1, b2 ); auto z2 = fusion::as_list( fusion::transform( z1, make_c() ) ); return 0; } ---- Both gcc and msvc complain like this: test.cpp:29:46: error: passing ‘const B’ as ‘this’ argument of ‘C B::make_c()’ discards qualifiers. What am I missing now? Gennadiy
Gennadiy Rozental <rogeeff@gmail.com> writes:
Hi,
Now I am trying to perform transform which mutates:
------ #include <boost/fusion/container/list/list.hpp> #include <boost/fusion/container/list/convert.hpp> #include <boost/fusion/container/generation/make_list.hpp> #include <boost/fusion/algorithm/transformation/transform.hpp> namespace fusion=boost::fusion;
struct C {};
struct B { C make_c() { return C(); } };
struct make_c { template<typename Sig> struct result;
template <typename T> struct result<make_c(T&)> { typedef C type; }; template <typename T> struct result<make_c(T)> { typedef C type; };
template <typename T> C operator()(T& t) const { return t.make_c(); } };
int main() { B b1, b2; auto z1 = fusion::make_list( b1, b2 );
auto z2 = fusion::as_list( fusion::transform( z1, make_c() ) );
return 0; } ----
Both gcc and msvc complain like this:
test.cpp:29:46: error: passing ‘const B’ as ‘this’ argument of ‘C B::make_c()’ discards qualifiers.
What am I missing now?
Gennadiy
fusion::transform only accepts cref-qualified sequences. That is why the resulting transform view will be store a reference to z1 const and thus the arguments passed to make_c are const-qualified. https://svn.boost.org/trac/boost/ticket/3446 Construct the transform view by hand and your example should work fine. Christopher
On 11/12/2011 7:18 PM, Christopher Schmidt wrote:
Gennadiy Rozental<rogeeff@gmail.com> writes:
Hi,
Now I am trying to perform transform which mutates:
[snip]
Both gcc and msvc complain like this:
test.cpp:29:46: error: passing ‘const B’ as ‘this’ argument of ‘C B::make_c()’ discards qualifiers.
What am I missing now?
Gennadiy
fusion::transform only accepts cref-qualified sequences. That is why the resulting transform view will be store a reference to z1 const and thus the arguments passed to make_c are const-qualified.
https://svn.boost.org/trac/boost/ticket/3446
Construct the transform view by hand and your example should work fine.
Again, as I said in the link you gave, I am willing to accept a patch if it includes docs + tests. The changes are simple enough. Just don't give me a whole change-everything-in-one-fell-swoop patch. I will not have enough time to review them all. Incremental changes such as this will be good. Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com
Gennadiy Rozental <rogeeff@gmail.com> writes:
Christopher Schmidt <mr.chr.schmidt <at> online.de> writes:
Construct the transform view by hand and your example should work fine.
I am rather a newbie fusion wise. Do you mind showing me an example?
Gennadiy
auto z2=fusion::as_list(fusion::transform_view<decltype(z1),make_c>(z1,make_c())); Christopher
Hi! please see my answer below. On Sat, Nov 12, 2011 at 12:03 PM, Gennadiy Rozental <rogeeff@gmail.com>wrote:
Hi,
Now I am trying to perform transform which mutates:
int main() { B b1, b2; auto z1 = fusion::make_list( b1, b2 ); !!! create a list of copied Bs
auto z2 = fusion::as_list( fusion::transform( z1, make_c() ) ); !!! copies Bs again
return 0; }
You need to make a list of references to Bs: This is a slighly modified code which compiled in msvc #include <boost/fusion/container/list/list.hpp> #include <boost/fusion/container/list/convert.hpp> #include <boost/fusion/container/generation/make_list.hpp> #include <boost/fusion/algorithm/transformation/transform.hpp> #include <boost/ref.hpp> using namespace boost; struct C {}; struct B { C make_c() { return C(); } }; struct make_c { template<typename Sig> struct result; template <typename T> struct result<make_c(T&)> { typedef C type; }; template <typename T> struct result<make_c(T)> { typedef C type; }; template <typename T> C operator()(T& t) const { return t.make_c(); } }; int main() { B b1, b2; auto z1 = fusion::make_list( ref(b1), ref(b2) ); auto z2 = fusion::as_list( fusion::transform( z1, make_c() ) ); return 0; } Regards, Ovanes
On Sat, Nov 12, 2011 at 12:20 PM, Ovanes Markarian <om_boost@keywallet.com>wrote:
Hi!
please see my answer below.
On Sat, Nov 12, 2011 at 12:03 PM, Gennadiy Rozental <rogeeff@gmail.com>wrote:
Hi,
Now I am trying to perform transform which mutates:
int main() { B b1, b2; auto z1 = fusion::make_list( b1, b2 ); !!! create a list of copied Bs
auto z2 = fusion::as_list( fusion::transform( z1, make_c() ) ); !!! copies Bs again
Actually transformation does not copy Bs. They are only copied at list construction , but transform calls the function: inline typename result_of::as_list<Sequence const>::type as_list(Sequence const& seq) { return result_of::as_list<Sequence const>::call(seq); } Which deals with a const sequence... Regards, Ovanes
Ovanes Markarian <om_boost <at> keywallet.com> writes:
inline typename result_of::as_list<Sequence const>::type as_list(Sequence const& seq) { return result_of::as_list<Sequence const>::call(seq); } Which deals with a const sequence...
I actually hope this one is going to be moved outside. I need final result to look line fusion::list, not any kind of view. Gennadiy
Ovanes Markarian <om_boost <at> keywallet.com> writes:
You need to make a list of references to Bs: B b1, b2; auto z1 = fusion::make_list( ref(b1), ref(b2) ); auto z2 = fusion::as_list( fusion::transform( z1, make_c() ) );
This one indeed works, but what I am really after is something like this: auto z1 = fusion::make_list( B(), B() ); auto z2 = fusion::as_list( fusion::transform( z1, make_c() ) ); I know first line will move constructed instances into list z1. Next I need to mutate them and adding boost::ref around B() is impossible. In reality my use case somewhat more complicated. Something like this: #include <boost/fusion/container/list/list.hpp> #include <boost/fusion/container/list/convert.hpp> #include <boost/fusion/container/generation/make_list.hpp> #include <boost/fusion/algorithm/transformation/transform.hpp> namespace fusion=boost::fusion; struct C {}; struct B { C make_c() { return C(); } }; class A { public: B make_b() const { return B(); } }; //____________________________________________________________________________// struct make_b { template<typename Sig> struct result; template <typename T> struct result<make_b(T const&)> { typedef B type; }; template <typename T> struct result<make_b(T)> { typedef B type; }; template <typename T> B operator()(T const& t) const { return t.make_b(); } }; struct make_c { template<typename Sig> struct result; template <typename T> struct result<make_c(T&)> { typedef C type; }; template <typename T> struct result<make_c(T)> { typedef C type; }; template <typename T> C operator()(T& t) const { return t.make_c(); } }; template<typename T> void do_something( T const& t ) { } int main() { auto z1 = fusion::as_list( fusion::transform( fusion::make_list( A(), A() ), make_b() ) ); size_t size = 1; // I calculate size here, irrelevant to the question while( size-- > 0 ) do_something( fusion::as_list( fusion::transform( z1, make_c() ) ) ); return 0; } Same problem. Gennadiy
On Sat, Nov 12, 2011 at 1:08 PM, Gennadiy Rozental <rogeeff@gmail.com>wrote:
Ovanes Markarian <om_boost <at> keywallet.com> writes:
You need to make a list of references to Bs: B b1, b2; auto z1 = fusion::make_list( ref(b1), ref(b2) ); auto z2 = fusion::as_list( fusion::transform( z1, make_c() ) );
This one indeed works, but what I am really after is something like this:
auto z1 = fusion::make_list( B(), B() ); auto z2 = fusion::as_list( fusion::transform( z1, make_c() ) );
I know first line will move constructed instances into list z1. Next I need to mutate them and adding boost::ref around B() is impossible. In reality my use case somewhat more complicated. Something like this:
Quickly, I can come up with: Declare the mutating member inside B (B::make_c()) as const and declare mutated members with mutable. This will work as well. Than you don't need to pass B by ref. You can than make it as you stated. May be there is a more elegant solution, I will think about it. Best Regards, Ovanes
participants (4)
-
Christopher Schmidt
-
Gennadiy Rozental
-
Joel de Guzman
-
Ovanes Markarian