三天以来,我一直在阅读有关组合器的信息,终于开始用代码编写它们(更像是从不同地方复制东西并理解事物)。
这是我正在尝试运行的一些代码:
#include <iostream>
#include <utility>
template <typename Lambda>
class y_combinator {
private:
Lambda lambda;
public:
template <typename T>
constexpr explicit y_combinator (T&& lambda)
: lambda (std::forward <T> (lambda))
{ }
template <typename...Args>
decltype(auto) operator () (Args&&... args) {
return lambda((decltype(*this)&)(*this), std::forward <Args> (args)...);
}
};
template <typename Lambda>
decltype(auto) y_combine (Lambda&& lambda) {
return y_combinator <std::decay_t <Lambda>> (std::forward <Lambda> (lambda));
}
int main () {
auto factorial = y_combine([&] (auto self, int64_t n) {
return n == 1 ? (int64_t)1 : n * self(n - 1);
});
int n;
std::cin >> n;
std::cout << factorial(n) << '\n';
}
如果我将 lambda 的返回类型明确声明为-> int64_t
,则一切正常。但是,当我删除它时,编译器会抱怨。错误:
main.cpp|16|error: use of 'main()::<lambda(auto:11, int64_t)> [with auto:11 = y_combinator<main()::<lambda(auto:11, int64_t)> >; int64_t = long long int]' before deduction of 'auto'
为什么编译器无法确定返回类型并推断出 auto?我首先想到,也许我需要更改... ? 1 : n * self(n - 1)
为,... ? int64_t(1) : n * self(n - 1)
以便两个返回值的类型最终都为int64_t
,并且不会留下任何可能的歧义。不过,情况似乎并非如此。我错过了什么?
此外,在y_combinator
类中,声明lambda
为类型的对象Lambda&&
似乎会导致问题。为什么会这样?这只发生在我将operator ()
重载中的强制转换写为(decltype(*this)&)
而不是std::ref(*this)
. 他们在做不同的事情吗?