c++ - 从模板中绑定(bind)模板函数

标签 c++ templates c++11 bind

接续 this question .我正在尝试绑定(bind)一个给定的函数,该函数返回除 void 之外的其他内容,以便稍后能够简单地调用 f() 。但是,以下代码无法在 GCC 4.4 上编译。它在 VS 2010 上编译,但生成的程序崩溃。

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 产生了这个疯狂的消息:

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 = ]’

我对内部 STL 工作原理的了解不足,无法从中做出任何东西。

但是在实验过程中我发现如果我删除第二个 std::bind从这样的 registerFunc 模板调用:

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

代码在 VS 和 GCC 中都按预期工作。所以我的结论是问题出在调用std::bind(_hideRet<RetType>, ...)从模板函数中。问题是为什么这是个问题?更重要的是如何解决这个问题?

最佳答案

这绝对是惊人的,但是替换:

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

在 Visual Studio 2010 下按预期运行(这实际上是您将第二个 bind 移出 registerFunc 所做的)。我正在尝试理解它,但在那之前,这似乎是解决您的问题的方法,

关于c++ - 从模板中绑定(bind)模板函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4484306/

相关文章:

C++ 性能 : using declaratives Vs using declarations Vs using names directly from the library

c++ - 在 C++ 中使用自定义新建/删除和 Qt 的段错误

c++ - 与库相关的错误

c++ - 在虚拟成员函数上使用模板的替代方法是什么?

c++11 - boost 日志 : using c++11 lambda expression to filter severity level

c++ - 找不到 boost_process cmake find_package

c++ - 如何在 C++ 函数模板中指定默认的非模板参数初始值设定项?

c++ - 模板类方法不会导致错误——这是标准的一部分吗?

C++11。是否可以这样做 : string foo = cout << (. 00000023)*(.00000023) << endl; -精确

c++ - C++ 中的运算符组合