调用嵌套的std::bind
表达式时遇到问题。以下代码演示了此问题。它无法使用libc ++进行编译,但可以使用boost:
#define BOOST 0
#if BOOST
#include <boost/function.hpp>
#include <boost/bind.hpp>
using boost::function;
using boost::bind;
#else
#include <functional>
using std::function;
using std::bind;
using std::placeholders::_1;
#endif
int sum(int a, int b) { return a+b; }
// works
template <typename F>
int yeah(F f, int c)
{
return f(c);
}
// breaks with libc++
template <typename F>
int nope(F f, int c)
{
return bind(f, c)();
}
// fixes the problem
template <typename F>
int fix1(F f, int c)
{
function<int(int)> g = f;
return bind(g, c)();
}
template <typename F>
class protect_t
{
public:
typedef typename F::result_type result_type;
explicit protect_t(F f): f_(f) {}
template <typename... Args>
result_type operator()(Args&&... args)
{
return f_(std::forward<Args>(args)...);
}
private:
F f_;
};
template <typename F>
protect_t<F> protect(F f)
{
return protect_t<F>(f);
}
// compilation fails with libc++
template <typename F>
int fix2(F f, int c)
{
return bind(protect(f), c)();
// F copy(f); // fails due to this!
}
#include <iostream>
int main()
{
std::cout << yeah(bind(sum, _1, 4), 5) << std::endl; // works
std::cout << nope(bind(sum, _1, 4), 5) << std::endl; // breaks
std::cout << fix1(bind(sum, _1, 4), 5) << std::endl; // fixes
std::cout << fix2(bind(sum, _1, 4), 5) << std::endl; // doesn't compile
}
将绑定表达式包装在std::function
(请参阅fix1
)可以解决问题,尽管由于运行时多态禁用内联而牺牲了速度(尽管没有测量它)。
在protect_t
中包装绑定表达式(请参阅fix2
)的灵感来自boost::protect
,但是,由于绑定表达式不可复制,因此使用libc ++进行编译失败。这让我想知道为什么将它们包装在std::function
中仍然适用。
知道如何解决这个问题吗?无论如何,std::bind
还有什么问题?首先,我认为这个问题与C ++ 11标准所规定的绑定表达式的急切评估有关(参见here),但这不是问题,是吗?
答案 0 :(得分:0)
标准规定任何可调用的内容都可以使用std::bind
进行包装,包括前一次调用std::bind
所产生的调用。您的问题是由于您正在使用的标准库的实现不足引起的,解决方案是升级,或者如果仍然修复此错误,则切换到不同的实现。