将SFINAE与通用lambda结合使用 [英] Using SFINAE with generic lambdas
问题描述
泛型lambda是否可以利用替换失败不是错误 规则?示例
Can generic lambdas take advantage of the "Substitution Failure Is Not An Error" rule ? Example
auto gL =
[](auto&& func, auto&& param1, auto&&... params)
-> enable_if_t< is_integral<
std::decay_t<decltype(param1)>
>::value>
{
// ...
};
auto gL =
[](auto&& func, auto&& param1, auto&&... params)
-> enable_if_t< !is_integral<
std::decay_t<decltype(param1)>
>::value>
{
// ...
};
是否有任何变通办法或计划将其包括在语言中?另外,由于通用Lambda是引擎盖下的模板化函数对象,难道这无法做到吗?
Are there any workarounds or plans to include this in the language ? Also since generic lambdas are templated function objects under the hood isn't it a bit odd that this can't be done ?
推荐答案
Lambda是内部的函数对象。通用lambda是具有模板 operator()
s的函数对象。
Lambdas are function objects under the hood. Generic lambdas are function objects with template operator()
s.
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 f_all = funcs( f1, f2 )
generates an object that is an overload of both f1
and 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
会进行SFINAE友好的重载
and calling gL
will do SFINAE friendly overload resolution on the two lambdas.
上面的代码在 funcs_t $ c $的线性继承中做了一些可以避免的虚假动作。 c>。在工业质量库中,我可以使继承成为二进制而不是线性(以限制模板的实例化深度和继承树的深度)。
The above does some spurious moves, which could be avoided, in the linear inheritance of funcs_t
. In an industrial quality library, I might make the inheritance binary rather than linear (to limit instantiation depth of templates, and the depth of the inheritance tree).
顺便说一句,我知道SFINAE启用lambda的原因有四个。
As an aside, there are 4 reasons I know of to SFINAE enable lambdas.
首先,添加新的 std :: function
,您可以在多个不同的回调签名上重载函数。
First, with new std::function
, you can overload a function on multiple different callback signatures.
第二个,上面的技巧。
第三,在一个函数对象具有正确数量和类型的args的情况下,对函数对象进行计算。
Third, currying a function object where it evaluates when it has the right number and type of args.
第四,自动元组拆包等。如果我使用的是延续传递样式,则可以询问传递的延续是否接受已拆包的元组,或将来拆装的元组,等等。
Forth, automatic tuple unpacking and similar. If I'm using continuation passing style, I can ask the passed in continuation if it will accept the tuple unpacked, or the future unbundled, etc.
这篇关于将SFINAE与通用lambda结合使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!