diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 3faaa4b54a..a11fe2a7aa 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -31,4 +31,5 @@ add_files(
smallvec_type.hpp
string_compare_type.hpp
tinystring_type.hpp
+ y_combinator.hpp
)
diff --git a/src/core/y_combinator.hpp b/src/core/y_combinator.hpp
new file mode 100644
index 0000000000..6429cda278
--- /dev/null
+++ b/src/core/y_combinator.hpp
@@ -0,0 +1,36 @@
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see .
+ */
+
+/** @file y_combinator.hpp Y-combinator template implementation to support recursive lambdas and similar. */
+
+#ifndef Y_COMBINATOR_HPP
+#define Y_COMBINATOR_HPP
+
+#include
+#include
+
+/* Based on C++ std library proposal: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0200r0.html */
+
+template
+class y_combinator_result {
+ F func_;
+public:
+ template
+ explicit y_combinator_result(T &&func): func_(std::forward(func)) {}
+
+ template
+ decltype(auto) operator()(Args &&...args) {
+ return func_(std::ref(*this), std::forward(args)...);
+ }
+};
+
+template
+decltype(auto) y_combinator(F &&func) {
+ return y_combinator_result>(std::forward(func));
+}
+
+#endif /* Y_COMBINATOR_HPP */