将std :: bind的结果传递给std :: function的“重载" [英] Passing result of std::bind to std::function "overloads"

查看:97
本文介绍了将std :: bind的结果传递给std :: function的“重载"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到的问题类似于将不同的lambda传递给c ++中的函数模板,但现在使用由 std :: bind 而不是lambda创建的包装器.

I have problem similar to Passing different lambdas to function template in c++ but now with wrappers created by std::bind instead of lambdas.

我有两个方法 Add 的重载,它们采用不同形式的 std :: function :

I have two overloads of method Add that take different forms of std::function:

template<typename T>
struct Value
{
    T value;
};

template <typename T>
void Add(Value<T> &value, function<bool()> predicate)
{
}

template <typename T>
void Add(Value<T> &value, block_deduction<function<bool(const Value<T> &)>> predicate)
{
}

这现在可以在lambdas上正常工作,但在与 std :: bind :

This now works fine with lambdas but fails with functors bound with std::bind:

struct Predicates
{
    bool Predicate0() { return true; }
    bool Predicate1(const Value<int> &) { return true; }
};

Predicates p;
Add(i, std::bind(&Predicates::Predicate0, &p));

失败

错误C2668:添加":对重载函数的模棱两可的调用

error C2668: 'Add': ambiguous call to overloaded function

Add(i, std::bind(&Predicates::Predicate1, &p, _1));

使用静态断言失败(Visual C ++ 2015,更新3):

fails with static assert (Visual C++ 2015, Update 3):

元组索引超出范围

tuple index out of bounds

是否有一种方法可以使其同时适用于lambda和绑定函子?我会考虑使用SFINAE基于 is_bindable_expression 启用单个重载并检查参数类型,但是我无法将其放在一起.

Is there a way to make it work both with lambdas and bound functors? I would think of using SFINAE to enable the individual overload based on is_bindable_expression and checking the argument type but I'm failing to put it together.

推荐答案

使用 std :: bind 停止.这是一堆乱七八糟的随机特征和怪癖.

Stop using std::bind. It is a mess of random features and quirks.

今天的怪癖是 std :: bind 将接受无限数量的参数,并丢弃任何多余的参数.明天您可能会遇到这样的事实,将 std :: bind 结果传递给 std :: bind 确实很奇怪.

Todays quirk is that std::bind will accept an unlimited number of arguments and discard any extra ones. Tomorrow you might run into the fact that passing std::bind result to std::bind does strange magic.

std :: bind 移植到了 boost 上,同时将lambdas添加到了该语言中.Lambda以几乎清晰的语法解决了 bind 所做的几乎所有问题,并且没有 bind 所做的怪癖,尤其是当 auto 时发布了C ++ 14代码> lambdas可用.(大多数C ++ 11编译器还支持 auto lambda).

std::bind was ported over to boost at the same time lambdas where added to the language. Lambdas solve almost every problem bind does in just as clear syntax and fails to have the myraid of quirks bind does, especially post C++14 when auto lambdas are available. (Most C++11 compilers also supported auto lambda).

您可以编写函数,以便在两个函数均适用时,它们是首选的重载.但是这样做会给您的界面增加很多噪音,在这种情况下,您想要该首选项的唯一原因是因为 std :: bind 做的是愚蠢的事情.

You can write functions so that one or the other is the preferred overload when they both apply. But doing so adds a pile of noise to your interface, and in this case about the only reason why you'd want that preference is because std::bind is doing something stupid.

围绕 std 库的设计欠佳进行设计是不值得的.只需停止使用 std 库中设计欠佳的位,或者在使用时强制转换即可.

Engineering around a poorly designed bit of std library is not worth it. Simply stop using that poorly designed bit of std library, or at point of use cast explicitly.

如果失败,请执行以下操作:

Failing that, do this:

template <class T, class F,
  std::enable_if_t<
    std::is_convertible<
      std::result_of_t<std::decay_t<F> const&(Value<T> const&)>,
      bool
    >{}, int
  > = 0
>
void Add(Value<T> &value, F&& f)
{
  // do pass f Value<T>
}
template <class T, class F,
  std::enable_if_t<
    !std::is_convertible<
      std::result_of_t<std::decay_t<F> const&(Value<T> const&)>,
      bool
    >{}
    && std::is_convertible<
      std::result_of_t<std::decay_t<F> const&()>,
      bool
    >{}, int
  > = 0
>
void Add(Value<T> &value, F&& f)
{
  // do not pass f Value<T>
}

我们在其中要使用两个重载中的哪个重载时抛出一些讨厌的SFINAE检测,并且明确地更喜欢一个.

where we throw some nasty SFINAE detection on which of the two overloads you want to use, and explicitly prefer one.

这不值得.

这篇关于将std :: bind的结果传递给std :: function的“重载"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