From a9cb1035cc54cdde3bcba522acc0f31f675939b5 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 9 Dec 2020 14:28:15 +0700 Subject: [PATCH] separate core and ext functional --- headers/kari.hpp/kari.hpp | 216 ------------------------------- headers/kari.hpp/kari_ext.hpp | 234 ++++++++++++++++++++++++++++++++++ untests/kari_ext_tests.cpp | 50 ++++++++ untests/kari_tests.cpp | 89 ------------- 4 files changed, 284 insertions(+), 305 deletions(-) create mode 100644 headers/kari.hpp/kari_ext.hpp create mode 100644 untests/kari_ext_tests.cpp diff --git a/headers/kari.hpp/kari.hpp b/headers/kari.hpp/kari.hpp index 4a17abd..622f7eb 100644 --- a/headers/kari.hpp/kari.hpp +++ b/headers/kari.hpp/kari.hpp @@ -252,221 +252,5 @@ namespace kari curryN(std::forward(f))(std::forward(a), std::forward(as)...)) } -namespace kari -{ - // - // fid - // - - struct fid_t { - template < typename A > - constexpr auto operator()(A&& a) const - KARI_HPP_NOEXCEPT_DECLTYPE_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, B&&) const - KARI_HPP_NOEXCEPT_DECLTYPE_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 - KARI_HPP_NOEXCEPT_DECLTYPE_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 - KARI_HPP_NOEXCEPT_DECLTYPE_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 - KARI_HPP_NOEXCEPT_DECLTYPE_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, - typename std::enable_if_t>, int> = 0, - typename std::enable_if_t>, int> = 0 - > - constexpr auto operator|(G&& g, F&& f) - KARI_HPP_NOEXCEPT_DECLTYPE_RETURN( - fpipe( - std::forward(g), - std::forward(f))) - - template - < - typename F, typename A, - typename std::enable_if_t< is_curried_v>, int> = 0, - typename std::enable_if_t>, int> = 0 - > - constexpr auto operator|(F&& f, A&& a) - KARI_HPP_NOEXCEPT_DECLTYPE_RETURN( - std::forward(f)(std::forward(a))) - - template - < - typename A, typename F, - typename std::enable_if_t>, int> = 0, - typename std::enable_if_t< is_curried_v>, int> = 0 - > - constexpr auto operator|(A&& a, F&& f) - KARI_HPP_NOEXCEPT_DECLTYPE_RETURN( - std::forward(f)(std::forward(a))) - - // - // fcompose operators - // - - template - < - typename G, typename F, - typename std::enable_if_t>, int> = 0, - typename std::enable_if_t>, int> = 0 - > - constexpr auto operator*(G&& g, F&& f) - KARI_HPP_NOEXCEPT_DECLTYPE_RETURN( - fcompose( - std::forward(g), - std::forward(f))) - - template - < - typename F, typename A, - typename std::enable_if_t< is_curried_v>, int> = 0, - typename std::enable_if_t>, int> = 0 - > - constexpr auto operator*(F&& f, A&& a) - KARI_HPP_NOEXCEPT_DECLTYPE_RETURN( - std::forward(f)(std::forward(a))) - - template - < - typename A, typename F, - typename std::enable_if_t>, int> = 0, - typename std::enable_if_t< is_curried_v>, int> = 0 - > - constexpr auto operator*(A&& a, F&& f) - KARI_HPP_NOEXCEPT_DECLTYPE_RETURN( - std::forward(f)(std::forward(a))) -} - -namespace kari -{ - namespace 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) KARI_HPP_NOEXCEPT_DECLTYPE_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) \ - KARI_HPP_NOEXCEPT_DECLTYPE_RETURN(curry(func)) \ - \ - template < typename A, typename std::enable_if_t>, int> = 0 > \ - constexpr auto operator op (A&& a, us_t) \ - KARI_HPP_NOEXCEPT_DECLTYPE_RETURN(curry(func, std::forward(a))) \ - \ - template < typename B, typename std::enable_if_t>, int> = 0 > \ - constexpr auto operator op (us_t, B&& b) \ - KARI_HPP_NOEXCEPT_DECLTYPE_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 - } -} - #undef KARI_HPP_NOEXCEPT_RETURN #undef KARI_HPP_NOEXCEPT_DECLTYPE_RETURN diff --git a/headers/kari.hpp/kari_ext.hpp b/headers/kari.hpp/kari_ext.hpp new file mode 100644 index 0000000..2311124 --- /dev/null +++ b/headers/kari.hpp/kari_ext.hpp @@ -0,0 +1,234 @@ +/******************************************************************************* + * 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" + +#define KARI_HPP_NOEXCEPT_RETURN(...) \ + noexcept(noexcept(__VA_ARGS__)) { return __VA_ARGS__; } + +#define KARI_HPP_NOEXCEPT_DECLTYPE_RETURN(...) \ + noexcept(noexcept(__VA_ARGS__)) -> decltype (__VA_ARGS__) { return __VA_ARGS__; } + +namespace kari +{ + // + // fid + // + + struct fid_t { + template < typename A > + constexpr auto operator()(A&& a) const + KARI_HPP_NOEXCEPT_DECLTYPE_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, B&&) const + KARI_HPP_NOEXCEPT_DECLTYPE_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 + KARI_HPP_NOEXCEPT_DECLTYPE_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 + KARI_HPP_NOEXCEPT_DECLTYPE_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 + KARI_HPP_NOEXCEPT_DECLTYPE_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, + typename std::enable_if_t>, int> = 0, + typename std::enable_if_t>, int> = 0 + > + constexpr auto operator|(G&& g, F&& f) + KARI_HPP_NOEXCEPT_DECLTYPE_RETURN( + fpipe( + std::forward(g), + std::forward(f))) + + template + < + typename F, typename A, + typename std::enable_if_t< is_curried_v>, int> = 0, + typename std::enable_if_t>, int> = 0 + > + constexpr auto operator|(F&& f, A&& a) + KARI_HPP_NOEXCEPT_DECLTYPE_RETURN( + std::forward(f)(std::forward(a))) + + template + < + typename A, typename F, + typename std::enable_if_t>, int> = 0, + typename std::enable_if_t< is_curried_v>, int> = 0 + > + constexpr auto operator|(A&& a, F&& f) + KARI_HPP_NOEXCEPT_DECLTYPE_RETURN( + std::forward(f)(std::forward(a))) + + // + // fcompose operators + // + + template + < + typename G, typename F, + typename std::enable_if_t>, int> = 0, + typename std::enable_if_t>, int> = 0 + > + constexpr auto operator*(G&& g, F&& f) + KARI_HPP_NOEXCEPT_DECLTYPE_RETURN( + fcompose( + std::forward(g), + std::forward(f))) + + template + < + typename F, typename A, + typename std::enable_if_t< is_curried_v>, int> = 0, + typename std::enable_if_t>, int> = 0 + > + constexpr auto operator*(F&& f, A&& a) + KARI_HPP_NOEXCEPT_DECLTYPE_RETURN( + std::forward(f)(std::forward(a))) + + template + < + typename A, typename F, + typename std::enable_if_t>, int> = 0, + typename std::enable_if_t< is_curried_v>, int> = 0 + > + constexpr auto operator*(A&& a, F&& f) + KARI_HPP_NOEXCEPT_DECLTYPE_RETURN( + std::forward(f)(std::forward(a))) +} + +namespace kari +{ + namespace 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) KARI_HPP_NOEXCEPT_DECLTYPE_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) \ + KARI_HPP_NOEXCEPT_DECLTYPE_RETURN(curry(func)) \ + \ + template < typename A, typename std::enable_if_t>, int> = 0 > \ + constexpr auto operator op (A&& a, us_t) \ + KARI_HPP_NOEXCEPT_DECLTYPE_RETURN(curry(func, std::forward(a))) \ + \ + template < typename B, typename std::enable_if_t>, int> = 0 > \ + constexpr auto operator op (us_t, B&& b) \ + KARI_HPP_NOEXCEPT_DECLTYPE_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 + } +} + +#undef KARI_HPP_NOEXCEPT_RETURN +#undef KARI_HPP_NOEXCEPT_DECLTYPE_RETURN diff --git a/untests/kari_ext_tests.cpp b/untests/kari_ext_tests.cpp new file mode 100644 index 0000000..d6f9d11 --- /dev/null +++ b/untests/kari_ext_tests.cpp @@ -0,0 +1,50 @@ +/******************************************************************************* + * 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) + ******************************************************************************/ + +#include +#include "doctest/doctest.hpp" + +using namespace kari; + +TEST_CASE("kari_feature") { + SUBCASE("underscore") { + using namespace kari::underscore; + REQUIRE((-_)(40) == -40); + + REQUIRE((_ + 40)(2) == 42); + REQUIRE((_ - 2)(44) == 42); + REQUIRE((_ * 21)(2) == 42); + REQUIRE((_ / 2)(84) == 42); + REQUIRE((_ % 100)(142) == 42); + + REQUIRE((_ == 42)(42)); + REQUIRE((_ != 42)(40)); + REQUIRE_FALSE((_ == 42)(40)); + REQUIRE_FALSE((_ != 42)(42)); + + REQUIRE((40 + _)(2) == 42); + REQUIRE((44 - _)(2) == 42); + REQUIRE((21 * _)(2) == 42); + REQUIRE((84 / _)(2) == 42); + REQUIRE((142 % _)(100) == 42); + + REQUIRE((42 == _)(42)); + REQUIRE((42 != _)(40)); + REQUIRE_FALSE((42 == _)(40)); + REQUIRE_FALSE((42 != _)(42)); + + REQUIRE((_ + _)(40,2) == 42); + REQUIRE((_ - _)(44,2) == 42); + REQUIRE((_ * _)(21,2) == 42); + REQUIRE((_ / _)(84,2) == 42); + REQUIRE((_ % _)(142,100) == 42); + + REQUIRE((_ == _)(42,42)); + REQUIRE((_ != _)(42,40)); + REQUIRE_FALSE((_ == _)(42,40)); + REQUIRE_FALSE((_ != _)(42,42)); + } +} diff --git a/untests/kari_tests.cpp b/untests/kari_tests.cpp index 02261cd..0a900cb 100644 --- a/untests/kari_tests.cpp +++ b/untests/kari_tests.cpp @@ -195,43 +195,6 @@ namespace using namespace kari; TEST_CASE("kari_feature") { - SUBCASE("underscore") { - using namespace kari::underscore; - REQUIRE((-_)(40) == -40); - - REQUIRE((_ + 40)(2) == 42); - REQUIRE((_ - 2)(44) == 42); - REQUIRE((_ * 21)(2) == 42); - REQUIRE((_ / 2)(84) == 42); - REQUIRE((_ % 100)(142) == 42); - - REQUIRE((_ == 42)(42)); - REQUIRE((_ != 42)(40)); - REQUIRE_FALSE((_ == 42)(40)); - REQUIRE_FALSE((_ != 42)(42)); - - REQUIRE((40 + _)(2) == 42); - REQUIRE((44 - _)(2) == 42); - REQUIRE((21 * _)(2) == 42); - REQUIRE((84 / _)(2) == 42); - REQUIRE((142 % _)(100) == 42); - - REQUIRE((42 == _)(42)); - REQUIRE((42 != _)(40)); - REQUIRE_FALSE((42 == _)(40)); - REQUIRE_FALSE((42 != _)(42)); - - REQUIRE((_ + _)(40,2) == 42); - REQUIRE((_ - _)(44,2) == 42); - REQUIRE((_ * _)(21,2) == 42); - REQUIRE((_ / _)(84,2) == 42); - REQUIRE((_ % _)(142,100) == 42); - - REQUIRE((_ == _)(42,42)); - REQUIRE((_ != _)(42,40)); - REQUIRE_FALSE((_ == _)(42,40)); - REQUIRE_FALSE((_ != _)(42,42)); - } SUBCASE("ref_functor") { REQUIRE(curry(minus3_gf())(1,2,3) == -4); { @@ -624,58 +587,6 @@ TEST_CASE("kari") { } } -TEST_CASE("kari_helpers") { - SUBCASE("fid") { - REQUIRE(fid(box(10)).v() == 10); - } - SUBCASE("fconst") { - REQUIRE(fconst(box(10), 20).v() == 10); - { - auto b10 = fconst(box(10)); - REQUIRE(b10(20).v() == 10); - REQUIRE(std::move(b10)(30).v() == 10); - REQUIRE(b10(20).v() == 100500); - } - } - SUBCASE("fflip") { - REQUIRE(fflip(curry(std::minus<>()))(10, 20) == 10); - REQUIRE(fflip(minus3_gl)(10,20,50) == -40); - } - SUBCASE("fpipe") { - using namespace kari::underscore; - REQUIRE(fpipe(_+2, _*2, 4) == 12); - REQUIRE(((_+2) | (_*2) | 4) == 12); - REQUIRE((4 | (_+2) | (_*2)) == 12); - } - SUBCASE("fcompose") { - using namespace kari::underscore; - REQUIRE(fcompose(_+2, _*2, 4) == 10); - REQUIRE((_+2) * (_*2) * 4 == 10); - REQUIRE(4 * (_+2) * (_*2) == 12); - { - const auto s3 = [](int v1, int v2, int v3){ - return v1 + v2 + v3; - }; - const auto c = curry(s3) * (_*2) * 10 * 20 * 30; - REQUIRE(c == 70); - } - { - // (. (+2)) (*2) $ 10 == 24 - int i = fflip(fcompose)(_+2, _*2, 10); - int j = (_*(_+2))(_*2)(10); - REQUIRE(i == 24); - REQUIRE(j == 24); - } - { - // ((+2) .) (*2) $ 10 == 24 - int i = fcompose(_+2)(_*2, 10); - int j = ((_+2) * _)(_*2)(10); - REQUIRE(i == 22); - REQUIRE(j == 22); - } - } -} - namespace kari_regression { namespace change_type_after_applying { template < typename C >