Continued from this question . I am trying to bind a given function that returns something other than empty, in order to be able to just call f () later. However, the following code does not compile in GCC 4.4. It compiles on VS 2010, but the resulting program crashes.
template<typename RetType> void _hideRet(std::function<RetType ()> func, RetType * ret) { *ret = func(); } template<typename FuncType, typename RetType, typename ParamType> std::function<void ()> registerFunc(FuncType func, RetType * ret, ParamType param) { auto f = std::bind(func, std::forward<ParamType>(param)); return std::bind(_hideRet<RetType>, f, ret); } int myFunction(std::string text) { std::cout << text << std::endl; return 42; } int main() { int ret = 0; auto f = registerFunc(myFunction, &ret, "text"); f(); std::cout << ret << std::endl; return 0; }
GCC creates this crazy message:
In file included from /usr/include/c++/4.4/functional:70, from func.cpp:4: /usr/include/c++/4.4/tr1_impl/functional: In member function 'typename std::result_of<_Functor(typename std::result_of<std::_Mu<_Bound_args, std::is_bind_expression::value, (std::is_placeholder::value > 0)>(_Bound_args, std::tuple<_UElements ...>)>::type ...)>::type std::_Bind<_Functor(_Bound_args ...)>::__call(const std::tuple<_UElements ...>&, std::_Index_tuple<_Indexes ...>) [with _Args = , int ..._Indexes = 0, 1, _Functor = void (*)(std::function<int()>, int*), _Bound_args = std::_Bind<int (*(const char*))(std::string)>, int*]': /usr/include/c++/4.4/tr1_impl/functional:1191: instantiated from 'typename std::result_of<_Functor(typename std::result_of<std::_Mu<_Bound_args, std::is_bind_expression::value, (std::is_placeholder::value > 0)>(_Bound_args, std::tuple<_UElements ...>)>::type ...)>::type std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args& ...) [with _Args = , _Functor = void (*)(std::function<int()>, int*), _Bound_args = std::_Bind<int (*(const char*))(std::string)>, int*]' /usr/include/c++/4.4/tr1_impl/functional:1668: instantiated from 'static void std::_Function_handler<void(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Functor = std::_Bind<void (*(std::_Bind<int (*(const char*))(std::string)>, int*))(std::function<int()>, int*)>, _ArgTypes = ]' /usr/include/c++/4.4/tr1_impl/functional:2005: instantiated from 'std::function<_Res(_ArgTypes ...)>::function(_Functor, typename __gnu_cxx::__enable_if<(! std::is_integral::value), std::function<_Res(_ArgTypes ...)>::_Useless>::__type) [with _Functor = std::_Bind<void (*(std::_Bind<int (*(const char*))(std::string)>, int*))(std::function<int()>, int*)>, _Res = void, _ArgTypes = ]' func.cpp:16: instantiated from 'std::function<void()> registerFunc(FuncType, RetType*, ParamType) [with FuncType = int (*)(std::string), RetType = int, ParamType = const char*]' func.cpp:28: instantiated from here /usr/include/c++/4.4/tr1_impl/functional:1137: error: invalid conversion from 'int' to 'std::_M_clear_type*' /usr/include/c++/4.4/tr1_impl/functional:1137: error: initializing argument 1 of 'std::function<_Res(_ArgTypes ...)>::function(std::_M_clear_type*) [with _Res = int, _ArgTypes = ]'
I do not have enough knowledge about the internal actions of STL to make any of this.
However, while experimenting, I found that if I remove the second call to std::bind from the registerFunc template as follows:
template<typename FuncType, typename RetType, typename ParamType> std::function<RetType ()> registerFunc(FuncType func, RetType *, ParamType param) { return std::bind(func, std::forward<ParamType>(param)); }
The code works as expected in both VS and GCC. So I came to the conclusion that the problem is calling std::bind(_hideRet<RetType>, ...) from the template function. The question is why is this a problem? And more importantly, how to fix it?