将带捕获的 lambda 传递给模板函数

pass a lambda with capture to a templated function

我尝试使用模板函数来包装任何返回布尔值的布尔表达式或仿函数。

template<typename BOOL_COND>
bool calculate(const BOOL_COND& bool_cond)
{
  return !(!(bool_cond));
}

assert( calculate( true ) );
assert( calculate( 1 == 1 ) );
std::shared_ptr<int> ptr = std::make_shared<int>(11);
assert( calculate( ptr ) );
assert( calculate( []() { return 1 == 1;} ) );
assert( calculate( std::function<bool()>([]() { return std::string().empty();} )) );

std::function<bool(void)> f = [&]() -> bool { return ptr.get();};
assert( calculate( f ));
assert( calculate( std::function<bool(void)>([&]() -> bool { return ptr.get();} )) );

// assert( calculate( [&]() -> bool { return ptr.get();} ) ); // NOT WORK!!!


// clang-600.0.57 with -std=c++1y

如果不显式转换为 std::function,我无法通过捕获传递 lambda。是什么原因?有没有不转换的解决方案?

模板专业化??怎么样?

您没有调用由 lambda 表达式 生成的闭包,而只是使用 bool_cond 就好像它是 bool 或隐式转换为它。

您需要改为调用 bool_cond

template<typename BOOL_COND>
bool calculate(const BOOL_COND& bool_cond)
{
  return !(!(bool_cond()));
}

std::function 起作用的原因是它提供了一个 implicit conversion operator bool.


如果您想要一个既适用于 函数对象 又可隐式转换 bool 的 "uniform" calculate 函数,您将需要两个用 enable_if:

约束的重载
template<typename BOOL_COND>
auto calculate(const BOOL_COND& bool_cond)
    -> std::enable_if_t<std::is_invokable_v<const BOOL_COND&>>
{
    return !(!(bool_cond()));
}

template<typename BOOL_COND>
auto calculate(const BOOL_COND& bool_cond)
    -> std::enable_if_t<!std::is_invokable_v<const BOOL_COND&>>
{
    return !(!(bool_cond));
}

使用 C++17:

template<typename BOOL_COND>
bool calculate(const BOOL_COND& bool_cond)
{
    if constexpr(std::is_invokable_v<const BOOL_COND&>)
    {
        return !(!(bool_cond()));
    }
    else
    {
        return !(!(bool_cond));
    }
}

仅略有相关,但我写了一篇文章,您可能会对将 functions/lambdas 传递给其他函数的各种方式感兴趣:"passing functions to functions".