Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions example/non_invoke_args.cpp
Original file line number Diff line number Diff line change
@@ -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 <boost/callable_traits/detail/config.hpp>
#ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS
int main(){ return 0; }
#else

//[ args
#include <type_traits>
#include <memory>
#include <boost/callable_traits.hpp>

namespace ct = boost::callable_traits;

template<typename T, typename Expect>
void test(){
using non_invoke_args_t = ct::non_invoke_args_t<T>;
static_assert(std::is_same<non_invoke_args_t, Expect>::value, "");
}

int main() {

{
auto lamda = [](int, float&, const char*){};
using lam = decltype(lamda);
using expect = std::tuple<int, float&, const char*>;

test<lam, expect>();
}

{
struct foo;
using pmf = void(foo::*)(int, float&, const char*);
using expect = std::tuple<int, float&, const char*>;

test<pmf, expect>();
}

{
using function_ptr = void(*)(int, float&, const char*);
using expect = std::tuple<int, float&, const char*>;
test<function_ptr, expect>();
}

{
using function_ref = void(&)(int, float&, const char*);
using expect = std::tuple<int, float&, const char*>;
test<function_ref, expect>();
}

{
using function = void(int, float&, const char*);
using expect = std::tuple<int, float&, const char*>;
test<function, expect>();
}

{
using abominable = void(int, float&, const char*) const;
using expect = std::tuple<int, float&, const char*>;
test<abominable, expect>();
}
}
//]
#endif //#ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS
1 change: 1 addition & 0 deletions include/boost/callable_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/callable_traits/is_noexcept.hpp>
#include <boost/callable_traits/is_transaction_safe.hpp>
#include <boost/callable_traits/is_volatile_member.hpp>
#include <boost/callable_traits/non_invoke_args.hpp>
#include <boost/callable_traits/qualified_class_of.hpp>
#include <boost/callable_traits/remove_member_const.hpp>
#include <boost/callable_traits/remove_member_cv.hpp>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ struct default_callable_traits {
template<template<class...> class Container>
using expand_args = error_t;

template<template<class...> class Container>
using expand_non_invoke_args = error_t;

template<template<class...> class Container, typename... RightArgs>
using expand_args_left = error_t;

Expand Down
4 changes: 4 additions & 0 deletions include/boost/callable_traits/detail/function_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ struct function_object : Base {
using expand_args = typename function<function_type>::template
expand_args<Container>;

template<template<class...> class Container>
using expand_non_invoke_args = typename function<function_type>::template
expand_non_invoke_args<Container>;

template<template<class...> class Container, typename... RightArgs>
using expand_args_left = typename function<function_type>::template
expand_args_left<Container, RightArgs...>;
Expand Down
3 changes: 3 additions & 0 deletions include/boost/callable_traits/detail/pmd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ struct pmd<D T::*> : default_callable_traits<> {
template<template<class...> class Container>
using expand_args = Container<invoke_type>;

template<template<class...> class Container>
using expand_non_invoke_args = Container<>;

using is_member_pointer = std::true_type;
};

Expand Down
3 changes: 3 additions & 0 deletions include/boost/callable_traits/detail/sfinae_errors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
10 changes: 8 additions & 2 deletions include/boost/callable_traits/detail/unguarded/function_3.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,13 @@ struct function<Return(Args...)
BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE
BOOST_CLBL_TRTS_NOEXCEPT_SPEC;

template<template<class...> class Container>
using expand_args = Container<Args...>;

template<template<class...> class Container>
using expand_non_invoke_args = Container<Args...>;

using is_member_pointer = std::false_type;
};

Expand Down Expand Up @@ -252,9 +255,12 @@ struct function<Return (Args..., ...)
BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE
BOOST_CLBL_TRTS_NOEXCEPT_SPEC;

template<template<class...> class Container>
using expand_args = Container<Args...>;

template<template<class...> class Container>
using expand_non_invoke_args = Container<Args...>;

using is_member_pointer = std::false_type;
};
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ struct function<
template<template<class...> class Container>
using expand_args = Container<Args...>;

template<template<class...> class Container>
using expand_non_invoke_args = Container<Args...>;

using is_member_pointer = std::false_type;
};

Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ struct function<BOOST_CLBL_TRTS_ST Return(BOOST_CLBL_TRTS_VARARGS_CC *)(Args...,
template<template<class...> class Container>
using expand_args = Container<Args...>;

template<template<class...> class Container>
using expand_non_invoke_args = Container<Args...>;

using is_member_pointer = std::false_type;
};

5 changes: 4 additions & 1 deletion include/boost/callable_traits/detail/unguarded/pmf_4.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,12 @@ struct pmf<Return(BOOST_CLBL_TRTS_CC T::*)(Args...)
BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE
BOOST_CLBL_TRTS_NOEXCEPT_SPEC;

template<template<class...> class Container>
using expand_args = Container<invoke_type, Args...>;

template<template<class...> class Container>
using expand_non_invoke_args = Container<Args...>;

