$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] [factory][bind] C2664 with MSVC 2015 & 1.63
From: Jens Weller (JensWeller_at_[hidden])
Date: 2017-02-02 10:26:31
> Gesendet: Mittwoch, 01. Februar 2017 um 20:34 Uhr
> Von: "Peter Dimov" <lists_at_[hidden]>
> An: boost_at_[hidden]
> Betreff: Re: [boost] [factory][bind] C2664 with MSVC 2015 & 1.63
>
> Jens Weller wrote:
> > Hi Peter,
> >
> > yes, I managed to that by now:
> > #include <boost/function.hpp>
> > #include <boost/functional/factory.hpp>
> > #include <boost/bind.hpp>
> >
> > struct Widget {};
> > struct Panel: Widget{Panel(Widget* q){}};
> >
> > using make_interface = boost::function<Widget*(Widget*)>;
> > void registerType(const make_interface &make)
> > {
> >     //factory.register_factory(type_id,make);
> > }
> > int main(int argc, char *argv[])
> > {
> >     auto f = boost::factory<Panel*>();
> >     registerType( boost::bind(f,_1));//< this line is the cause, factory 
> > it self compiles
> > }
> 
> Thanks Jens.
> 
> When I try
> 
>     registerType( f );
> 
> I get the same error:
> 
> 1>testbed2015.cpp(6): warning C4100: 'q': unreferenced formal parameter
> 1>testbed2015.cpp(10): warning C4100: 'make': unreferenced formal parameter
> 1>c:\Projects\boost-git\boost\boost/function/function_template.hpp(138): 
> error C2664: 'Panel *boost::factory<Panel 
> *,void,boost::factory_alloc_for_pointee_and_deleter>::operator ()(void) 
> const': cannot convert argument 1 from 'Widget *' to 'Widget *&'
> 
> The problem as far as I can see is that boost::function passes its parameter 
> of type Widget* as an rvalue to its target, rather than as an lvalue, and 
> factory<> takes its arguments by lvalue reference.
> 
> function's behavior is correct in that if you declare 
> boost::function<void(unique_ptr<X>)>, the argument needs to be passed as an 
> rvalue or it won't work. But it does break code such as the above.
> 
> Ideally, boost::factory would need to be fixed to use perfect forwarding on 
> C++11 and above.
> 
> A quick look at its documentation suggests using forward_adapter:
> 
>     auto f2 = boost::forward_adapter<decltype(f)>( f );
>     registerType( f2 ); // works
> 
> forward_adapter however doesn't define ::result_type so when you bind it you 
> have to give the type:
> 
>     registerType( boost::bind<Widget*>( f2, _1 ) );
> 
> No idea why it needs to be so hard.
> 
> 
> _______________________________________________
> Unsubscribe & other changes: http://listarchives.boost.org/mailman/listinfo.cgi/boost
> 
Yes, that fixes this indeed. Didn't know about forward_adapter.
thanks,
Jens Weller