Lambda 是底层的函数对象。通用 lambda 是带有模板的函数对象operator()
。
template<class...Fs>
struct funcs_t{};
template<class F0, class...Fs>
struct funcs_t<F0, Fs...>: F0, funcs_t<Fs...> {
funcs_t(F0 f0, Fs... fs):
F0(std::move(f0)),
funcs_t<Fs...>(std::move(fs)...)
{}
using F0::operator();
using funcs_t<Fs...>::operator();
};
template<class F>
struct funcs_t<F>:F {
funcs_t(F f):F(std::move(f)){};
using F::operator();
};
template<class...Fs>
funcs_t< std::decay_t<Fs>... > funcs(Fs&&...fs) {
return {std::forward<Fs>(fs)...};
}
auto f_all = funcs( f1, f2 )
生成一个对象,它是 和 的f1
重载f2
。
auto g_integral =
[](auto&& func, auto&& param1, auto&&... params)
-> std::enable_if_t< std::is_integral<
std::decay_t<decltype(param1)>
>{}>
{
// ...
};
auto g_not_integral =
[](auto&& func, auto&& param1, auto&&... params)
-> std::enable_if_t< !std::is_integral<
std::decay_t<decltype(param1)>
>{}>
{
// ...
};
auto gL = funcs( g_not_integral, g_integral );
并且调用gL
将对两个 lambda 进行 SFINAE 友好的重载解析。
以上在 的线性继承中做了一些可以避免的虚假动作funcs_t
。在工业质量库中,我可能会使用二进制而不是线性的继承(以限制模板的实例化深度和继承树的深度)。
顺便说一句,我知道 SFINAE 启用 lambda 有 4 个原因。
首先,使用 new std::function
,您可以在多个不同的回调签名上重载一个函数。
二、以上招数。
第三,对一个函数对象进行柯里化,当它具有正确数量和类型的参数时,它会在其中进行评估。
第四,自动元组解包等。如果我使用的是延续传递风格,我可以询问传递的延续,它是否会接受解包的元组,或者未来的解包等。