1

我正在尝试创建一个函数,它将可变参数 lambda 工厂方法绑定到一个不带参数的函数。我不确定 VC 支持(使用 VS2012 和 2012 年 11 月的 CTP)是否不完全存在,或者(更有可能)我做错了。我对可变参数模板的工作不多,因此将不胜感激。

template <typename T, typename...Args>
std::function<T*()> MakeFactoryMethod(Args&&... args)
{
    return std::bind([](Args&&... args2)
        {
            return new T(std::forward<Args>(args2)...);
        },
        std::forward<Args>(args)...);
}

...

auto test = MakeFactoryMethod<SomeClassWithSingleIntConstructor>(5);

我从编译器收到一长串错误。看起来 VC 标准库本身还没有使用可变参数模板。

1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xrefwrap(431): error C2440: 'return' : cannot convert from 'std::_Do_call_ret<false,_Ret,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,std::tuple<int,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>,std::tuple<std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>>::type' to 'SomeClassWithSingleIntConstructor *'
1>          with
1>          [
1>              _Ret=void
1>          ]
1>          Expressions of type void cannot be converted to other types
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\functional(239) : see reference to function template instantiation '_Ret std::_Callable_obj<std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,_Ty,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>,false>::_ApplyX<_Rx>(void)' being compiled
1>          with
1>          [
1>              _Ret=SomeClassWithSingleIntConstructor *
1>  ,            _Ty=int
1>  ,            _Rx=SomeClassWithSingleIntConstructor *
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\functional(239) : see reference to function template instantiation '_Ret std::_Callable_obj<std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,_Ty,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>,false>::_ApplyX<_Rx>(void)' being compiled
1>          with
1>          [
1>              _Ret=SomeClassWithSingleIntConstructor *
1>  ,            _Ty=int
1>  ,            _Rx=SomeClassWithSingleIntConstructor *
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\functional(239) : while compiling class template member function 'SomeClassWithSingleIntConstructor std::_Func_impl<_MyWrapper,_Alloc,_Ret,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::_Do_call(void)'
1>          with
1>          [
1>              _Alloc=std::allocator<std::_Func_class<SomeClassWithSingleIntConstructor *,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>>
1>  ,            _Ret=SomeClassWithSingleIntConstructor *
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\functional(514) : see reference to class template instantiation 'std::_Func_impl<_MyWrapper,_Alloc,_Ret,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>' being compiled
1>          with
1>          [
1>              _Alloc=std::allocator<std::_Func_class<SomeClassWithSingleIntConstructor *,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>>
1>  ,            _Ret=SomeClassWithSingleIntConstructor *
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\functional(514) : see reference to function template instantiation 'void std::_Func_class<_Ret,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::_Do_alloc<_Myimpl,_Ty,_Alloc>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=SomeClassWithSingleIntConstructor *
1>  ,            _Ty=std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,int,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>
1>  ,            _Alloc=std::allocator<std::_Func_class<SomeClassWithSingleIntConstructor *,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>>
1>  ,            _Fty=std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,int,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\functional(514) : see reference to function template instantiation 'void std::_Func_class<_Ret,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::_Do_alloc<_Myimpl,_Ty,_Alloc>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=SomeClassWithSingleIntConstructor *
1>  ,            _Ty=std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,int,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>
1>  ,            _Alloc=std::allocator<std::_Func_class<SomeClassWithSingleIntConstructor *,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>>
1>  ,            _Fty=std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,int,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\functional(514) : see reference to function template instantiation 'void std::_Func_class<_Ret,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::_Reset_alloc<_Ty,std::allocator<std::_Func_class<_Ret,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>>>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=SomeClassWithSingleIntConstructor *
1>  ,            _Ty=std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,int,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>
1>  ,            _Fty=std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,int,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>
1>  ,            _Alloc=std::allocator<std::_Func_class<SomeClassWithSingleIntConstructor *,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\functional(514) : see reference to function template instantiation 'void std::_Func_class<_Ret,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::_Reset_alloc<_Ty,std::allocator<std::_Func_class<_Ret,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>>>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=SomeClassWithSingleIntConstructor *
1>  ,            _Ty=std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,int,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>
1>  ,            _Fty=std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,int,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>
1>  ,            _Alloc=std::allocator<std::_Func_class<SomeClassWithSingleIntConstructor *,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\functional(675) : see reference to function template instantiation 'void std::_Func_class<_Ret,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::_Reset<_Ty>(_Fty &&)' being compiled
1>          with
1>          [
1>              _Ret=SomeClassWithSingleIntConstructor *
1>  ,            _Ty=std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,int,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>
1>  ,            _Fty=std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,int,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\functional(675) : see reference to function template instantiation 'void std::_Func_class<_Ret,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::_Reset<_Ty>(_Fty &&)' being compiled
1>          with
1>          [
1>              _Ret=SomeClassWithSingleIntConstructor *
1>  ,            _Ty=std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,int,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>
1>  ,            _Fty=std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,int,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>
1>          ]
1>          c:\code\configurabletestserver\application.cpp(121) : see reference to function template instantiation 'std::function<SomeClassWithSingleIntConstructor *(void)>::function<std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,_Ty,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>>(_Fx &&)' being compiled
1>          with
1>          [
1>              _Ty=int
1>  ,            _Fx=std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,int,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>
1>          ]
1>          c:\code\configurabletestserver\application.cpp(121) : see reference to function template instantiation 'std::function<SomeClassWithSingleIntConstructor *(void)>::function<std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,_Ty,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>>(_Fx &&)' being compiled
1>          with
1>          [
1>              _Ty=int
1>  ,            _Fx=std::_Bind<false,void,MakeFactoryMethod::<lambda_eabc5b7f0a2cea764c71ce16901cde81>,int,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>
1>          ]
1>          c:\code\configurabletestserver\application.cpp(139) : see reference to function template instantiation 'std::function<SomeClassWithSingleIntConstructor *(void)> MakeFactoryMethod<SomeClassWithSingleIntConstructor,int>(int &&)' being compiled

谢谢。

4

2 回答 2

3

在我看来,您似乎试图使其复杂化。为什么要通过 RHR 捕获它们,然后将它们作为完美前锋传递——这意味着你将捕获任何临时的作为临时的——当你要从中制作一个仿函数时?这意味着您必须将副本等传递到每个新调用中以确保对象仍然存在。

template <typename T, typename...Args>
std::function<T*()> MakeFactoryMethod(Args&&... args)
{
    return [=]()
        {
            return new T(args...);
        }
}

当您确实必须制作副本时,只需在 lambda 创建中制作一个副本并完成它。

错误消息非常令人困惑,但对我来说,用右手引用制作 lambda 似乎是设计错误的,所以我对错误消息并不太在意。

于 2013-04-02T08:51:17.190 回答
0

你的 lambda 返回 void

应该

template <typename T, typename...Args>
std::function<T*()> MakeFactoryMethod(Args&&... args)
{
    return std::bind([](Args&&... args2) -> T*
        {
            return new T(std::forward<Args>(args2)...);
        },
        std::forward<Args>(args)...);
}
于 2013-04-02T08:16:14.690 回答