У меня проблема при вызове вложенных выражений 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
? Сначала я подумал, что проблема связана с нетерпеливой оценкой выражений привязки, продиктованных стандартом С++ 11 (см. здесь), но это не было бы проблемой здесь, не так ли?
libc++
). Я бы посоветовал обновиться до более новой версии. - person Mankarse   schedule 20.08.2012f
вfix1
, поэтому я подозреваю, что что-то еще является подделкой. - person Xeo   schedule 20.08.2012