最近,我阅读了Barry对这个问题Recursive lambda functions in C++11的回答:
template <class F>
struct y_combinator {
F f; // the lambda will be stored here
// a forwarding operator():
template <class... Args>
decltype(auto) operator()(Args&&... args) const {
// we pass ourselves to f, then the arguments.
// [edit: Barry] pass in std::ref(*this) instead of *this
return f(std::ref(*this), std::forward<Args>(args)...);
}
};
// deduction guide
template <class F> y_combinator(F) -> y_combinator<F>;
基本上,y_combinator
允许人们更轻松地编写递归 lambda 表达式(例如,无需删除 a std::function
)。当我玩的时候y_combinator
,我发现了一些奇怪的东西:
int main() {
// Case #1 compiles fine
y_combinator{[](auto g, int a, int b) {
if (a >= b) return 0;
return 1 + g(a + 1, b);
}}(1, 2);
// Case #2 deos not compile
y_combinator{[](auto g, int a) {
if (a >= 0) return 0;
return 1 + g(a + 1);
}}(1);
// Case #3 compiles just fine
y_combinator{[](auto g, int a)->int {
if (a >= 0) return 0;
return 1 + g(a + 1);
}}(1);
}
案例#1 和案例#3 编译良好,而案例#2 不编译。我使用 Clang 10.0 和 GCC 9.3 得到了相同的结果。对于案例 #2,Clang 说
prog.cc:25:18: error: no matching function for call to object of type 'std::__1::reference_wrapper<const y_combinator<(lambda at prog.cc:23:18)> >'
return 1 + g(a + 1);
^
- 案例#1 和案例#2 的结果有何不同?
- 为什么尾随返回类型会在案例 #2 和案例 #3 之间产生差异?
您可以在Wandbox上查看。