[factory][bind] C2664 with MSVC 2015 & 1.63

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

[factory][bind] C2664 with MSVC 2015 & 1.63

Jens Weller
Hello Boost,

I'm having this Problem: http://lists.boost.org/boost-users/2015/04/84176.php

That message already describes pretty much what I see, except that I use 1.63 and the latest 2015 VC++.

Errormessage:
D:\cpp\libraries\boost_1_63_0\boost\bind\bind.hpp:388: error: C2664: 'ListsModuleWidget *boost::factory<ListsModuleWidget *,void,boost::factory_alloc_for_pointee_and_deleter>::operator ()(void) const': cannot convert argument 1 from 'Module *' to 'Module *&'

bind.hpp code:
> template<class R, class F, class A> R operator()(type<R>, F & f, A & a, long)
>     {
>  >>this line        return unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_]);
>    }

Compiler says:

..\..\..\..\cpp\libraries\boost_1_63_0\boost/bind/bind.hpp(388): error C2664: 'ListsModuleWidget *boost::factory<ListsModuleWidget *,void,boost::factory_alloc_for_pointee_and_deleter>::operator ()(void) const': cannot convert argument 1 from 'Module *' to 'Module *&'
..\..\..\..\cpp\libraries\boost_1_63_0\boost/bind/bind.hpp(1342): note: see reference to function template instantiation 'R *boost::_bi::list3<boost::arg<1>,boost::arg<2>,boost::arg<3>>::operator ()<ListsModuleWidget*,F,boost::_bi::rrlist4<A1,A2,A3,A4>>(boost::_bi::type<ListsModuleWidget *>,F &,A &,long)' being compiled
        with
        [
            R=ListsModuleWidget *,
            F=boost::factory<ListsModuleWidget *,void,boost::factory_alloc_for_pointee_and_deleter>,
            A1=Module *,
            A2=const QString &,
            A3=const QString &,
            A4=QWidget *,
            A=boost::_bi::rrlist4<Module *,const QString &,const QString &,QWidget *>
        ]

cheers,

Jens Weller

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [factory][bind] C2664 with MSVC 2015 & 1.63

Peter Dimov-2
Jens Weller wrote:
> Hello Boost,
>
> I'm having this Problem:
> http://lists.boost.org/boost-users/2015/04/84176.php
>
> That message already describes pretty much what I see, except that I use
> 1.63 and the latest 2015 VC++.

Can you please give me a short but complete program that fails with the same
or a similar error?


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [factory][bind] C2664 with MSVC 2015 & 1.63

Jens Weller
> Gesendet: Mittwoch, 01. Februar 2017 um 17:04 Uhr
> Von: "Peter Dimov" <[hidden email]>
> An: [hidden email]
> Betreff: Re: [boost] [factory][bind] C2664 with MSVC 2015 & 1.63
>
> Jens Weller wrote:
> > Hello Boost,
> >
> > I'm having this Problem:
> > http://lists.boost.org/boost-users/2015/04/84176.php
> >
> > That message already describes pretty much what I see, except that I use
> > 1.63 and the latest 2015 VC++.
>
> Can you please give me a short but complete program that fails with the same
> or a similar error?
>
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>

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
}

Error: boost\bind\bind.hpp:249: 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 *&'

thanks,

Jens Weller

Adding the full error message from compiler output here:


D:\cpp\libraries\boost_1_63_0\boost/bind/bind.hpp(249): 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 *&'
D:\cpp\libraries\boost_1_63_0\boost/bind/bind.hpp(1306): note: see reference to function template instantiation 'R *boost::_bi::list1<boost::arg<1>>::operator ()<Panel*,F,boost::_bi::rrlist1<A1>>(boost::_bi::type<Panel *>,F &,A &,long)' being compiled
        with
        [
            R=Panel *,
            F=boost::factory<Panel *,void,boost::factory_alloc_for_pointee_and_deleter>,
            A1=Widget *,
            A=boost::_bi::rrlist1<Widget *>
        ]
D:\cpp\libraries\boost_1_63_0\boost/bind/bind.hpp(1306): note: see reference to function template instantiation 'R *boost::_bi::list1<boost::arg<1>>::operator ()<Panel*,F,boost::_bi::rrlist1<A1>>(boost::_bi::type<Panel *>,F &,A &,long)' being compiled
        with
        [
            R=Panel *,
            F=boost::factory<Panel *,void,boost::factory_alloc_for_pointee_and_deleter>,
            A1=Widget *,
            A=boost::_bi::rrlist1<Widget *>
        ]
D:\cpp\libraries\boost_1_63_0\boost/function/function_template.hpp(138): note: see reference to function template instantiation 'Panel *boost::_bi::bind_t<boost::_bi::unspecified,boost::factory<Panel *,void,boost::factory_alloc_for_pointee_and_deleter>,boost::_bi::list1<boost::arg<1>>>::operator ()<T>(A1 &&)' being compiled
        with
        [
            T=Widget *,
            A1=Widget *
        ]
D:\cpp\libraries\boost_1_63_0\boost/function/function_template.hpp(138): note: see reference to function template instantiation 'Panel *boost::_bi::bind_t<boost::_bi::unspecified,boost::factory<Panel *,void,boost::factory_alloc_for_pointee_and_deleter>,boost::_bi::list1<boost::arg<1>>>::operator ()<T>(A1 &&)' being compiled
        with
        [
            T=Widget *,
            A1=Widget *
        ]
