c++ - 将 std::bind 的结果传递给 std::function "overloads"

标签 c++ c++14 template-meta-programming sfinae

我有类似 Passing different lambdas to function template in c++ 的问题但现在使用 std::bind 而不是 lambda 创建的包装器。

我有两个方法重载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 绑定(bind)的仿函数:

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

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

失败

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

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

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

tuple index out of bounds

有没有办法让它同时适用于 lambda 和绑定(bind)仿函数?我会考虑使用 SFINAE 来启用基于 is_bindable_expression 的单独重载并检查参数类型,但我无法将它们放在一起。

最佳答案

停止使用 std::bind。这是一团乱七八糟的随机功能和怪癖。

今天的怪癖是 std::bind 将接受无限数量的参数并丢弃任何额外的参数。明天您可能会发现将 std::bind 结果传递给 std::bind 会产生奇怪的魔法。

std::bind 被移植到 boost,同时 lambdas 添加到语言中。 Lambda 解决了 bind 几乎所有的问题,语法清晰,并且没有 bind 的怪癖,尤其是 C++14 之后的 auto lambda 可用。 (大多数 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 检测,并明确更喜欢一个。

这不值得。

关于c++ - 将 std::bind 的结果传递给 std::function "overloads",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40547846/

相关文章:

c++ - 如何为第 3 方渲染提供空 QML 项的 OpenGL 上下文?

c++ - 在同一命令中使用变量时移至 lambda

C# 等价于 C++ 回调

c++ - 将 shared_ptr 移动到在 shared_ptr 指向的对象上调用的方法

c++ - 如何从函数指针推导出参数列表?

c++ - 使用 vector (字符串)C++

混合整数类型的 C++ 算术导致溢出

c++ - C++ 中类似 Python 的 map

C++11 constexpr 函数的参数传入模板参数

c++ - C++ 概念和 C++ 模板约束有什么区别?