c++ - 将 lambda 直接传递给函数

标签 c++ c++11

我正在写一个 Option表示可能存在或可能不存在的值的类。 if_opt函数旨在采用 Option和一个将根据 Option 中保存的值调用的函数,但前提是该值存在。

template <class T>
class Option {
private:
    std::shared_ptr<T> m_value;
public:
    explicit operator bool()const noexcept
    {
        return (bool)m_value;
    }

    Option() = default;

    explicit Option(T value)
    {
        m_value =  std::make_shared<T>(value);
    }

    template <class U>
    friend void if_opt(Option<U>&, std::function<void(U&)>);
};

template <class T>
void if_opt(Option<T>& opt, std::function<void(T&)> f)
{
    if (opt) f(*opt.m_value);
};

我注意到如果我这样使用它,它会起作用:

Option<int> none;
Option<int> some(10);

function<void(int&)> f1 = [](int& none)
{
    cout << "This should never be reached" << endl;
};

function<void(int&)> f2 = [](int& some)
{
    cout << "The value of some is: " << some << endl;
};

if_opt(none, f1);

if_opt(some, f2);

但我希望能够将 lambda 表达式直接放在调用中,但是当我这样做时:

if_opt(none, [](int&)
{
    cout << "This should never be reached" << endl;
});

if_opt(some, [](int& some)
{
    cout << "The value of some is: " << some << endl;
});

我得到一个错误:

error: no matching function for call to 'if_opt(Option<int>&, main()::<lambda(int&)>)'

我知道 lambda 表达式的类型在标准中是未定义的,它只需要分配给 std::function<R(T)> ,所以这很有意义,但是有没有办法让 lambda 参数隐式转换为 std::function<void(T&)>这样我就可以在对 if_opt 的调用中定义 lambda我尝试的方式?

最佳答案

std::function<Sig>是一种类型删除工具。它删除(几乎)所有关于它存储的值的所有信息,它可以用 Sig 调用。 .

模板参数推导采用传入的类型并推导应使用的类型,然后生成并(通常)调用模板函数。

这些几乎是彼此相反的。在类型删除模板上进行推导是代码味道,而且几乎总是一个坏主意。

所以这是你的基本设计错误。


修复代码的方法有很多种。

首先,if_opt不应该是模板。

friend void if_opt(Option<T>& opt, std::function<void(T&)> f){
  if (opt) f(*opt.m_value);
}

这创建了我所说的 Koenig friend 。您必须内联定义主体。真的,那个U类型毫无意义,在某些情况下甚至会导致错误。

但是这里的类型删除也是毫无意义的。修复返回模板,但现在有充分的理由。

template<class F>
friend void if_opt(Option<T>& opt, F&& f){
  if (opt) f(*opt.m_value);
}

这是一个更好的设计。

你可以去投资 SFINAE 重载解析代码,但我不会费心。

template<class F,
  std::conditional_t<true, bool,std::result_of_t<F&(T&)>> = true
>
friend void if_opt(Option<T>& opt, F&& f){
  if (opt) f(*opt.m_value);
}

以上是晦涩的,并且与上面的相比具有最小的边际优势。

关于c++ - 将 lambda 直接传递给函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48969458/

相关文章:

c++ - 指向 std::vector 的指针,指针声明

c++ - 如何在没有拷贝的情况下使右值引用传递的对象保持事件状态?

c++ - 如何将类的方法传递给 C++ 中的另一个函数?

c++ - 类中的 std::function 初始化

c++ - 为什么我在 CUDA 中实现求和减少时会得到错误的结果?

c++ - 与 XBoard(国际象棋引擎)通信(C++/C)

c++ 11使用lambda排序 vector 跟踪索引

c++ - 'x' 和 L'x' 之间的关系并加宽 ('x' )

使用模板的 C++ 链表

c++ - 为什么我们只对用户定义的数据类型使用箭头和点运算符为什么不对原始数据类型使用?