C++ 将lambda直接传递给函数

C++ 将lambda直接传递给函数,c++,c++11,C++,C++11,我正在编写一个选项类,它表示一个可能存在或不存在的值。if_opt函数旨在获取一个选项和一个函数,该函数将根据选项中的值调用,但仅当该值存在时才调用 template <class T> class Option { private: std::shared_ptr<T> m_value; public: explicit operator bool()const noexcept { return (bool)m_value;

我正在编写一个
选项
类,它表示一个可能存在或不存在的值。
if_opt
函数旨在获取一个
选项
和一个函数,该函数将根据
选项
中的值调用,但仅当该值存在时才调用

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);
};
模板
类选项{
私人:
std::共享_ptr m_值;
公众:
显式运算符bool()const noexcept
{
返回(bool)m_值;
}
选项()=默认值;
显式选项(T值)
{
m_值=标准::使_共享(值);
}
模板
如果_opt(选项&标准::函数),则友元无效;
};
模板
如果选择无效(选项&opt,标准::函数f)
{
if(opt)f(*opt.m_值);
};
我注意到,如果我这样使用它,它会起作用:

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);
选项无;
方案一(10);
函数f1=[](int&none)
{
cout
std::function
是一种类型擦除工具。它擦除(几乎)它存储的expet值的所有内容,这些内容可以通过
Sig
调用

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

在类型擦除模板上进行推断是一种代码气味,而且几乎总是一个坏主意

这就是你的基本设计错误


有许多方法可以修复代码

首先,
if_opt
不应该是模板

friend void if_opt(Option<T>& opt, std::function<void(T&)> 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);
}
模板
如果选择,则朋友无效(选项和选项,F和F){
if(opt)f(*opt.m_值);
}
上面的代码是模糊的,与上面的代码相比具有最小的边际优势。

std::function
是一种类型擦除工具。它擦除(几乎)它存储的excpet值的所有可以用
Sig
调用的内容

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

在类型擦除模板上进行推断是一种代码气味,而且几乎总是一个坏主意

这就是你的基本设计错误


有许多方法可以修复代码

首先,
if_opt
不应该是模板

friend void if_opt(Option<T>& opt, std::function<void(T&)> 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);
}
模板
如果选择,则朋友无效(选项和选项,F和F){
if(opt)f(*opt.m_值);
}

上面的内容是模糊的,与上面的内容相比具有最小的边际优势。

如果_opt(Option&opt,F F){…}
FWIW,有一些
std::optional
的实现可以与C++11一起使用。A
shared_ptr
因为这太过分了,对于
if_opt
std::function
也太过分了,因为它从来没有被存储过。@IgorTandetnik老实说,这就是我想要的。我觉得不只是这么做太傻了。我接受这个答案@chris谢谢,我不知道std::optional
你知道这是一个发明的轮子吗?
#如果_opt(Option&opt,F F){…}包含
模板无效
FWIW,有一些
std::optional
的实现可以与C++11一起使用。A
shared_ptr
因为这太过分了,对于
if_opt
std::function
也太过分了,因为它从来没有被存储过。@IgorTandetnik老实说,这就是我想要的。我觉得不只是这么做太傻了。我接受这个答案@克里斯:谢谢,我不知道std::optional你知道这是一个发明的轮子吗?
#包括
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);
}