c_cpp C ++ 14中的函数currying(function_traits.cpp:https://gist.github.com/Garciat/cafe27d04cfdff0e891e)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp C ++ 14中的函数currying(function_traits.cpp:https://gist.github.com/Garciat/cafe27d04cfdff0e891e)相关的知识,希望对你有一定的参考价值。

#include "curry.cpp"
#include "meow.cpp"
#include <iostream>

int main() {
	{
		auto add = curry([](meow, int a, int b, int c) { return a + b + c; });
		
		std::cout << add(meow{})(5)(5)(5) << std::endl;
	}
	
	meow::report();
}
#include <type_traits>
#include <utility>
#include <tuple>

#include "function_traits.cpp"

// ---

template <typename Args, typename Params>
struct apply_args;

template <typename HeadArgs, typename... Args, typename HeadParams, typename... Params>
struct apply_args<std::tuple<HeadArgs, Args...>, std::tuple<HeadParams, Params...>>
	: std::enable_if<
		std::is_constructible<HeadParams, HeadArgs>::value,
		apply_args<std::tuple<Args...>, std::tuple<Params...>>
	>::type
{ };

template <typename... Params>
struct apply_args<std::tuple<>, std::tuple<Params...>> {
	using type = std::tuple<Params...>;
};

// ---

using empty_tuple_t = std::tuple<>;

template <typename TupleType>
struct is_empty_tuple : std::false_type { };

template <>
struct is_empty_tuple<empty_tuple_t> : std::true_type { };

// ----

template <typename FType, typename Env, typename Params>
struct currying;

template <typename FType, typename... Env, typename... Params>
struct currying<FType, std::tuple<Env...>, std::tuple<Params...>> {
	using function_type = FType;
	using closure_env_type = std::tuple<Env...>;
	using param_tuple_type = std::tuple<Params...>;
	
	template <typename Func, typename... Args>
	constexpr
	currying(Func&& func, Args&&... args) :
		func(std::move(func)),
		env(std::forward<Args>(args)...)
	{ }
	
	template <typename... Args>
	constexpr
	auto operator() (Args&&... args) const& {
		using ArgsTuple = std::tuple<Args...>;
		
		using NewEnv = std::tuple<Env..., Args...>;
		using NewParams = typename apply_args<ArgsTuple, param_tuple_type>::type;
		using NewCurrying = currying<FType, NewEnv, NewParams>;
		
		using EnvIndices = std::make_index_sequence<sizeof...(Env)>;
		
		using CanExecute = is_empty_tuple<NewParams>;
		
		return apply<NewCurrying, CanExecute>(EnvIndices{}, std::forward<Args>(args)...);
	}
	
	template <typename... Args>
	constexpr
	auto operator() (Args&&... args) && {
		using ArgsTuple = std::tuple<Args...>;
		
		using NewEnv = std::tuple<Env..., Args...>;
		using NewParams = typename apply_args<ArgsTuple, param_tuple_type>::type;
		using NewCurrying = currying<FType, NewEnv, NewParams>;
		
		using EnvIndices = std::make_index_sequence<sizeof...(Env)>;
		
		using CanExecute = is_empty_tuple<NewParams>;
		
		return std::move(*this).template apply<NewCurrying, CanExecute>(EnvIndices{}, std::forward<Args>(args)...);
	}
	
private:
	template <typename NewCurrying, typename CanExecute, typename... Args, size_t... Indices>
	constexpr
	auto apply(std::index_sequence<Indices...>, Args&&... args) const& {
		return apply<NewCurrying>(CanExecute{}, std::get<Indices>(env)..., std::forward<Args>(args)...);
	}
	
	template <typename NewCurrying, typename CanExecute, typename... Args, size_t... Indices>
	constexpr
	auto apply(std::index_sequence<Indices...>, Args&&... args) && {
		return std::move(*this).template apply<NewCurrying>(CanExecute{}, std::get<Indices>(std::move(env))..., std::forward<Args>(args)...);
	}
	
	template <typename NewCurrying, typename... Args>
	constexpr
	auto apply(std::false_type, Args&&... args) const& {
		return NewCurrying{ func, std::forward<Args>(args)... };
	}
	
	template <typename NewCurrying, typename... Args>
	constexpr
	auto apply(std::false_type, Args&&... args) && {
		return NewCurrying{ std::move(func), std::forward<Args>(args)... };
	}
	
	template <typename NewCurrying, typename... Args>
	constexpr
	auto apply(std::true_type, Args&&... args) const {
		return func(std::forward<Args>(args)...);
	}
	
	function_type func;
	closure_env_type env;
};

// ---

template <typename FType>
constexpr
auto curry(FType&& func) {
	using ArgsTuple = function_arg_tuple_t<FType>;
	
	using CurryType = currying<FType, empty_tuple_t, ArgsTuple>;
	
	return CurryType{ std::move(func) };
}

以上是关于c_cpp C ++ 14中的函数currying(function_traits.cpp:https://gist.github.com/Garciat/cafe27d04cfdff0e891e)的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp 使用一堆C ++ 11/14特性和“老派”C ++开发人员的单一函数甚至不再像C ++那样阅读.Specificall

Curry 通用量化函数

手写curry函数,实现函数柯里化

js函数柯里化的理解

js函数柯里化的理解

JS中的柯里化(currying)