Skip to content

Instantly share code, notes, and snippets.

@koturn
Last active May 26, 2020 05:05
Show Gist options
  • Select an option

  • Save koturn/8d80bdedec0bf1ed6655454775041e15 to your computer and use it in GitHub Desktop.

Select an option

Save koturn/8d80bdedec0bf1ed6655454775041e15 to your computer and use it in GitHub Desktop.
再帰ラムダのオーバーロード
#include <iostream>
#include <type_traits>
#include <utility>
#if defined(__cpp_variadic_using) && defined(__cpp_deduction_guides)
template <typename... Fs>
class
#if defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard)
[[nodiscard]]
#endif // defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard)
OverloadedFunc
: public Fs...
{
public:
template <
typename... Gs,
std::enable_if_t<sizeof...(Fs) == sizeof...(Gs), std::nullptr_t> = nullptr
>
explicit constexpr OverloadedFunc(Gs&& ... gs) noexcept
: Fs{std::forward<Gs>(gs)}...
{}
using Fs::operator()...;
}; // class OverloadedFunc
template <typename... Fs>
OverloadedFunc(Fs&&...)
-> OverloadedFunc<std::decay_t<Fs>...>;
#else
template <typename... Fs>
class OverloadedFunc;
template <typename F>
class
#if defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard)
[[nodiscard]]
#endif // defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard)
OverloadedFunc<F>
: private F
{
public:
explicit constexpr OverloadedFunc(F&& f) noexcept
: F{std::forward<F>(f)}
{}
using F::operator();
}; // class OverloadedFunc
template <
typename F,
typename G,
typename... Fs
>
class
#if defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard)
[[nodiscard]]
#endif // defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard)
OverloadedFunc<F, G, Fs...>
: private F
, private OverloadedFunc<G, Fs...>
{
public:
explicit constexpr OverloadedFunc(F&& f, G&& g, Fs&& ... fs) noexcept
: F{std::forward<F>(f)}
, OverloadedFunc<G, Fs...>{std::forward<G>(g), std::forward<Fs>(fs)...}
{}
using F::operator();
using OverloadedFunc<G, Fs...>::operator();
}; // class OverloadedFunc
#endif // defined(__cpp_variadic_using) && defined(__cpp_deduction_guides)
namespace
{
template <typename... Fs>
#if !defined(__has_cpp_attribute) || !__has_cpp_attribute(nodiscard)
#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 4)
__attribute__((warn_unused_result))
#elif defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_Check_return_)
_Check_return_
#endif // defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 4)
#endif // !defined(__has_cpp_attribute) || !__has_cpp_attribute(nodiscard)
constexpr auto
makeOverloadedFunc(Fs&&... fs) noexcept
-> OverloadedFunc<typename std::decay<Fs>::type...>
{
return OverloadedFunc<typename std::decay<Fs>::type...>{std::forward<typename std::decay<Fs>::type>(fs)...};
}
} // namespace
template <typename... Fs>
class
#if defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard)
[[nodiscard]]
#endif // defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard)
FixPoint final : private OverloadedFunc<Fs...>
{
using OverloadedFunc<Fs...>::operator();
public:
template <typename... Gs>
explicit constexpr FixPoint(Gs&& ... gs) noexcept
: OverloadedFunc<Fs...>{std::forward<Gs>(gs)...}
{}
template <typename... Args>
constexpr decltype(auto)
operator()(Args&&... args) const
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 9
noexcept(noexcept(operator()(std::declval<FixPoint>(), std::declval<Args>()...)))
#endif // !defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 9
{
return operator()(*this, std::forward<Args>(args)...);
}
}; // class FixPoint
#if defined(__cpp_deduction_guides)
template <typename... Fs>
FixPoint(Fs&&...)
-> FixPoint<std::decay_t<Fs>...>;
#endif // defined(__cpp_deduction_guides)
namespace
{
template <typename... Fs>
#if !defined(__has_cpp_attribute) || !__has_cpp_attribute(nodiscard)
#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 4)
__attribute__((warn_unused_result))
#elif defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_Check_return_)
_Check_return_
#endif // defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 4)
#endif // !defined(__has_cpp_attribute) || !__has_cpp_attribute(nodiscard)
inline constexpr decltype(auto)
fix(Fs&&... fs) noexcept
{
return FixPoint<std::decay_t<Fs>...>{std::forward<std::decay_t<Fs>>(fs)...};
}
} // namespace
int
main()
{
auto f = fix(
[](auto&& f, int n) -> int {
return n < 2 ? n : (f(n - 1) + f(n - 2));
},
[](auto&& f, double n) -> double {
return n < 2 ? n : (f(n - 1) + f(n - 2));
});
std::cout << f(10) << std::endl;
std::cout << f(9.5) << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment