Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
97 views
in Technique[技术] by (71.8m points)

c++ - VC2013: function from bind not compiling

Here is a short sample:

class A {};

class S {};

class B
{
public:
    typedef std::function <bool (A& retVal)> property_getter_t;
    typedef std::function<bool (B* /*this*/, const std::shared_ptr<S>&, A& retVal)> SettingsPropGetter;

    void DefineSettingsProperty(const std::wstring& name, const SettingsPropGetter& getter)
    {
        auto fn_g = std::bind(getter, this, std::placeholders::_1, std::placeholders::_2);
        auto fn_gg = std::bind(&B::GetterHandler, this, fn_g, std::placeholders::_1);

        property_getter_t x = fn_gg;  // PROBLEM IS HERE
    }

    bool GetterHandler(const std::function<bool (const std::shared_ptr<S>&, A&)>& getter, A& a)
    {
        std::shared_ptr <S> s;
        return getter (s, a);
    }
};

The code compiles fine under VC2010. Under VC2013 I keep getting a huge pack of errors.

What's wrong? Can this be fixed somehow?

Here are the errors:

1>c:program files (x86)microsoft visual studio 12.0vcincludeuple(540): error C2504: 'std::tuple_element<0,std::tuple<>>' : base class undefined
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(900) : see reference to class template instantiation 'std::tuple_element<1,_Ftuple>' being compiled
1>          with
1>          [
1>              _Ftuple=std::tuple<A &>
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(946) : see reference to class template instantiation 'std::_Fixarg_ret_base<_Placeholder,_Funx,std::_Ph<2>,_Ftuple>' being compiled
1>          with
1>          [
1>              _Funx=std::function<bool (B *,const std::shared_ptr<S> &,A &)>
1>  ,            _Ftuple=std::tuple<A &>
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(975) : see reference to class template instantiation 'std::_Fixarg_ret<_Funx,std::_Ph<2> &,_Ftuple>' being compiled
1>          with
1>          [
1>              _Funx=std::function<bool (B *,const std::shared_ptr<S> &,A &)>
1>  ,            _Ftuple=std::tuple<A &>
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludexrefwrap(58) : see reference to class template instantiation 'std::_Do_call_ret<false,_Ret,std::function<bool (B *,const std::shared_ptr<S> &,A &)>,std::tuple<B *,std::_Ph<1>,std::_Ph<2>>,std::tuple<A &>,std::_Arg_idx<0,1,2>>' being compiled
1>          with
1>          [
1>              _Ret=void
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludexrefwrap(118) : see reference to class template instantiation 'std::_Result_of<_Fty,A &>' being compiled
1>          with
1>          [
1>              _Fty=std::_Bind<false,void,const B::SettingsPropGetter &,B *const ,std::_Ph<1> &,std::_Ph<2> &>
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(914) : see reference to class template instantiation 'std::result_of<_Bind_t (A &)>' being compiled
1>          with
1>          [
1>              _Bind_t=std::_Bind<false,void,const B::SettingsPropGetter &,B *const ,std::_Ph<1> &,std::_Ph<2> &>
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(924) : see reference to class template instantiation 'std::_Call_ret<_Barg,std::tuple<A &>,std::_Arg_idx<0>>' being compiled
1>          with
1>          [
1>              _Barg=std::_Bind<false,void,const B::SettingsPropGetter &,B *const ,std::_Ph<1> &,std::_Ph<2> &>
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(946) : see reference to class template instantiation 'std::_Fixarg_ret_base<_Bind_expression,_Funx,std::_Bind<false,void,const B::SettingsPropGetter &,B *const ,std::_Ph<1> &,std::_Ph<2> &>,_Ftuple>' being compiled
1>          with
1>          [
1>              _Funx=std::_Pmf_wrap<bool (__thiscall B::* )(const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &),bool,B,const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &> &
1>  ,            _Ftuple=std::tuple<A &>
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(1148) : see reference to class template instantiation 'std::_Fixarg_ret<std::_Pmf_wrap<bool (__thiscall B::* )(const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &),bool,B,const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &> &,_Ty,std::tuple<A &>>' being compiled
1>          with
1>          [
1>              _Ty=std::_Bind<false,void,const B::SettingsPropGetter &,B *const ,std::_Ph<1> &,std::_Ph<2> &>
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(1137) : see reference to function template instantiation 'bool std::_Bind<true,bool,std::_Pmf_wrap<bool (__thiscall B::* )(const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &),bool,B,const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &>,B *const ,std::_Bind<false,void,const B::SettingsPropGetter &,B *const ,std::_Ph<1> &,std::_Ph<2> &> &,std::_Ph<1> &>::_Do_call<A,0,1,2>(std::tuple<A &>,std::_Arg_idx<0,1,2>)' being compiled
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(1137) : see reference to function template instantiation 'bool std::_Bind<true,bool,std::_Pmf_wrap<bool (__thiscall B::* )(const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &),bool,B,const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &>,B *const ,std::_Bind<false,void,const B::SettingsPropGetter &,B *const ,std::_Ph<1> &,std::_Ph<2> &> &,std::_Ph<1> &>::_Do_call<A,0,1,2>(std::tuple<A &>,std::_Arg_idx<0,1,2>)' being compiled
1>          c:program files (x86)microsoft visual studio 12.0vcincludexrefwrap(283) : see reference to function template instantiation 'bool std::_Bind<true,bool,std::_Pmf_wrap<bool (__thiscall B::* )(const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &),bool,B,const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &>,B *const ,std::_Bind<false,void,const B::SettingsPropGetter &,B *const ,std::_Ph<1> &,std::_Ph<2> &> &,std::_Ph<1> &>::operator ()<A&>(A &)' being compiled
1>          c:program files (x86)microsoft visual studio 12.0vcincludexrefwrap(283) : see reference to function template instantiation 'bool std::_Bind<true,bool,std::_Pmf_wrap<bool (__thiscall B::* )(const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &),bool,B,const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &>,B *const ,std::_Bind<false,void,const B::SettingsPropGetter &,B *const ,std::_Ph<1> &,std::_Ph<2> &> &,std::_Ph<1> &>::operator ()<A&>(A &)' being compiled
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(228) : see reference to function template instantiation '_Ret std::_Callable_obj<std::_Bind<true,_Ret,std::_Pmf_wrap<bool (__thiscall B::* )(const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &),bool,B,const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &>,B *const ,std::_Bind<false,void,const B::SettingsPropGetter &,B *const ,std::_Ph<1> &,std::_Ph<2> &> &,std::_Ph<1> &>,false>::_ApplyX<_Rx,A&>(A &)' being compiled
1>          with
1>          [
1>              _Ret=bool
1>  ,            _Rx=bool
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(228) : see reference to function template instantiation '_Ret std::_Callable_obj<std::_Bind<true,_Ret,std::_Pmf_wrap<bool (__thiscall B::* )(const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &),bool,B,const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &>,B *const ,std::_Bind<false,void,const B::SettingsPropGetter &,B *const ,std::_Ph<1> &,std::_Ph<2> &> &,std::_Ph<1> &>,false>::_ApplyX<_Rx,A&>(A &)' being compiled
1>          with
1>          [
1>              _Ret=bool
1>  ,            _Rx=bool
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(226) : while compiling class template member function 'bool std::_Func_impl<_MyWrapper,_Alloc,_Ret,A &>::_Do_call(A &)'
1>          with
1>          [
1>              _Alloc=std::allocator<std::_Func_class<bool,A &>>
1>  ,            _Ret=bool
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(495) : see reference to class template instantiation 'std::_Func_impl<_MyWrapper,_Alloc,_Ret,A &>' being compiled
1>          with
1>          [
1>              _Alloc=std::allocator<std::_Func_class<bool,A &>>
1>  ,            _Ret=bool
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(396) : see reference to function template instantiation 'void std::_Func_class<_Ret,A &>::_Do_alloc<_Myimpl,std::_Bind<true,_Ret,std::_Pmf_wrap<bool (__thiscall B::* )(const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &),bool,B,const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &>,B *const ,std::_Bind<false,void,const B::SettingsPropGetter &,B *const ,std::_Ph<1> &,std::_Ph<2> &> &,std::_Ph<1> &>&,_Alloc>(_Fty,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=bool
1>  ,            _Alloc=std::allocator<std::_Func_class<bool,A &>>
1>  ,            _Fty=std::_Bind<true,bool,std::_Pmf_wrap<bool (__thiscall B::* )(const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &),bool,B,const std::function<bool (const std::shared_ptr<S> &,A &)> &,A &>,B *const ,std::_Bind<false,void,const B::SettingsPropGetter &,B *const ,std::_Ph<1> &,std::_Ph<2> &> &,std::_Ph<1> &> &
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(396) : see reference to function template instantiation 'void std::_Func_class<_Ret,A &>::_Do_alloc<_Myimpl,std::_Bind<true,_Ret,std::_Pmf_wrap<boo

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I would normally quote the standard, but the standardese here is particularly dense, so I'll just explain what's happening.

std::bind does something special when you pass an argument to be bound if that argument is a function object returned by a previous call to std::bind. Suppose you do:

auto f = std::bind(foo, std::placeholders::_1);
auto g = std::bind(bar, f, std::placeholders::_1);

Then invoking g(a) is roughly equivalent to

bar(foo(a), a)

rather than

bar(f, a)

Demo.

That is, if you pass something returned by bind to bind as an argument to be bound, what's going to end up being passed to the function you are binding is the result of invoking that bind expression. It's a sort of composition.

However, in your code, you actually don't want the composition to take place. (This composition is what caused g++ to emit 320+ lines of errors when I tried to call your fn_gg on an A. Clang with libc++ printed only 10 lines, thankfully.) You want fn_g to be treated just like an ordinary argument. So you can wrap it in a std::function:

std::function<bool (const std::shared_ptr<S>&, A&)> fn_g = std::bind(getter, this, std::placeholders::_1, std::placeholders::_2);

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...