Binding a template function from a template

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)); } // in main auto tmp = registerFunc(myFunction, &ret, "text"); auto f = std::bind(_hideRet<int>, tmp, &ret); f(); 

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?

+4
source share
1 answer

This is absolutely awesome, but replacing:

 auto f = std::bind(func, std::forward<ParamType>(param)); return std::bind(_hideRet<RetType>, f, ret); 

:

 std::function<RetType ()> f = std::bind(func, std::forward<ParamType>(param)); return std::bind(_hideRet<RetType>, f, ret); 

in Visual Studio 2010 it works as expected (which, in essence, you did by moving the second bind from registerFunc ). I'm trying to figure this out, but until then this seems like a workaround for your problem,

+4
source

Source: https://habr.com/ru/post/1332681/


All Articles