【问题标题】:chained std::bind compile error with VS2015VS2015 的链式 std::bind 编译错误
【发布时间】:2017-07-01 13:44:43
【问题描述】:

我正在使用 VS2015,我在玩 std::functionstd::bind 我发现了一个奇怪的错误。

我有一个 2 链式绑定操作:

int main()
{


    auto func1 = [](int i) -> int {
        return i + 1;
    };

    auto func2 = [](float f, function<int(int)>&& func) -> float {
        return f + func(f);
    };


    auto func2_instance = std::bind(func2, std::placeholders::_1, func1);

    cout << func2_instance(0.2) << endl;

    auto func3 = [](double d, function<float(float)>&& func)->double {
        return d + func(d);
    };
   //doesn't work
auto func3_instance = std::bind(func3, std::placeholders::_1, std::move(func2_instance));
  //works
auto func3_instance = std::bind(func3, std::placeholders::_1, [funcmv = std::move(func2_instance)](float a)->float{
        return funcmv(a);
    });

    func3_instance(0.2);


}

我得到的错误与func3_instance(0.2) 行有关

D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\type_traits(1468): error C2893: Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)'

你能帮忙吗?我想念与std::bind 相关的内容?

提前致谢。

【问题讨论】:

  • 也许您尝试将std::bind 更改为某个 lambda 表达式?请...使用std::
  • 嵌套绑定表达式被急切求值;请参阅std::is_bind_expressionboost::protect 了解详情。
  • @21koizyd 我不明白你的意思!
  • @ildjarn 我尝试 ` namespace std { template struct is_bind_expression : public true_type {}; }` 同样的错误。我认为问题来自func3_instance 调用。好像找不到合适的功能。
  • bind 的参数是另一个 bind 调用的行为有点违反直觉。 func3_instance(x) 并不意味着 func3(x, func2_instance) - 它意味着 func3(x, func2_instance(x))。一种思考方式是嵌套的bind 表达式与外部bind 共享占位符,并且它们同时被替换。在您的示例中,您实际上有 bind(func3, _1, bind(func2, _1, func1)) - _1 的两个实例同时被替换,它们不是独立的。

标签: c++11 c++14 std-function stdbind


【解决方案1】:

如果添加代码,从这里窃取: Why is there no std::protect?

template<typename T>
struct protect_wrapper : T
{
    protect_wrapper(const T& t) : T(t) {}
    protect_wrapper(T&& t) : T(std::move(t)) {}
};

template<typename T>
typename std::enable_if< !std::is_bind_expression< typename std::decay<T>::type >::value,
    T&& >::type
protect(T&& t)
{
    return std::forward<T>(t);
}

template<typename T>
typename std::enable_if< std::is_bind_expression< typename std::decay<T>::type >::value,
    protect_wrapper<typename std::decay<T>::type > >::type
protect(T&& t)
{
    return protect_wrapper<typename std::decay<T>::type >(std::forward<T>(t));
}

并将您的行修改为:

auto func3_instance = std::bind(func3, std::placeholders::_1, protect( func2_instance));

代码有效(对我来说)。

【讨论】:

  • 我喜欢这个答案,但如果有@IgorTandetnik 对实际发生的事情的解释会更好。
  • @rex:是的,会的。但我不想在我的答案中复制同事的答案……如果伊戈尔喜欢他,欢迎在我的答案中添加评论。正如您已经做过的那样,您的评论将指向解释......
  • 感谢@Klaus 你的template&lt;&gt; protect() 函数解决了这个问题。即使我真的不明白我仍在学习的原因。还std::ref 解决了这个问题。正如我从您过去的链接中看到的那样,std::ref 可以很好地替代protectfunction,除非它不接受右值和右值引用。
猜你喜欢
  • 2016-11-13
  • 1970-01-01
  • 2012-04-29
  • 1970-01-01
  • 1970-01-01
  • 2013-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多