是否存在无法避免lambda中的尾随返回类型语法的情况? [英] Are there cases in which trailing-return-type syntax in lambda cannot be avoided?

查看:94
本文介绍了是否存在无法避免lambda中的尾随返回类型语法的情况?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于上一个问题(是否可以通过引用从lambda返回类型T的对象而无需使用尾随返回类型语法?),我想知道是否还有其他重要案例或示例,其中使用lambda时 trailing-return-type 语法是否可以不能被避免.

In relation to a previous question (Is it possible to return an object of type T by reference from a lambda without using trailing return type syntax?), I was wondering if there is any other significant case or example in which trailing-return-type syntax, when using lambdas, can not be avoided.

推荐答案

在C ++ 14中,一个人为设计的示例是将sfinae与通用lambda结合使用:

In C++14, a bit contrived example is the use of sfinae in combination with a generic lambda:

[](auto &&arg)
-> decltype(arg.f(), void())
{ /* do whatever you want */ }

无论如何,有人可能会说static_assert就足够了:

Anyway one could argue that a static_assert suffices:

[](auto &&arg) {
    static_assert(has_metod_f<std::decay_t<decltype(arg)>>::value, "!");
    /* do whatever you want */
}

has_method_f是常见的检测器习惯用法.
无论如何,想象一下您想从一堆lambda开始构造组合函子的情况:

Where has_method_f is the common detector idiom.
Anyway, imagine a case where you want to construct a composed functor starting from a bunch of lambdas:

#include<utility>
#include<iostream>

template<typename...>
struct Base;

template<typename Func, typename... Others>
struct Base<Func, Others...>: Func, Base<Others...> {
    Base(Func func, Others... others)
    : Func{std::move(func)}, Base<Others...>{std::move(others)...}
    {}

    template<typename... Args>
    auto operator()(int, Args&&... args)
    -> decltype(Func::operator()(std::forward<Args>(args)...)) {
        Func::operator()(std::forward<Args>(args)...);
    }

    template<typename... Args>
    auto operator()(char, Args&&... args) {
        Base<Others...>::operator()(0, std::forward<Args>(args)...);
    }
};

template<>
struct Base<> {
    template<typename... Args>
    auto operator()(Args&&...) {
        std::cout << "fallback" << std::endl;
    }
};

template<typename... Ops>
struct Mixin: Base<Ops...> {
    Mixin(Ops... ops)
        : Base<Ops...>{std::move(ops)...}
    {}

    template<typename... Args>
    auto operator()(Args&&... args) {
        return Base<Ops...>::operator()(0, std::forward<Args>(args)...);
    }
};

struct T { void f() {} };
struct U {};

int main() {
    auto l1 = [](auto &&arg) -> decltype(arg.f(), void()) {
        std::cout << "accept T" << std::endl;
    };

    auto l2 = [](U) {
        std::cout << "accept U" << std::endl;
    };

    Mixin<decltype(l1), decltype(l2)> mixin{std::move(l1), std::move(l2)};
    mixin(T{});
    mixin(U{});
    mixin(0);
}

在这种情况下,static_assert将阻止编译,这不是预期的结果.
另一方面,可以使用尾随返回类型在包装器的帮助下直接在lambda上启用sfinae.

In this case, a static_assert would prevent the compilation and it is not the expected result.
On the other side, the trailing return type can be used to enable sfinae directly on the lambdas with the help of their wrappers.

这篇关于是否存在无法避免lambda中的尾随返回类型语法的情况?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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