constexpr な bind1st
ついでにカリー化も。
[ソース]
#include <functional> #include <type_traits> namespace aliases{ template<typename T> using remove_reference = typename std::remove_reference<T>::type; } // namespace aliases template<typename F, typename First> struct bind1st_impl{ template<typename ...Args> constexpr auto operator ()(Args&&... args) const ->decltype(std::declval<F>()(std::declval<First>(), std::forward<Args>(args)...)){ return func(first, std::forward<Args>(args)...); } F func; First first; }; template<typename F, typename First> constexpr bind1st_impl<F, aliases::remove_reference<First>> bind1st(F func, First&& first){ return { func, std::forward<First>(first) }; } template<typename F> struct curry_impl{ template<typename T> constexpr operator T() const{ return func(); } template<typename First> constexpr curry_impl<bind1st_impl<F, aliases::remove_reference<First>>> operator ()(First&& first) const{ return { ::bind1st(func, std::forward<First>(first)) }; } F func; }; template<typename F> constexpr curry_impl<F> curry(F func){ return { std::forward<F>(func) }; } struct plus{ template<typename T> constexpr aliases::remove_reference<T> operator ()(T&& t) const{ return std::forward<T>(t); } template<typename T, typename ...Args> constexpr aliases::remove_reference<T> operator ()(T&& t, Args&&... args) const{ return std::forward<T>(t) + (*this)(std::forward<Args>(args)... ); } }; constexpr int minus(int a, int b, int c){ return a - b - c; } int main(){ constexpr auto plus3 = bind1st(plus(), 3); static_assert(plus3( 2) == 5, ""); static_assert(plus3(-3) == 0, ""); static_assert(bind1st(bind1st(minus, 10), 4)(2), ""); static_assert(bind1st(bind1st(plus(), 10), 5)() == 15, ""); constexpr int result = curry(&minus)(3)(2)(1); static_assert(result == 0, ""); constexpr int result2 = curry(plus())(3)(2)(1)(-4); static_assert(result2 == 2, ""); return 0; }
こんな感じであっているかしら?
そういえば、メソッドのこととかあんまり考えていないなー。