Skip to content

Instantly share code, notes, and snippets.

@gintenlabo
Created September 3, 2013 09:46
Show Gist options
  • Save gintenlabo/6421801 to your computer and use it in GitHub Desktop.
Save gintenlabo/6421801 to your computer and use it in GitHub Desktop.
C++11 で不動点コンビネータ( GCC-4.8 だと std::function<int(int)> の SFINAE に引っかかって動かない)
#include <functional>
namespace etude {
template<class F>
struct fixed {
template<class F_,
class = typename std::enable_if<std::is_convertible<F_, F>{}>::type>
explicit fixed(F_ && f)
: f_(std::forward<F_>(f)) {
}
template<class... Args>
auto operator()(Args&&... args)
-> decltype(
std::declval<F&>()(
std::ref(std::declval<fixed&>()),
std::declval<Args&&>()...)) {
return f_(std::ref(*this), std::forward<Args>(args)...);
}
template<class... Args>
auto operator()(Args&&... args) const
-> decltype(
std::declval<F const&>()(
std::ref(std::declval<fixed const&>()),
std::declval<Args&&>()...)) {
return f_(std::ref(*this), std::forward<Args>(args)...);
}
private:
F f_;
};
template<class F>
fixed<F> fix(F f) {
return fixed<F>{std::forward<F>(f)};
}
} // namespace etude
#include <iostream>
int main() {
auto f = etude::fix(
[] (std::function<int(int)> f, int x) -> int {
return x > 0 ? x * f(x-1) : 1;
});
std::cout << f(5) << std::endl;
auto const g = f;
std::cout << g(5) << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment