将std :: bind的结果传递给std :: function“overloads”(Passing result of std::bind to std::function “overloads

编程入门 行业动态 更新时间:2024-10-26 16:32:41
将std :: bind的结果传递给std :: function“overloads”(Passing result of std::bind to std::function “overloads”)

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

我有两个重载方法Add ,它们采用不同形式的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) { }

这现在对lambda表达式正常工作,但与函数绑定与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:'添加':对重载函数的模糊调用

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

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

元组索引超出范围

有没有办法使它与lambdas和绑定的函子一起工作? 我会考虑使用SFINAE来启用基于is_bindable_expression的单个重载并检查参数类型但我没有把它放在一起。

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

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) { }

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));

fails with

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

and

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

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

tuple index out of bounds

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 。 这是一个随机的功能和怪癖混乱。

今天的怪癖是, std::bind将接受无限数量的参数并丢弃任何额外的参数。 明天你可能会遇到这样一个事实:将std::bind结果传递给std::bind会产生奇怪的效果。

std::bind被移植到同一时间增加了语言的lambdas。 Lambdas几乎解决了每个问题bind问题,就像清晰的语法一样,并且没有让怪癖bind问题,特别是在auto lambda表达式可用后的C ++ 14之后。 (大多数C ++ 11编译器也支持auto lambda)。

您可以编写函数,使其中一个或另一个在他们都适用时是首选的超载。 但是这样做会给你的界面增加一堆噪音,在这种情况下,你想要这个偏好的唯一原因是因为std::bind做了一些愚蠢的事情。

围绕设计不佳的std库进行工程是不值得的。 只需停止使用std库的设计不佳的地方,或者在明确使用的地方使用。


如果没有,请这样做:

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检测,在你想使用的两个重载中选择哪一个,并明确地选择一个。

这不值得。

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

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 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).

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.

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> }

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

This is not worth it.

更多推荐

本文发布于:2023-07-19 02:43:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1171544.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:function   bind   std   result   Passing

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!