D:\cpp\libraries\boost_1_63_0\boost/function/function_template.hpp(132): note: while compiling class template member function 'Widget *boost::detail::function::function_obj_invoker1<FunctionObj,R,T0>::invoke(boost::detail::function::function_buffer &,T0)'
        with
        [
            FunctionObj=boost::_bi::bind_t<boost::_bi::unspecified,boost::factory<Panel *,void,boost::factory_alloc_for_pointee_and_deleter>,boost::_bi::list1<boost::arg<1>>>,
            R=Widget *,
            T0=Widget *
        ]
D:\cpp\libraries\boost_1_63_0\boost/function/function_template.hpp(936): note: see reference to function template instantiation 'Widget *boost::detail::function::function_obj_invoker1<FunctionObj,R,T0>::invoke(boost::detail::function::function_buffer &,T0)' being compiled
        with
        [
            FunctionObj=boost::_bi::bind_t<boost::_bi::unspecified,boost::factory<Panel *,void,boost::factory_alloc_for_pointee_and_deleter>,boost::_bi::list1<boost::arg<1>>>,
            R=Widget *,
            T0=Widget *
        ]
D:\cpp\libraries\boost_1_63_0\boost/function/function_template.hpp(936): note: see reference to class template instantiation 'boost::detail::function::function_obj_invoker1<FunctionObj,R,T0>' being compiled
        with
        [
            FunctionObj=boost::_bi::bind_t<boost::_bi::unspecified,boost::factory<Panel *,void,boost::factory_alloc_for_pointee_and_deleter>,boost::_bi::list1<boost::arg<1>>>,
            R=Widget *,
            T0=Widget *
        ]
D:\cpp\libraries\boost_1_63_0\boost/function/function_template.hpp(727): note: see reference to function template instantiation 'void boost::function1<R,T0>::assign_to<Functor>(Functor)' being compiled
        with
        [
            R=Widget *,
            T0=Widget *,
            Functor=boost::_bi::bind_t<boost::_bi::unspecified,boost::factory<Panel *,void,boost::factory_alloc_for_pointee_and_deleter>,boost::_bi::list1<boost::arg<1>>>
        ]
D:\cpp\libraries\boost_1_63_0\boost/function/function_template.hpp(727): note: see reference to function template instantiation 'void boost::function1<R,T0>::assign_to<Functor>(Functor)' being compiled
        with
        [
            R=Widget *,
            T0=Widget *,
            Functor=boost::_bi::bind_t<boost::_bi::unspecified,boost::factory<Panel *,void,boost::factory_alloc_for_pointee_and_deleter>,boost::_bi::list1<boost::arg<1>>>
        ]
D:\cpp\libraries\boost_1_63_0\boost/function/function_template.hpp(1073): note: see reference to function template instantiation 'boost::function1<R,T0>::function1<Functor>(Functor,int)' being compiled
        with
        [
            R=Widget *,
            T0=Widget *,
            Functor=boost::_bi::bind_t<boost::_bi::unspecified,boost::factory<Panel *,void,boost::factory_alloc_for_pointee_and_deleter>,boost::_bi::list1<boost::arg<1>>>
        ]
D:\cpp\libraries\boost_1_63_0\boost/function/function_template.hpp(1072): note: see reference to function template instantiation 'boost::function1<R,T0>::function1<Functor>(Functor,int)' being compiled
        with
        [
            R=Widget *,
            T0=Widget *,
            Functor=boost::_bi::bind_t<boost::_bi::unspecified,boost::factory<Panel *,void,boost::factory_alloc_for_pointee_and_deleter>,boost::_bi::list1<boost::arg<1>>>
        ]
..\msvctestbed\main.cpp(19): note: see reference to function template instantiation 'boost::function<Widget *(Widget *)>::function<boost::_bi::bind_t<boost::_bi::unspecified,boost::factory<Panel *,void,boost::factory_alloc_for_pointee_and_deleter>,boost::_bi::list1<boost::arg<1>>>>(Functor,int)' being compiled
        with
        [
            Functor=boost::_bi::bind_t<boost::_bi::unspecified,boost::factory<Panel *,void,boost::factory_alloc_for_pointee_and_deleter>,boost::_bi::list1<boost::arg<1>>>
        ]
..\msvctestbed\main.cpp(19): note: see reference to function template instantiation 'boost::function<Widget *(Widget *)>::function<boost::_bi::bind_t<boost::_bi::unspecified,boost::factory<Panel *,void,boost::factory_alloc_for_pointee_and_deleter>,boost::_bi::list1<boost::arg<1>>>>(Functor,int)' being compiled
        with
        [
            Functor=boost::_bi::bind_t<boost::_bi::unspecified,boost::factory<Panel *,void,boost::factory_alloc_for_pointee_and_deleter>,boost::_bi::list1<boost::arg<1>>>
        ]

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [factory][bind] C2664 with MSVC 2015 & 1.63

Peter Dimov-2
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://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [factory][bind] C2664 with MSVC 2015 & 1.63

Jens Weller


> Gesendet: Mittwoch, 01. Februar 2017 um 20:34 Uhr
> Von: "Peter Dimov" <[hidden email]>
> An: [hidden email]
> 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://lists.boost.org/mailman/listinfo.cgi/boost
>

Yes, that fixes this indeed. Didn't know about forward_adapter.

thanks,

Jens Weller

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost