关于前一个问题( 是否可以通过引用从lambda返回类型为T的对象而不使用尾随返回类型语法? ),我想知道是否有任何其他重要案例或示例,其中trailing-return-type语法,当使用lambdas时, 无法避免。
I suppose that another case is when there is type inconsistency between differents returns.
A silly example
std::function<long(int)> f
= [](int v) -> long { if ( v ) return v; else return 0L; };
Obviously you can avoid it if you avoid inconsistency so I don't know if it's significant.
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 */ }
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 */
}
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);
}
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.