请看看我的快速博客文章,在那里我会告诉你一些有趣的兰姆达的例子。你知道如何写递归的 lambda 吗?把它们存放在容器里?或在编译时调用?
请参阅本文中的介绍。
1. 递归兰姆达与std::function
编写递归函数相对简单:在函数定义中,可以通过其名称调用同一函数。羔羊怎么样?
x
int主() |
自动因子= (intn) =
};
5
回报因子(5);
6
}
这个,可惜不编译 ... ...
我们如何解决这个问题?
一种方法就是使用 std::function
:
C++
x
1
1
[int 主()]
4
conststd::函数<int(int)>factorial=因子= 和因子factorial=(intintn) |
5
返回n>1?n*因子 (n-11;
6
};
7
回报因子(5);
8
}
这一次, 我们需要 factorial
捕捉, 然后我们可以参考它在羔羊体内1px;"[int 主()]
2
康斯特自动因子= (intn) =
3
constautofact_impl[ (intnconst自动&impl->int]
4
返回n>1?n_impl(n-1impl1;
5
};
6
返回fact_impl(nfact_impl)
7
回报因子(5);
9
}
这一次,它甚至更加复杂(但不需要大量使用 std::function
。它使用内部 lambda 进行主计算,然后作为泛型参数传递。
但我想知道: 你曾经使用过递归的羔羊吗?或者,最好依靠递归函数(似乎使用和写入要舒服多了)。
2. constexpr
兰达斯
但这还不是全部与递归:)
由于 C++17,我们可以编写将呼叫运算符定义为 的 constexpr
lambda。我们可以使用此属性,将递归示例扩展到:
C++
x
1
1
[constexpr auto 自动因子] [(int n) ]
3
constexpr自动fact_impl[ [(intintnconst自动&impl->int]
4
返回n>1?n_impl(n-1impl1;
5
};
6
返回fact_impl(nfact_impl)
7
static_assert(5) = 120);
9
}
在 C++20 中,您甚至可以 consteval
应用标记只能在编译时评估的 lambda。
3. 将兰姆达斯存放在容器中
这可能有点欺骗...但理论上我们可以把羔羊存放在容器里
虽然闭包类型删除了默认构造函数(除非它是 C++20 中的无状态 lambda),但我们可以在 C++20 中执行一点哈克并将其所有 lambda 存储为 std::function
对象。例如:
C++
x
1
28
1
3
4
5
int主() |
6
std::向量<std::函数<std::字符串(conststd::字符串&;)>>vecFilters;
7
8
vecFilters。emplace_back(+)(constconststd::字符串和x
9
返回x="惊人"
10
vecfilters.emplace_back(*(const std::字符串和 x) |
12
返回x="现代"
13
});
14
vecFilters。emplace_back(+)(constconststd::字符串和x
15
返回x="C++"
16
});
17
vecFilters。emplace_back(+)(constconststd::字符串和x
18
});
20
21
conststd::字符串str="你好";
22
自动温度=str;
23
24
用于(自动和输入FuncvecFilters)
25
温度=条目乐趣 (温度);
26
27
}
4.通用的羔羊和帮助与扣除
C++14为 lambdas 带来了一个重要的补充:通用 lambda 参数。下面是一个示例,它显示了它为什么有用:
C++
x
1
16
1
3
4
5
6
int主() |
7
conststd::地图<std::字符串int>数字
8
"一"1 +, [二"2"三"3]
9
};
10
11
[(const std::p航空<std:字符串, int>&条目)]
13
std::cout<<条目。第一个 <<\n;" = "<<entry第二个 <<\n''\n';
14
}
15
);
16
}
你知道这有什么错误吗?参数类型是否在 内部 lambda 中适当指定 for_each
?
我指定了: const std::pair<std::string, int>& entry
。
但它是错误的,因为地图中的键/值对的类型是:
这就是为什么编译器必须创建不需要的临时副本,然后将它们传递给我的 lambda。
我们可以通过使用来自 14 岁的通用 lambda 来C++问题。
C++
x
1
1
std::for_each(std:: 开始(数字std:: 结束(数字
2
[(康斯特auto自动和条目entry)]
3
std::cout<<条目。第一个 <<\" = "n;entry
1px;"> }
5
);
现在,这些类型匹配,并且不会创建其他副本。
5. 返回兰姆达
如果要从函数返回 lambda(例如,对于部分函数应用程序,咖喱),则不简单,因为您不知道闭包对象的确切类型。
在C++11 中,一种方法就是使用 std::function
:
C++
x
1
10
1
{std::函数<int)> CreateLambda(int y)>
4
返回=y=(intx返回x=y; =;
5
}
6
7
int主() |
8
自动lam=CreateLambda(10)
9
返回lam(32);
10
自动创建Lambda(int y)
2
返回=y=(intx返回x=y; =;
3
}
4
5
int主() |
6
自动lam=CreateLambda(10)
7
返回lam(32);
8
[C++兰姆达故事] @Leanpub, @Amazon。
Comments are closed.