From d36ab3e517c28a46bce8ea137c7622292661790d Mon Sep 17 00:00:00 2001 From: badair Date: Wed, 30 Mar 2016 00:58:29 -0500 Subject: [PATCH] adding common_signature --- include/callable_traits/config.hpp | 1 + include/callable_traits/detail/at.hpp | 38 ++++++ include/callable_traits/detail/best_match.hpp | 12 +- .../detail/bind_expression_parser.hpp | 11 +- .../callable_traits/detail/build_function.hpp | 30 +++++ .../detail/common_signature_t.hpp | 120 ++++++++++++++++++ include/callable_traits/detail/traits.hpp | 5 +- include/callable_traits/interface.hpp | 10 ++ ...ak_common_type.cpp => best_match_bind.cpp} | 0 test/can_invoke_constexpr.cpp | 7 + test/common_signature.cpp | 75 +++++++++++ test/detail/make_constexpr.cpp | 12 ++ test/is_constexpr.cpp | 7 + 13 files changed, 312 insertions(+), 16 deletions(-) create mode 100644 include/callable_traits/detail/at.hpp create mode 100644 include/callable_traits/detail/build_function.hpp create mode 100644 include/callable_traits/detail/common_signature_t.hpp rename test/{weak_common_type.cpp => best_match_bind.cpp} (100%) create mode 100644 test/common_signature.cpp diff --git a/include/callable_traits/config.hpp b/include/callable_traits/config.hpp index b97d745..d78fe24 100644 --- a/include/callable_traits/config.hpp +++ b/include/callable_traits/config.hpp @@ -20,6 +20,7 @@ Distributed under the Boost Software License, Version 1.0. #undef CALLABLE_TRAITS_VARARGS_CC #define CALLABLE_TRAITS_VARARGS_CC __cdecl #define CALLABLE_TRAITS_CONSTEXPR_CHECKS_DISABLED +#define CALLABLE_TRAITS_MSVC #endif //ifndef __clang__ #endif //_MSC_VER diff --git a/include/callable_traits/detail/at.hpp b/include/callable_traits/detail/at.hpp new file mode 100644 index 0000000..572706a --- /dev/null +++ b/include/callable_traits/detail/at.hpp @@ -0,0 +1,38 @@ +/*! +Copyright (c) 2016 Barrett Adair + +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 CALLABLE_TRAITS_DETAIL_AT_HPP +#define CALLABLE_TRAITS_DETAIL_AT_HPP + +#include +#include +#include + +namespace callable_traits { + + namespace detail { + + template + using at = typename std::tuple_element::type; + + template + struct weak_at_t { + using type = at; + }; + + template + struct weak_at_t= std::tuple_size::value>>{ + using type = invalid_type; + }; + + template + using weak_at = typename weak_at_t::type; + + } +} + +#endif diff --git a/include/callable_traits/detail/best_match.hpp b/include/callable_traits/detail/best_match.hpp index ee52367..75beff6 100644 --- a/include/callable_traits/detail/best_match.hpp +++ b/include/callable_traits/detail/best_match.hpp @@ -108,14 +108,16 @@ namespace callable_traits { }; template - using sorted_cartesian_product_of_conversions = tuple_sort< - std::tuple...>, - conversion_result_sort_predicate - >; + struct sorted_cartesian_product_of_conversions { + using type = tuple_sort< + std::tuple...>, + conversion_result_sort_predicate + >; + }; template using best_conversion_result = - typename std::tuple_element<0, sorted_cartesian_product_of_conversions>::type; + typename std::tuple_element<0, typename sorted_cartesian_product_of_conversions::type>::type; template using best_match = typename best_conversion_result::key; diff --git a/include/callable_traits/detail/bind_expression_parser.hpp b/include/callable_traits/detail/bind_expression_parser.hpp index 2095a81..0e934a4 100644 --- a/include/callable_traits/detail/bind_expression_parser.hpp +++ b/include/callable_traits/detail/bind_expression_parser.hpp @@ -15,6 +15,7 @@ Distributed under the Boost Software License, Version 1.0. #include #include #include +#include #include #include @@ -111,14 +112,6 @@ namespace callable_traits { using type = std::tuple<>; }; - template - struct build_function {}; - - template - struct build_function>{ - using type = Return(Args...); - }; - template struct bind_expression_parser { @@ -150,7 +143,7 @@ namespace callable_traits { using arg_types = typename common_expected_arg_types::type; using return_type = typename root_expression::return_type; - using function_type = typename build_function::type; + using function_type = build_function; using abominable_type = function_type; }; } diff --git a/include/callable_traits/detail/build_function.hpp b/include/callable_traits/detail/build_function.hpp new file mode 100644 index 0000000..e1b2ac5 --- /dev/null +++ b/include/callable_traits/detail/build_function.hpp @@ -0,0 +1,30 @@ +/*! +Copyright (c) 2016 Barrett Adair + +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 CALLABLE_TRAITS_DETAIL_BUILD_FUNCTION_HPP +#define CALLABLE_TRAITS_DETAIL_BUILD_FUNCTION_HPP + +#include + +namespace callable_traits { + + namespace detail { + + template + struct build_function_t; + + template + struct build_function_t>{ + using type = Return(Args...); + }; + + template + using build_function = typename build_function_t::type; + } +} + +#endif diff --git a/include/callable_traits/detail/common_signature_t.hpp b/include/callable_traits/detail/common_signature_t.hpp new file mode 100644 index 0000000..4b19ed5 --- /dev/null +++ b/include/callable_traits/detail/common_signature_t.hpp @@ -0,0 +1,120 @@ +/*! +Copyright (c) 2016 Barrett Adair + +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 CALLABLE_TRAITS_DETAIL_COMMON_SIGNATURE_T_HPP +#define CALLABLE_TRAITS_DETAIL_COMMON_SIGNATURE_T_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace callable_traits { + + namespace detail { + + template + struct reverse_impl; + + template + struct reverse_impl> { + using type = std::tuple...>; + }; + + template + using reverse = typename reverse_impl::value>>::type; + + template + struct trim_left; + + template + struct trim_left, EndSize> { + using type = typename std::conditional< + EndSize == 1, + std::tuple, + std::tuple<> + >::type; + }; + + template + struct trim_left, EndSize> { + using type = std::tuple<>; + }; + + template + struct trim_left, EndSize> { + + using type = typename std::conditional< + EndSize == sizeof...(Args) + 1, + std::tuple, + typename trim_left, EndSize>::type + >::type; + }; + + template + struct trim_right { + using reversed = reverse; + using type = reverse::type>; + }; + + template + struct best_match_cross_section; + + template + struct best_match_cross_section>{ + using type = best_match>...>; + }; + + template + struct common_args; + + template + struct common_args> { + using seq = std::index_sequence; + using type = std::tuple::type...>; + }; + + template + struct common_signature_t; + + template + struct common_signature_t> { + + using common_return = typename std::common_type< + typename at::return_type... + >::type; + + using args_tuples = std::tuple< + typename at::arg_types... + >; + + using first_args = at<0, args_tuples>; + + using arg_count = std::tuple_size; + + using seq = std::make_index_sequence< + arg_count::value <= sizeof...(I) ? sizeof...(I) : arg_count::value + >; + + using common_arg_types = typename common_args::type; + using trimmed_arg_types = typename trim_right< + common_arg_types, arg_count::value>::type; + + using type = build_function; + }; + } +} + +#endif diff --git a/include/callable_traits/detail/traits.hpp b/include/callable_traits/detail/traits.hpp index 00148a0..0fd92e8 100644 --- a/include/callable_traits/detail/traits.hpp +++ b/include/callable_traits/detail/traits.hpp @@ -26,9 +26,10 @@ namespace callable_traits { namespace detail { - template::type> + template using decay_if_ptr_or_integral_constant = typename std::conditional< - std::is_pointer::value || is_integral_constant::value, + std::is_pointer::type>::value + || is_integral_constant::value, shallow_decay, T >::type; diff --git a/include/callable_traits/interface.hpp b/include/callable_traits/interface.hpp index a9e92ad..fcdea8c 100644 --- a/include/callable_traits/interface.hpp +++ b/include/callable_traits/interface.hpp @@ -22,6 +22,7 @@ Distributed under the Boost Software License, Version 1.0. #include #include #include +#include #include #include @@ -44,6 +45,12 @@ namespace callable_traits { template using qualified_signature = typename detail::traits::abominable_type; + template + using common_signature = typename detail::common_signature_t< + std::tuple...>, + std::make_index_sequence + >::type; + template using result_of = typename detail::traits::return_type; @@ -114,6 +121,9 @@ namespace callable_traits { template using qualified_signature = detail::if_valid>; + template + using common_signature = no_sfinae::common_signature; + template using result_of = detail::if_valid>; diff --git a/test/weak_common_type.cpp b/test/best_match_bind.cpp similarity index 100% rename from test/weak_common_type.cpp rename to test/best_match_bind.cpp diff --git a/test/can_invoke_constexpr.cpp b/test/can_invoke_constexpr.cpp index 3dab55a..58c8473 100644 --- a/test/can_invoke_constexpr.cpp +++ b/test/can_invoke_constexpr.cpp @@ -1,3 +1,10 @@ +/*! +Copyright (c) 2016 Barrett Adair + +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 diff --git a/test/common_signature.cpp b/test/common_signature.cpp new file mode 100644 index 0000000..cc42bff --- /dev/null +++ b/test/common_signature.cpp @@ -0,0 +1,75 @@ +/*! +Copyright (c) 2016 Barrett Adair + +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 + +#ifndef CT_ASSERT +#define CT_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) +#endif //CT_ASSERT + +namespace ct = callable_traits; + +//ct::common_signature makes MSVC crash :( +#ifndef CALLABLE_TRAITS_MSVC + +namespace test1 { + + using test = ct::common_signature< + char(int), + short(int&&), + int(const int&) + >; + + using expect = int(int); + + CT_ASSERT(std::is_same::value); +} + +namespace test2 { + + using test = ct::common_signature< + char(), + int() + >; + + using expect = int(); + + CT_ASSERT(std::is_same::value); +} + +namespace test3 { + + struct Vampire {}; + struct Robot {}; + struct Animal {}; + struct Dog : Animal {}; + struct Poodle : Dog {}; + struct VampireRobotPoodle : Poodle, Robot, Vampire {}; + + using test = ct::common_signature< + Dog(VampireRobotPoodle, Vampire, Robot, Dog, Animal), + Poodle(Vampire, VampireRobotPoodle, Robot, Dog, Animal), + Poodle(Vampire, Robot, VampireRobotPoodle, Dog, Animal), + VampireRobotPoodle(Vampire, Robot, Dog, VampireRobotPoodle, Animal), + Animal(Vampire, Robot, Dog, Animal, VampireRobotPoodle) + >; + + using expect = Animal( + VampireRobotPoodle, + VampireRobotPoodle, + VampireRobotPoodle, + VampireRobotPoodle, + VampireRobotPoodle + ); + + CT_ASSERT(std::is_same::value); +} + +#endif + +int main() { return 0; } diff --git a/test/detail/make_constexpr.cpp b/test/detail/make_constexpr.cpp index 4c1c082..eeddba8 100644 --- a/test/detail/make_constexpr.cpp +++ b/test/detail/make_constexpr.cpp @@ -1,9 +1,19 @@ +/*! +Copyright (c) 2016 Barrett Adair + +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 #ifndef CT_ASSERT #define CT_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) #endif //CT_ASSERT +#ifndef CALLABLE_TRAITS_CONSTEXPR_CHECKS_DISABLED + struct foo { constexpr int operator()(int&) & { @@ -84,4 +94,6 @@ CT_ASSERT(12 == CALLABLE_TRAITS_MAKE_CONSTEXPR(const foo)(CALLABLE_TRAITS_MAKE_C CT_ASSERT(12 == CALLABLE_TRAITS_MAKE_CONSTEXPR(const foo&&)(CALLABLE_TRAITS_MAKE_CONSTEXPR(int))); CT_ASSERT(12 == CALLABLE_TRAITS_MAKE_CONSTEXPR(const foo)(CALLABLE_TRAITS_MAKE_CONSTEXPR(int))); +#endif + int main() { return 0; } \ No newline at end of file diff --git a/test/is_constexpr.cpp b/test/is_constexpr.cpp index c1235b2..cff0c36 100644 --- a/test/is_constexpr.cpp +++ b/test/is_constexpr.cpp @@ -1,3 +1,10 @@ +/*! +Copyright (c) 2016 Barrett Adair + +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