diff --git a/headers/kari.hpp/kari.hpp b/headers/kari.hpp/kari.hpp index 2d9047a..55805da 100644 --- a/headers/kari.hpp/kari.hpp +++ b/headers/kari.hpp/kari.hpp @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -109,3 +110,196 @@ namespace kari_hpp return curry(std::forward(f))(std::forward(a), std::forward(as)...); } } + +namespace kari_hpp::ext +{ + // + // fid + // + + struct fid_t { + template < typename A > + constexpr auto operator()(A&& a) const { + return std::forward(a); + } + }; + inline constexpr auto fid = curry(fid_t{}); + + // + // fconst + // + + struct fconst_t { + template < typename A, typename B > + constexpr auto operator()(A&& a, [[maybe_unused]] B&& b) const { + return std::forward(a); + } + }; + inline constexpr auto fconst = curry(fconst_t{}); + + // + // fflip + // + + struct fflip_t { + template < typename F, typename A, typename B > + constexpr auto operator()(F&& f, A&& a, B&& b) const { + return curry(std::forward(f), std::forward(b), std::forward(a)); + } + }; + inline constexpr auto fflip = curry(fflip_t{}); + + // + // fpipe + // + + struct fpipe_t { + template < typename G, typename F, typename A > + constexpr auto operator()(G&& g, F&& f, A&& a) const { + return curry( + std::forward(f), + curry(std::forward(g), std::forward(a))); + } + }; + inline constexpr auto fpipe = curry(fpipe_t{}); + + // + // fcompose + // + + struct fcompose_t { + template < typename G, typename F, typename A > + constexpr auto operator()(G&& g, F&& f, A&& a) const { + return curry( + std::forward(g), + curry(std::forward(f), std::forward(a))); + } + }; + inline constexpr auto fcompose = curry(fcompose_t{}); + + // + // fpipe operators + // + + template < typename G, typename F + , std::enable_if_t>, + is_curried>>, int> = 0 > + constexpr auto operator|(G&& g, F&& f) { + constexpr bool gc = is_curried_v>; + constexpr bool fc = is_curried_v>; + + if constexpr ( gc && fc ) { + return fpipe(std::forward(g), std::forward(f)); + } + + if constexpr ( gc && !fc) { + return std::forward(g)(std::forward(f)); + } + + if constexpr ( !gc && fc) { + return std::forward(f)(std::forward(g)); + } + + static_assert(gc || fc, "F or G or both arguments should be curried"); + } + + // + // fcompose operators + // + + template < typename G, typename F + , std::enable_if_t>, + is_curried>>, int> = 0 > + constexpr auto operator*(G&& g, F&& f) { + constexpr bool gc = is_curried_v>; + constexpr bool fc = is_curried_v>; + + if constexpr ( gc && fc ) { + return fcompose(std::forward(g), std::forward(f)); + } + + if constexpr ( gc && !fc) { + return std::forward(g)(std::forward(f)); + } + + if constexpr ( !gc && fc) { + return std::forward(f)(std::forward(g)); + } + + static_assert(gc || fc, "F or G or both arguments should be curried"); + } +} + +namespace kari_hpp::ext::underscore +{ + struct us_t {}; + inline constexpr us_t _{}; + + // + // is_underscore, is_underscore_v + // + + template < typename T > + struct is_underscore + : std::bool_constant>> {}; + + template < typename T > + inline constexpr bool is_underscore_v = is_underscore::value; + + // + // unary operators + // + + #define KARI_HPP_DEFINE_UNDERSCORE_UNARY_OP(op, func)\ + constexpr auto operator op (us_t) {\ + return curry(func);\ + } + + KARI_HPP_DEFINE_UNDERSCORE_UNARY_OP(-, std::negate<>()) + KARI_HPP_DEFINE_UNDERSCORE_UNARY_OP(~, std::bit_not<>()) + KARI_HPP_DEFINE_UNDERSCORE_UNARY_OP(!, std::logical_not<>()) + #undef KARI_HPP_DEFINE_UNDERSCORE_UNARY_OP + + // + // binary operators + // + + #define KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(op, func)\ + constexpr auto operator op (us_t, us_t) {\ + return curry(func);\ + }\ + \ + template < typename A, std::enable_if_t>, int> = 0 >\ + constexpr auto operator op (A&& a, us_t) {\ + return curry(func, std::forward(a));\ + }\ + \ + template < typename B, std::enable_if_t>, int> = 0 >\ + constexpr auto operator op (us_t, B&& b) {\ + return fflip(func, std::forward(b));\ + } + + KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(+ , std::plus<>()) + KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(- , std::minus<>()) + KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(* , std::multiplies<>()) + KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(/ , std::divides<>()) + KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(% , std::modulus<>()) + + KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(< , std::less<>()) + KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(> , std::greater<>()) + KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(<=, std::less_equal<>()) + KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(>=, std::greater_equal<>()) + + KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(==, std::equal_to<>()) + KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(!=, std::not_equal_to<>()) + + KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(| , std::bit_or<>()) + KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(& , std::bit_and<>()) + KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(^ , std::bit_xor<>()) + + KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(||, std::logical_or<>()) + KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(&&, std::logical_and<>()) + #undef KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP +} diff --git a/headers/kari.hpp/kari_ext.hpp b/headers/kari.hpp/kari_ext.hpp deleted file mode 100644 index 8415a3e..0000000 --- a/headers/kari.hpp/kari_ext.hpp +++ /dev/null @@ -1,206 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/BlackMATov/kari.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2017-2020, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include "kari.hpp" - -#include -#include -#include - -namespace kari_hpp -{ - // - // fid - // - - struct fid_t { - template < typename A > - constexpr auto operator()(A&& a) const { - return std::forward(a); - } - }; - inline constexpr auto fid = curry(fid_t{}); - - // - // fconst - // - - struct fconst_t { - template < typename A, typename B > - constexpr auto operator()(A&& a, [[maybe_unused]] B&& b) const { - return std::forward(a); - } - }; - inline constexpr auto fconst = curry(fconst_t{}); - - // - // fflip - // - - struct fflip_t { - template < typename F, typename A, typename B > - constexpr auto operator()(F&& f, A&& a, B&& b) const { - return curry(std::forward(f), std::forward(b), std::forward(a)); - } - }; - inline constexpr auto fflip = curry(fflip_t{}); - - // - // fpipe - // - - struct fpipe_t { - template < typename G, typename F, typename A > - constexpr auto operator()(G&& g, F&& f, A&& a) const { - return curry( - std::forward(f), - curry(std::forward(g), std::forward(a))); - } - }; - inline constexpr auto fpipe = curry(fpipe_t{}); - - // - // fcompose - // - - struct fcompose_t { - template < typename G, typename F, typename A > - constexpr auto operator()(G&& g, F&& f, A&& a) const { - return curry( - std::forward(g), - curry(std::forward(f), std::forward(a))); - } - }; - inline constexpr auto fcompose = curry(fcompose_t{}); - - // - // fpipe operators - // - - template < typename G, typename F - , std::enable_if_t>, - is_curried>>, int> = 0 > - constexpr auto operator|(G&& g, F&& f) { - constexpr bool gc = is_curried_v>; - constexpr bool fc = is_curried_v>; - - if constexpr ( gc && fc ) { - return fpipe(std::forward(g), std::forward(f)); - } - - if constexpr ( gc && !fc) { - return std::forward(g)(std::forward(f)); - } - - if constexpr ( !gc && fc) { - return std::forward(f)(std::forward(g)); - } - - static_assert(gc || fc, "F or G or both arguments should be curried"); - } - - // - // fcompose operators - // - - template < typename G, typename F - , std::enable_if_t>, - is_curried>>, int> = 0 > - constexpr auto operator*(G&& g, F&& f) { - constexpr bool gc = is_curried_v>; - constexpr bool fc = is_curried_v>; - - if constexpr ( gc && fc ) { - return fcompose(std::forward(g), std::forward(f)); - } - - if constexpr ( gc && !fc) { - return std::forward(g)(std::forward(f)); - } - - if constexpr ( !gc && fc) { - return std::forward(f)(std::forward(g)); - } - - static_assert(gc || fc, "F or G or both arguments should be curried"); - } -} - -namespace kari_hpp::underscore -{ - struct us_t {}; - inline constexpr us_t _{}; - - // - // is_underscore, is_underscore_v - // - - template < typename T > - struct is_underscore - : std::bool_constant>> {}; - - template < typename T > - inline constexpr bool is_underscore_v = is_underscore::value; - - // - // unary operators - // - - #define KARI_HPP_DEFINE_UNDERSCORE_UNARY_OP(op, func)\ - constexpr auto operator op (us_t) {\ - return curry(func);\ - } - - KARI_HPP_DEFINE_UNDERSCORE_UNARY_OP(-, std::negate<>()) - KARI_HPP_DEFINE_UNDERSCORE_UNARY_OP(~, std::bit_not<>()) - KARI_HPP_DEFINE_UNDERSCORE_UNARY_OP(!, std::logical_not<>()) - #undef KARI_HPP_DEFINE_UNDERSCORE_UNARY_OP - - // - // binary operators - // - - #define KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(op, func)\ - constexpr auto operator op (us_t, us_t) {\ - return curry(func);\ - }\ - \ - template < typename A, std::enable_if_t>, int> = 0 >\ - constexpr auto operator op (A&& a, us_t) {\ - return curry(func, std::forward(a));\ - }\ - \ - template < typename B, std::enable_if_t>, int> = 0 >\ - constexpr auto operator op (us_t, B&& b) {\ - return fflip(func, std::forward(b));\ - } - - KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(+ , std::plus<>()) - KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(- , std::minus<>()) - KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(* , std::multiplies<>()) - KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(/ , std::divides<>()) - KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(% , std::modulus<>()) - - KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(< , std::less<>()) - KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(> , std::greater<>()) - KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(<=, std::less_equal<>()) - KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(>=, std::greater_equal<>()) - - KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(==, std::equal_to<>()) - KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(!=, std::not_equal_to<>()) - - KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(| , std::bit_or<>()) - KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(& , std::bit_and<>()) - KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(^ , std::bit_xor<>()) - - KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(||, std::logical_or<>()) - KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP(&&, std::logical_and<>()) - #undef KARI_HPP_DEFINE_UNDERSCORE_BINARY_OP -} diff --git a/untests/kari_ext_tests.cpp b/untests/kari_ext_tests.cpp index 4cf04da..a805fe0 100644 --- a/untests/kari_ext_tests.cpp +++ b/untests/kari_ext_tests.cpp @@ -4,10 +4,11 @@ * Copyright (C) 2017-2020, by Matvey Cherevko (blackmatov@gmail.com) ******************************************************************************/ -#include +#include #include "doctest/doctest.hpp" using namespace kari_hpp; +using namespace kari_hpp::ext; TEST_CASE("kari_ext") { struct box final {