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 */