VC2013:来自绑定的函数未编译

2021-12-22 00:00:00 visual-c++ c++ c++11 visual-studio-2013

这是一个简短的示例:

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);
    }
};

代码在 VC2010 下编译良好.在 VC2013 下,我不断收到大量错误.

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

怎么了?这能以某种方式修复吗?

What's wrong? Can this be fixed somehow?

以下是错误:

1>c:program files (x86)microsoft visual studio 12.0vcinclude	uple(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<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(385) : see reference to function template instantiation 'void std::_Func_class<_Ret,A &>::_Reset_alloc<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> &>&,std::allocator<std::_Func_class<_Ret,A &>>>(_Fty,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=bool
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>  ,            _Alloc=std::allocator<std::_Func_class<bool,A &>>
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(385) : see reference to function template instantiation 'void std::_Func_class<_Ret,A &>::_Reset_alloc<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> &>&,std::allocator<std::_Func_class<_Ret,A &>>>(_Fty,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=bool
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>  ,            _Alloc=std::allocator<std::_Func_class<bool,A &>>
1>          ]
1>          c:program files (x86)microsoft visual studio 12.0vcincludefunctional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,A &>::_Reset<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> &>&>(_Fty)' being compiled
1>          with
1>          [
1>              _Ret=bool
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(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,A &>::_Reset<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> &>&>(_Fty)' being compiled
1>          with
1>          [
1>              _Ret=bool
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:worksource	est.cpp(29) : see reference to function template instantiation 'std::function<bool (A &)>::function<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> &>&>(_Fx)' being compiled
1>          with
1>          [
1>              _Fx=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:worksource	est.cpp(29) : see reference to function template instantiation 'std::function<bool (A &)>::function<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> &>&>(_Fx)' being compiled
1>          with
1>          [
1>              _Fx=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(900): error C2039: 'type' : is not a member of 'std::tuple_element<1,_Ftuple>'
1>          with
1>          [
1>              _Ftuple=std::tuple<A &>
1>          ]
1>c:program files (x86)microsoft visual studio 12.0vcincludefunctional(900): error C2146: syntax error : missing ',' before identifier 'type'
1>c:program files (x86)microsoft visual studio 12.0vcincludefunctional(900): error C2065: 'type' : undeclared identifier
1>c:program files (x86)microsoft visual studio 12.0vcincludefunctional(900): error C2977: 'std::add_reference' : too many template arguments
1>          c:program files (x86)microsoft visual studio 12.0vcinclude	ype_traits(180) : see declaration of 'std::add_reference'
1>c:program files (x86)microsoft visual studio 12.0vcincludefunctional(900): error C2955: 'std::add_reference' : use of class template requires template argument list
1>          c:program files (x86)microsoft visual studio 12.0vcinclude	ype_traits(180) : see declaration of 'std::add_reference'

c:worksource est.cpp(29) - 是我的源文件(问题在这里"注释所在的位置).

c:worksource est.cpp(29) - is my source file (where the "PROBLEM IS HERE" comment is).

推荐答案

我通常会引用标准,但这里的标准语特别密集,所以我只会解释发生了什么.

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

std::bind 在传递要绑定的参数时会做一些特别的事情,如果该参数是先前调用 std::bind 返回的函数对象.假设你这样做:

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);

然后调用g(a)大致相当于

bar(foo(a), a)

而不是

bar(f, a)

演示.

也就是说,如果您将 bind 返回的内容作为要绑定的参数传递给 bind,那么最终会传递给您正在绑定的函数的是调用该绑定表达式的结果.这是一种组合.

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.

但是,在您的代码中,您实际上不希望组合发生.(当我尝试在 A 上调用您的 fn_gg 时,这种组合导致 g++ 发出 320 多行错误.幸好,使用 libc++ 的 Clang 仅打印了 10 行.)您希望 fn_g 被视为普通参数.所以你可以把它包装在一个 std::function:

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);

相关文章