sin*_*raj 6 lambda functional-programming composition c++11
有没有办法超载,比如>>操作员的功能组合?操作员应该在lambda上无缝地工作std::function?
要求:
bind调用,这是一个快速而肮脏的示例,说明了所需的行为:
#include <iostream>
#include <functional>
using namespace std;
// An example of a quick and dirty function composition.
// Note that instead of 'std::function' this operator should accept
// any functional/callable type (just like 'bind').
template<typename R1, typename R2, typename... ArgTypes1>
function<R2(ArgTypes1...)> operator >> (
const function<R1(ArgTypes1...)>& f1,
const function<R2(R1)>& f2) {
return [=](ArgTypes1... args){ return f2(f1(args...)); };
}
int main(int argc, char **args) {
auto l1 = [](int i, int j) {return i + j;};
auto l2 = [](int i) {return i * i;};
function<int(int, int)> f1 = l1;
function<int(int)> f2 = l2;
cout << "Function composition: " << (f1 >> f2)(3, 5) << endl;
// The following is desired, but it doesn't compile as it is:
cout << "Function composition: " << (l1 >> l2)(3, 5) << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
(l1 >> l2)永远无法工作。
它们是由编译器创建的函数对象,不包含该运算符,因此除非您计划将编译器修改为不合格,否则它总是会这样。:)
但是,您可以引入一个“关键字”(实用程序类),这可以说是一件好事,但它很重:
// https://ideone.com/MS2E3
#include <iostream>
#include <functional>
namespace detail
{
template <typename R, typename... Args>
class composed_function;
// utility stuff
template <typename... Args>
struct variadic_typedef;
template <typename Func>
struct callable_type_info :
callable_type_info<decltype(&Func::operator())>
{};
template <typename Func>
struct callable_type_info<Func*> :
callable_type_info<Func>
{};
template <typename DeducedR, typename... DeducedArgs>
struct callable_type_info<DeducedR(DeducedArgs...)>
{
typedef DeducedR return_type;
typedef variadic_typedef<DeducedArgs...> args_type;
};
template <typename O, typename DeducedR, typename... DeducedArgs>
struct callable_type_info<DeducedR (O::*)(DeducedArgs...) const>
{
typedef DeducedR return_type;
typedef variadic_typedef<DeducedArgs...> args_type;
};
template <typename DeducedR, typename... DeducedArgs>
struct callable_type_info<std::function<DeducedR(DeducedArgs...)>>
{
typedef DeducedR return_type;
typedef variadic_typedef<DeducedArgs...> args_type;
};
template <typename Func>
struct return_type
{
typedef typename callable_type_info<Func>::return_type type;
};
template <typename Func>
struct args_type
{
typedef typename callable_type_info<Func>::args_type type;
};
template <typename FuncR, typename... FuncArgs>
struct composed_function_type
{
typedef composed_function<FuncR, FuncArgs...> type;
};
template <typename FuncR, typename... FuncArgs>
struct composed_function_type<FuncR, variadic_typedef<FuncArgs...>> :
composed_function_type<FuncR, FuncArgs...>
{};
template <typename R, typename... Args>
class composed_function
{
public:
composed_function(std::function<R(Args...)> func) :
mFunction(std::move(func))
{}
template <typename... CallArgs>
R operator()(CallArgs&&... args)
{
return mFunction(std::forward<CallArgs>(args)...);
}
template <typename Func>
typename composed_function_type<
typename return_type<Func>::type, Args...>::type
operator>>(Func func) /* && */ // rvalues only (unsupported for now)
{
std::function<R(Args...)> thisFunc = std::move(mFunction);
return typename composed_function_type<
typename return_type<Func>::type, Args...>::type(
[=](Args... args)
{
return func(thisFunc(args...));
});
}
private:
std::function<R(Args...)> mFunction;
};
}
template <typename Func>
typename detail::composed_function_type<
typename detail::return_type<Func>::type,
typename detail::args_type<Func>::type>::type
compose(Func func)
{
return typename detail::composed_function_type<
typename detail::return_type<Func>::type,
typename detail::args_type<Func>::type>::type(func);
}
int main()
{
using namespace std;
auto l1 = [](int i, int j) {return i + j;};
auto l2 = [](int i) {return i * i;};
std:function<int(int, int)> f1 = l1;
function<int(int)> f2 = l2;
cout << "Function composition: " << (compose(f1) >> f2)(3, 5) << endl;
cout << "Function composition: " << (compose(l1) >> l2)(3, 5) << endl;
cout << "Function composition: " << (compose(f1) >> l2)(3, 5) << endl;
cout << "Function composition: " << (compose(l1) >> f2)(3, 5) << endl;
return 0;
Run Code Online (Sandbox Code Playgroud)
这是相当多的代码!不幸的是我不知道如何减少它。
你可以走另一条路,只是为了在你的方案中使用 lambda,你只需要显式地将它们设置为std::function<>s,但它不太统一。上面的一些机制可以用来创建某种to_function()函数,将 lambda 函数转换为std::function<>s。