【问题标题】:Chained invocation of C++11 std::bind doesn't workC++11 std::bind 的链式调用不起作用
【发布时间】:2012-08-20 09:48:25
【问题描述】:

我在调用嵌套的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),但这不会是问题,不是吗?

【问题讨论】:

  • 为我工作(使用libc++)。我建议更新到较新的版本。
  • 你还在fix1中复制了f,所以我怀疑其他东西是假的。
  • 你用哪个g++版本编译?
  • 投票结束,因为问题没有解决方案。

标签: c++ c++11 boost-bind libc++


【解决方案1】:

标准规定可以使用std::bind 包装任何可调用对象,包括由先前调用std::bind 生成的调用对象。您的问题是由于您正在使用的标准库的实现存在缺陷引起的,解决方案是升级,或者如果此错误仍未修复,则切换到不同的实现。

【讨论】:

    猜你喜欢
    • 2012-05-20
    • 1970-01-01
    • 1970-01-01
    • 2021-11-23
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多