using is_member_pointer = std::true_type;
};
Original file line number Diff line number Diff line change
Expand Up @@ -145,5 +145,8 @@ struct pmf<Return(BOOST_CLBL_TRTS_VARARGS_CC T::*)(Args..., ...)
template<template<class...> class Container>
using expand_args = Container<invoke_type, Args...>;

template<template<class...> class Container>
using expand_non_invoke_args = Container<Args...>;

using is_member_pointer = std::true_type;
};
98 changes: 98 additions & 0 deletions include/boost/callable_traits/non_invoke_args.hpp
Original file line number Diff line number Diff line change
@@ -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 <boost/callable_traits/detail/core.hpp>

namespace boost { namespace callable_traits {

//[ args_hpp
/*`[section:ref_args args]
[heading Header]
``#include <boost/callable_traits/
#include <boost/callable_traits/args.hpp>.hpp>``
[heading Definition]
*/

template<typename T, template<class...> class Container = std::tuple>
using non_invoke_args_t = //see below
//<-
detail::try_but_fail_if_invalid<
typename detail::traits<
detail::shallow_decay<T>>::template expand_non_invoke_args<Container>,
cannot_expand_the_parameter_list_of_first_template_argument2>;

namespace detail {

template<typename T, template<class...> class Container,
typename = std::false_type>
struct non_invoke_args_impl {};

template<typename T, template<class...> class Container>
struct non_invoke_args_impl <T, Container, typename std::is_same<
non_invoke_args_t<T, Container>, detail::dummy>::type>
{
using type = non_invoke_args_t<T, Container>;
};
}

//->

template<typename T,
template<class...> class Container = std::tuple>
struct non_invoke_args : detail::non_invoke_args_impl<T, Container> {};

//<-
}} // 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<T>`]]
[[`void(float, char, int)`] [`std::tuple<float, char, int>`]]
[[`void(*)(float, char, int)`] [`std::tuple<float, char, int`]]
[[`void(&)(float, char, int)`] [`std::tuple<float, char, int`]]
[[`void(float, char, int) const &&`][`std::tuple<float, char, int>`]]
[[`void(*)()`] [`std::tuple<>`]]
[[`void(foo::* const &)(float, char, int)`] [`std::tuple<float, char, int>`]]
[[`int(foo::*)(int) const`] [`std::tuple<int>`]]
[[`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
37 changes: 24 additions & 13 deletions test/args.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<args_t, std::tuple<foo1&, char, float&, int>>{});
using args_t = TRAIT(args, pmf);
using non_invoke_args_t = TRAIT(non_invoke_args, pmf);
CT_ASSERT(is_same<args_t, std::tuple<foo1&, char, float&, int>>{});
CT_ASSERT(is_same<non_invoke_args_t, std::tuple<char, float&, int>>{});
} {
using pmf = decltype(&foo2::bar);
using args_t = TRAIT(args, pmf);
CT_ASSERT(is_same<args_t, std::tuple<foo2&, char, float&, int>>{});
using args_t = TRAIT(args, pmf);
using non_invoke_args_t = TRAIT(non_invoke_args, pmf);
CT_ASSERT(is_same<args_t, std::tuple<foo2&, char, float&, int>>{});
CT_ASSERT(is_same<non_invoke_args_t, std::tuple<char, float&, int>>{});
} {
using args_t = TRAIT(args, foo3);
CT_ASSERT(is_same<args_t, std::tuple<char, float&, int>>{});
using args_t = TRAIT(args, foo3);
using non_invoke_args_t = TRAIT(non_invoke_args, foo3);
CT_ASSERT(is_same<args_t, std::tuple<char, float&, int>>{});
CT_ASSERT(is_same<non_invoke_args_t, std::tuple<char, float&, int>>{});
} {
using args_t = TRAIT(args, foo4);
CT_ASSERT(is_same<args_t, std::tuple<char, float&, int>>{});
using args_t = TRAIT(args, foo4);
using non_invoke_args_t = TRAIT(non_invoke_args, foo4);
CT_ASSERT(is_same<args_t, std::tuple<char, float&, int>>{});
CT_ASSERT(is_same<non_invoke_args_t, std::tuple<char, float&, int>>{});
} {
using args_t = TRAIT(args, decltype(foo5));
CT_ASSERT(is_same<args_t, std::tuple<char, float&, int>>{});
using args_t = TRAIT(args, decltype(foo5));
using non_invoke_args_t = TRAIT(non_invoke_args, decltype(foo5));
CT_ASSERT(is_same<args_t, std::tuple<char, float&, int>>{});
CT_ASSERT(is_same<non_invoke_args_t, std::tuple<char, float&, int>>{});
} {
using args_t = TRAIT(args, decltype(foo6));
CT_ASSERT(is_same<args_t, std::tuple<char, float&, int>>{});
using args_t = TRAIT(args, decltype(foo6));
using non_invoke_args_t = TRAIT(non_invoke_args, decltype(foo6));
CT_ASSERT(is_same<args_t, std::tuple<char, float&, int>>{});
CT_ASSERT(is_same<non_invoke_args_t, std::tuple<char, float&, int>>{});
}

return 0;
Expand Down