Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PythonのデコレーターをC++で再現しようと思ったらよくわからないバケモンが完成した
// copyright (c) 2021 M.K (a.k.a plasma-effect)
// Distributed under the Boost Software License, Version 1.0.
// (See http://www.boost.org/LICENSE_1_0.txt)
#pragma once
#include <utility>
#include <tuple>
namespace cpp_decorator
{
namespace detail
{
template<class FuncData, class Base, class IndexSequence, class Tuple>struct decorator;
template<class Return, class... FuncArgs, class Base, std::size_t... Is, class Tuple>
struct decorator<Return(FuncArgs...), Base, std::index_sequence<Is...>, Tuple>
{
Base base;
Tuple args;
template<class Func>constexpr auto operator<<=(Func func)const
{
return [base=base, args=args, func=func](FuncArgs... fargs)->Return
{
return base(func, std::get<Is>(args)...)(fargs...);
};
}
};
template<class FuncData, class Base>struct decorator_t;
template<class Return, class... FuncArgs, class Base>
struct decorator_t<Return(FuncArgs...), Base>
{
Base base;
template<class... Args>constexpr auto operator()(Args... args)const
{
auto t = std::make_tuple(args...);
return decorator<Return(FuncArgs...), Base, std::make_index_sequence<sizeof...(Args)>, decltype(t)>{base, t};
}
};
template<class FuncData>struct decorator_t2;
template<class Return, class... FuncArgs>
struct decorator_t2<Return(FuncArgs...)>
{
template<class Base>constexpr auto operator()(Base base)const
{
return decorator_t<Return(FuncArgs...), Base>{base};
}
};
}
template<class FuncData>constexpr detail::decorator_t2<FuncData> decorator;
}
#include "decorator.hpp"
#include <functional>
#include <iostream>
using namespace cpp_decorator;
auto add_i(std::function<int(int)> func, int v)
{
return [=](int u)
{
return func(u) + v;
};
}
auto mul_i(std::function<int(int)> func, int v)
{
return [=](int u)
{
return func(u) * v;
};
}
constexpr auto add = decorator<int(int)>(add_i);
constexpr auto mul = decorator<int(int)>(mul_i);
auto func = mul(2) <<= add(1) <<= [&](int v)
{
return 2 * v;
};
int main()
{
std::cout << func(5) << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment