From bdca099908a4c25d26bab053ed5d77fd916dcae7 Mon Sep 17 00:00:00 2001 From: Michael Jones Date: Thu, 25 Sep 2025 14:11:26 -0500 Subject: [PATCH] Fixes #133 -- Add a way to retrieve parameter list without the class type --- example/non_invoke_args.cpp | 69 +++++++++++++ include/boost/callable_traits.hpp | 1 + .../detail/default_callable_traits.hpp | 3 + .../detail/function_object.hpp | 4 + include/boost/callable_traits/detail/pmd.hpp | 3 + .../callable_traits/detail/sfinae_errors.hpp | 3 + .../detail/unguarded/function_3.hpp | 10 +- .../detail/unguarded/function_ptr_3.hpp | 3 + .../unguarded/function_ptr_varargs_3.hpp | 3 + .../detail/unguarded/pmf_4.hpp | 5 +- .../detail/unguarded/pmf_varargs_4.hpp | 3 + .../boost/callable_traits/non_invoke_args.hpp | 98 +++++++++++++++++++ test/args.cpp | 37 ++++--- 13 files changed, 226 insertions(+), 16 deletions(-) create mode 100644 example/non_invoke_args.cpp create mode 100644 include/boost/callable_traits/non_invoke_args.hpp diff --git a/example/non_invoke_args.cpp b/example/non_invoke_args.cpp new file mode 100644 index 0000000..deaa13b --- /dev/null +++ b/example/non_invoke_args.cpp @@ -0,0 +1,69 @@ +/*<- +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 +#ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS +int main(){ return 0; } +#else + +//[ args +#include +#include +#include + +namespace ct = boost::callable_traits; + +template +void test(){ + using non_invoke_args_t = ct::non_invoke_args_t; + static_assert(std::is_same::value, ""); +} + +int main() { + + { + auto lamda = [](int, float&, const char*){}; + using lam = decltype(lamda); + using expect = std::tuple; + + test(); + } + + { + struct foo; + using pmf = void(foo::*)(int, float&, const char*); + using expect = std::tuple; + + test(); + } + + { + using function_ptr = void(*)(int, float&, const char*); + using expect = std::tuple; + test(); + } + + { + using function_ref = void(&)(int, float&, const char*); + using expect = std::tuple; + test(); + } + + { + using function = void(int, float&, const char*); + using expect = std::tuple; + test(); + } + + { + using abominable = void(int, float&, const char*) const; + using expect = std::tuple; + test(); + } +} +//] +#endif //#ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS diff --git a/include/boost/callable_traits.hpp b/include/boost/callable_traits.hpp index 87f0fa6..840ac1a 100644 --- a/include/boost/callable_traits.hpp +++ b/include/boost/callable_traits.hpp @@ -34,6 +34,7 @@ Distributed under the Boost Software License, Version 1.0. #include #include #include +#include #include #include #include diff --git a/include/boost/callable_traits/detail/default_callable_traits.hpp b/include/boost/callable_traits/detail/default_callable_traits.hpp index 8497078..658cae8 100644 --- a/include/boost/callable_traits/detail/default_callable_traits.hpp +++ b/include/boost/callable_traits/detail/default_callable_traits.hpp @@ -151,6 +151,9 @@ struct default_callable_traits { template class Container> using expand_args = error_t; + template class Container> + using expand_non_invoke_args = error_t; + template class Container, typename... RightArgs> using expand_args_left = error_t; diff --git a/include/boost/callable_traits/detail/function_object.hpp b/include/boost/callable_traits/detail/function_object.hpp index d12fc00..a196f5b 100644 --- a/include/boost/callable_traits/detail/function_object.hpp +++ b/include/boost/callable_traits/detail/function_object.hpp @@ -45,6 +45,10 @@ struct function_object : Base { using expand_args = typename function::template expand_args; + template class Container> + using expand_non_invoke_args = typename function::template + expand_non_invoke_args; + template class Container, typename... RightArgs> using expand_args_left = typename function::template expand_args_left; diff --git a/include/boost/callable_traits/detail/pmd.hpp b/include/boost/callable_traits/detail/pmd.hpp index 13a2c44..2e4b999 100644 --- a/include/boost/callable_traits/detail/pmd.hpp +++ b/include/boost/callable_traits/detail/pmd.hpp @@ -45,6 +45,9 @@ struct pmd : default_callable_traits<> { template class Container> using expand_args = Container; + template class Container> + using expand_non_invoke_args = Container<>; + using is_member_pointer = std::true_type; }; diff --git a/include/boost/callable_traits/detail/sfinae_errors.hpp b/include/boost/callable_traits/detail/sfinae_errors.hpp index 485d172..38aba0f 100644 --- a/include/boost/callable_traits/detail/sfinae_errors.hpp +++ b/include/boost/callable_traits/detail/sfinae_errors.hpp @@ -78,6 +78,9 @@ namespace boost { namespace callable_traits { BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(expand_args) BOOST_CLBL_TRTS_SFINAE_MSG(expand_args, cannot_expand_the_parameter_list_of_first_template_argument) + BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(expand_non_invoke_args) + BOOST_CLBL_TRTS_SFINAE_MSG(expand_non_invoke_args, cannot_expand_the_parameter_list_of_first_template_argument2) + BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(member_pointer_required) BOOST_CLBL_TRTS_SFINAE_MSG(member_pointer_required, type_is_not_a_member_pointer) diff --git a/include/boost/callable_traits/detail/unguarded/function_3.hpp b/include/boost/callable_traits/detail/unguarded/function_3.hpp index 2c329c4..b6a63f0 100644 --- a/include/boost/callable_traits/detail/unguarded/function_3.hpp +++ b/include/boost/callable_traits/detail/unguarded/function_3.hpp @@ -137,10 +137,13 @@ struct function class Container> using expand_args = Container; + template class Container> + using expand_non_invoke_args = Container; + using is_member_pointer = std::false_type; }; @@ -252,9 +255,12 @@ struct function class Container> using expand_args = Container; + + template class Container> + using expand_non_invoke_args = Container; using is_member_pointer = std::false_type; }; diff --git a/include/boost/callable_traits/detail/unguarded/function_ptr_3.hpp b/include/boost/callable_traits/detail/unguarded/function_ptr_3.hpp index e657b57..d155587 100644 --- a/include/boost/callable_traits/detail/unguarded/function_ptr_3.hpp +++ b/include/boost/callable_traits/detail/unguarded/function_ptr_3.hpp @@ -89,6 +89,9 @@ struct function< template class Container> using expand_args = Container; + template class Container> + using expand_non_invoke_args = Container; + using is_member_pointer = std::false_type; }; diff --git a/include/boost/callable_traits/detail/unguarded/function_ptr_varargs_3.hpp b/include/boost/callable_traits/detail/unguarded/function_ptr_varargs_3.hpp index 42e2293..f456efc 100644 --- a/include/boost/callable_traits/detail/unguarded/function_ptr_varargs_3.hpp +++ b/include/boost/callable_traits/detail/unguarded/function_ptr_varargs_3.hpp @@ -93,6 +93,9 @@ struct function class Container> using expand_args = Container; + template class Container> + using expand_non_invoke_args = Container; + using is_member_pointer = std::false_type; }; diff --git a/include/boost/callable_traits/detail/unguarded/pmf_4.hpp b/include/boost/callable_traits/detail/unguarded/pmf_4.hpp index 5a1f48c..3378dce 100644 --- a/include/boost/callable_traits/detail/unguarded/pmf_4.hpp +++ b/include/boost/callable_traits/detail/unguarded/pmf_4.hpp @@ -139,9 +139,12 @@ struct pmf class Container> using expand_args = Container; + template class Container> + using expand_non_invoke_args = Container; + using is_member_pointer = std::true_type; }; diff --git a/include/boost/callable_traits/detail/unguarded/pmf_varargs_4.hpp b/include/boost/callable_traits/detail/unguarded/pmf_varargs_4.hpp index ca33ebf..d561489 100644 --- a/include/boost/callable_traits/detail/unguarded/pmf_varargs_4.hpp +++ b/include/boost/callable_traits/detail/unguarded/pmf_varargs_4.hpp @@ -145,5 +145,8 @@ struct pmf class Container> using expand_args = Container; + template class Container> + using expand_non_invoke_args = Container; + using is_member_pointer = std::true_type; }; diff --git a/include/boost/callable_traits/non_invoke_args.hpp b/include/boost/callable_traits/non_invoke_args.hpp new file mode 100644 index 0000000..3de4db1 --- /dev/null +++ b/include/boost/callable_traits/non_invoke_args.hpp @@ -0,0 +1,98 @@ +/* + +@Copyright Barrett Adair 2015-2017 +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 BOOST_CLBL_TRTS_NON_INVOKE_ARGS_HPP +#define BOOST_CLBL_TRTS_NON_INVOKE_ARGS_HPP + +#include + +namespace boost { namespace callable_traits { + +//[ args_hpp +/*`[section:ref_args args] +[heading Header] +``#include .hpp>`` +[heading Definition] +*/ + +template class Container = std::tuple> +using non_invoke_args_t = //see below +//<- + detail::try_but_fail_if_invalid< + typename detail::traits< + detail::shallow_decay>::template expand_non_invoke_args, + cannot_expand_the_parameter_list_of_first_template_argument2>; + +namespace detail { + + template class Container, + typename = std::false_type> + struct non_invoke_args_impl {}; + + template class Container> + struct non_invoke_args_impl , detail::dummy>::type> + { + using type = non_invoke_args_t; + }; +} + +//-> + +template class Container = std::tuple> +struct non_invoke_args : detail::non_invoke_args_impl {}; + +//<- +}} // namespace boost::callable_traits +//-> + +/*` +[heading Constraints] +* `T` must be one of the following: + * function + * function pointer + * function reference + * member function pointer + * member data pointer + * user-defined type with a non-overloaded `operator()` + * type of a non-generic lambda + +[heading Behavior] +* When the constraints are violated, a substitution failure occurs. +* When `T` is a function, function pointer, or function reference, the aliased type is `Container` instantiated with the function's parameter types. +* When `T` is a function object, the aliased type is `Container` instantiated with the `T::operator()` parameter types. +* When `T` is a member function pointer, the aliased type is a `Container` instantiation, The type arguments, if any, are the parameter types of the member function. +* When `T` is a member data pointer, the aliased type is `Container` with a single element, which is a `const` reference to the parent class of `T`. + +[heading Input/Output Examples] +[table + [[`T`] [`args_t`]] + [[`void(float, char, int)`] [`std::tuple`]] + [[`void(*)(float, char, int)`] [`std::tuple`]] + [[`void(*)()`] [`std::tuple<>`]] + [[`void(foo::* const &)(float, char, int)`] [`std::tuple`]] + [[`int(foo::*)(int) const`] [`std::tuple`]] + [[`void(foo::*)() volatile &&`] [`std::tuple<>`]] + [[`int foo::*`] [`std::tuple<>`]] + [[`const int foo::*`] [`std::tuple<>`]] + [[`int`] [(substitution failure)]] + [[`int (*const)()`] [(substitution failure)]] +] + +[heading Example Program] +[import ../example/args.cpp] +[args] +[endsect] +*/ +//] + +#endif // #ifndef BOOST_CLBL_TRTS_NON_INVOKE_ARGS_HPP diff --git a/test/args.cpp b/test/args.cpp index b3f5138..ef67f38 100644 --- a/test/args.cpp +++ b/test/args.cpp @@ -40,27 +40,38 @@ struct foo7 { using std::is_same; int main() { - { using pmf = decltype(&foo1::bar); - using args_t = TRAIT(args, pmf); - CT_ASSERT(is_same>{}); + using args_t = TRAIT(args, pmf); + using non_invoke_args_t = TRAIT(non_invoke_args, pmf); + CT_ASSERT(is_same>{}); + CT_ASSERT(is_same>{}); } { using pmf = decltype(&foo2::bar); - using args_t = TRAIT(args, pmf); - CT_ASSERT(is_same>{}); + using args_t = TRAIT(args, pmf); + using non_invoke_args_t = TRAIT(non_invoke_args, pmf); + CT_ASSERT(is_same>{}); + CT_ASSERT(is_same>{}); } { - using args_t = TRAIT(args, foo3); - CT_ASSERT(is_same>{}); + using args_t = TRAIT(args, foo3); + using non_invoke_args_t = TRAIT(non_invoke_args, foo3); + CT_ASSERT(is_same>{}); + CT_ASSERT(is_same>{}); } { - using args_t = TRAIT(args, foo4); - CT_ASSERT(is_same>{}); + using args_t = TRAIT(args, foo4); + using non_invoke_args_t = TRAIT(non_invoke_args, foo4); + CT_ASSERT(is_same>{}); + CT_ASSERT(is_same>{}); } { - using args_t = TRAIT(args, decltype(foo5)); - CT_ASSERT(is_same>{}); + using args_t = TRAIT(args, decltype(foo5)); + using non_invoke_args_t = TRAIT(non_invoke_args, decltype(foo5)); + CT_ASSERT(is_same>{}); + CT_ASSERT(is_same>{}); } { - using args_t = TRAIT(args, decltype(foo6)); - CT_ASSERT(is_same>{}); + using args_t = TRAIT(args, decltype(foo6)); + using non_invoke_args_t = TRAIT(non_invoke_args, decltype(foo6)); + CT_ASSERT(is_same>{}); + CT_ASSERT(is_same>{}); } return 0;