将SFINAE与通用lambda结合使用 [英] Using SFINAE with generic lambdas

查看:88
本文介绍了将SFINAE与通用lambda结合使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

泛型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 。在工业质量库中,我可以使继承成为二进制而不是线性(以限制模板的实例化深度和继承树的深度)。

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