From 5de2361d0042f636b04596450359e9b7ddee7a1c Mon Sep 17 00:00:00 2001 From: badair Date: Wed, 25 May 2016 15:44:36 -0500 Subject: [PATCH] adding tests, make_function --- bind_parser.hpp | 50 ++++++++++++++++++++--- test/best_match.cpp | 36 ++++++++++++++++ test/flatten_bind_expressions.cpp | 68 +++++++++++++++++++++++++++++++ test/make_function.hpp | 55 ------------------------- test/make_function_example.cpp | 7 ++-- 5 files changed, 151 insertions(+), 65 deletions(-) create mode 100644 test/best_match.cpp create mode 100644 test/flatten_bind_expressions.cpp delete mode 100644 test/make_function.hpp diff --git a/bind_parser.hpp b/bind_parser.hpp index 096582d..0221b89 100644 --- a/bind_parser.hpp +++ b/bind_parser.hpp @@ -17,6 +17,7 @@ Distributed under the Boost Software License, Version 1.0. #include #include #include +#include namespace bind_parser { @@ -824,6 +825,7 @@ namespace bind_parser { struct bind_expression_parser { static constexpr const bool value = false; + using arg_types = invalid_type; using return_type = invalid_type; using function_type = invalid_type; @@ -854,6 +856,15 @@ namespace bind_parser { }; } + template + using args = typename detail::bind_expression_parser::args; + + template + using result_of = typename detail::bind_expression_parser::return_type; + + template + using function_type = typename detail::bind_expression_parser::function_type; + template inline constexpr auto bind(T&& t, Args&&... args) -> @@ -865,14 +876,41 @@ namespace bind_parser { }; } - template - using args = typename detail::bind_expression_parser::args; + // make_function turns a non-overloaded callable into a type-erased std::function object + template + inline decltype(auto) make_function(T&& t) { - template - using result_of = typename detail::bind_expression_parser::return_type; + using no_ref = typename ::std::remove_reference::type; + using f = ::callable_traits::function_type; + return ::std::function{ ::std::forward(t) }; + } - template - using function_type = typename detail::bind_expression_parser::function_type; + // this make_function overload turns a bind expression into a type-erased std::function object + template + inline decltype(auto) make_function(T&& t, First&& first, Others&&... others) { + + // bind_parser::bind is a compile-time parser of placeholder expressions, + // for the purpose of retaining more type information than std::bind normally + // allows - specifically, bind_parser::bind is used to determine the de-facto + // signature of the std::bind return type, with special considerations for + // conversions between reused placeholders and nested placeholder expressions. + // For the sake of convenience, bind_parser::bind is also a thin forwarding + // wrapper around std::bind. + + using bind_expr = decltype( ::bind_parser::bind( + ::std::forward(t), + ::std::forward(first), + ::std::forward(others)... + )); + + using f = ::bind_parser::function_type; + + return ::std::function{ ::std::bind( + ::std::forward(t), + ::std::forward(first), + ::std::forward(others)... + )}; + } } #endif //#ifndef BIND_PARSER_HPP diff --git a/test/best_match.cpp b/test/best_match.cpp new file mode 100644 index 0000000..4ff0488 --- /dev/null +++ b/test/best_match.cpp @@ -0,0 +1,36 @@ +/* + +Copyright Barrett Adair 2016 +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "bind_parser.hpp" + +struct Vampire {}; +struct Robot {}; +struct Animal {}; +struct Dog : Animal {}; +struct Poodle : Dog {}; +struct ScaryMonster : Poodle, Robot, Vampire {}; + +int main() { + + { + using test = bind_parser::detail::best_match< + Vampire, Robot, Poodle, Animal, Dog, ScaryMonster>; + + using expect = ScaryMonster; + + static_assert(std::is_same::value, ""); + } +} diff --git a/test/flatten_bind_expressions.cpp b/test/flatten_bind_expressions.cpp new file mode 100644 index 0000000..c0d010d --- /dev/null +++ b/test/flatten_bind_expressions.cpp @@ -0,0 +1,68 @@ +/* + +Copyright Barrett Adair 2016 +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "bind_parser.hpp" + +using namespace std::placeholders; + +struct A {}; +struct B {}; +struct C {}; +struct D {}; +struct E {}; +struct F {}; +struct G {}; + +// functions `ordered_letters`, `BEEF_returns_D`, `BEEF_returns_G`, +// and `BEEF_returns_B` are used to set up a complex bind expression +// with bind + +auto ordered_letters(A, B, C, D, E, F, G) { + return 0; +} + +auto BEEF_returns_D(B, E, E, F) { + return D{}; +} + +auto BEEF_returns_G(B, E, E, F) { + return G{}; +} + +auto BEEF_returns_B(B, E, E, F) { + return B{}; +} + +#define INNER_3 bind_parser::bind(&BEEF_returns_B, B{}, _10, E{}, F{}) +#define INNER_2 bind_parser::bind(&BEEF_returns_G, INNER_3, _9, E{}, _8) +#define INNER_1 bind_parser::bind(&BEEF_returns_D, _2, E{}, _4, _7) + +int main() { + + auto root = bind_parser::bind(&ordered_letters, _1, _2, _3, INNER_1, _5, _6, INNER_2); + + using test = decltype(root)::flattened_bind_expressions; + + using expect = std::tuple< + decltype(root), + decltype(INNER_1), + decltype(INNER_2), + decltype(INNER_3) + >; + + static_assert(std::is_same::value, ""); + + return 0; +} diff --git a/test/make_function.hpp b/test/make_function.hpp deleted file mode 100644 index 50bcafa..0000000 --- a/test/make_function.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/*<- -Copyright Barrett Adair 2016 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http ://boost.org/LICENSE_1_0.txt) -->*/ - -#ifndef EXAMPLE_MAKE_FUNCTION_HPP -#define EXAMPLE_MAKE_FUNCTION_HPP - -#include -#include -#include - -#include "bind_parser.hpp" - -namespace example { - - // make_function turns a non-overloaded callable into a type-erased std::function object - template - inline decltype(auto) make_function(T&& t) { - - using no_ref = typename std::remove_reference::type; - using f = bind_parser::function_type; - using result_type = std::function; - return result_type{ std::forward(t) }; - } - - // this make_function overload turns a bind expression into a type-erased std::function object - template - inline decltype(auto) make_function(T&& t, First&& first, Others&&... others) { - - // bind_parser::bind is a compile-time parser of placeholder expressions, - // for the purpose of retaining more type information than std::bind normally - // allows - specifically, bind_parser::bind is used to determine the de-facto - // signature of the std::bind return type, with special considerations for - // conversions between reused placeholders and nested placeholder expressions. - // For the sake of convenience, bind_parser::bind is also a thin forwarding - // wrapper around std::bind. - - using bind_expr = decltype(bind_parser::bind( - std::forward(t), - std::forward(first), - std::forward(others)... - )); - - using f = bind_parser::function_type; - using result_type = std::function; - - return result_type{ std::bind( - std::forward(t), - std::forward(first), - std::forward(others)... - )}; - } -} diff --git a/test/make_function_example.cpp b/test/make_function_example.cpp index 375df1e..2d1cc39 100644 --- a/test/make_function_example.cpp +++ b/test/make_function_example.cpp @@ -3,15 +3,14 @@ Copyright Barrett Adair 2016 Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.md or copy at http ://boost.org/LICENSE_1_0.txt) ->*/ - -#undef NDEBUG +#undef NDEBUG #include #include -#include "make_function.hpp" +#include "bind_parser.hpp" -using namespace example; +using namespace bind_parser; using namespace std::placeholders; int add(int i, int j) {