123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- /*
- Copyright Barrett Adair 2016-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)
- */
- #include <type_traits>
- #include <functional>
- #include <utility>
- #include <boost/callable_traits/is_invocable.hpp>
- #include "test.hpp"
- #ifdef BOOST_CLBL_TRTS_GCC_OLDER_THAN_4_9_2
- //gcc < 4.9 doesn't like the invoke_case pattern used here
- int main(){}
- #else
- template<typename T>
- struct tag {
- using type = T;
- };
- template<bool Expect, typename Ret, typename... Args>
- struct invoke_case {
- template<typename Callable>
- void operator()(tag<Callable>) const {
- // when available, test parity with std implementation (c++2a breaks our expectations but we still match std impl)
- #if defined(__cpp_lib_is_invocable) || __cplusplus >= 201707L
- CT_ASSERT((std::is_invocable_r<Ret, Callable, Args...>() == boost::callable_traits::is_invocable_r<Ret, Callable, Args...>()));
- #else
- CT_ASSERT((Expect == boost::callable_traits::is_invocable_r<Ret, Callable, Args...>()));
- #endif
- }
- };
- template<typename Callable, typename... InvokeCases>
- void run_tests() {
- using ignored = int[];
- ignored x {(InvokeCases{}(tag<Callable>{}),0)..., 0};
- (void)x;
- }
- struct foo {};
- int main() {
- run_tests<void(foo::*)()
- ,invoke_case<true, void, foo>
- ,invoke_case<true, void, foo*>
- ,invoke_case<true, void, foo&>
- ,invoke_case<true, void, foo&&>
- ,invoke_case<true, void, std::reference_wrapper<foo>>
- ,invoke_case<false, int, foo>
- ,invoke_case<false, int, foo*>
- ,invoke_case<false, int, foo&>
- ,invoke_case<false, int, foo&&>
- ,invoke_case<false, int, std::reference_wrapper<foo>>
- ,invoke_case<false, void, foo const>
- ,invoke_case<false, void, foo const*>
- ,invoke_case<false, void, foo const&>
- ,invoke_case<false, void, foo const&&>
- ,invoke_case<false, void, std::reference_wrapper<foo const>>
- ,invoke_case<false, void, foo, int>
- ,invoke_case<false, void, foo*, int>
- ,invoke_case<false, void, foo&, int>
- ,invoke_case<false, void, foo&&, int>
- ,invoke_case<false, void, std::reference_wrapper<foo>, int>
- ,invoke_case<false, int, foo const>
- ,invoke_case<false, int, foo const*>
- ,invoke_case<false, int, foo const&>
- ,invoke_case<false, int, foo const&&>
- ,invoke_case<false, int, std::reference_wrapper<foo const>>
- ,invoke_case<false, int, foo, int>
- ,invoke_case<false, int, foo*, int>
- ,invoke_case<false, int, foo&, int>
- ,invoke_case<false, int, foo&&, int>
- ,invoke_case<false, int, std::reference_wrapper<foo>, int>
- >();
- run_tests<char(foo::*)()
- ,invoke_case<true, void, foo>
- ,invoke_case<true, void, foo*>
- ,invoke_case<true, void, foo&>
- ,invoke_case<true, void, foo&&>
- ,invoke_case<true, void, std::reference_wrapper<foo>>
- ,invoke_case<true, int, foo>
- ,invoke_case<true, int, foo*>
- ,invoke_case<true, int, foo&>
- ,invoke_case<true, int, foo&&>
- ,invoke_case<true, int, std::reference_wrapper<foo>>
- >();
- run_tests<void(foo::*)() LREF
- ,invoke_case<false, void, foo>
- ,invoke_case<true, void, foo*>
- ,invoke_case<true, void, foo&>
- ,invoke_case<false, int, foo*>
- ,invoke_case<false, int, foo&>
- ,invoke_case<false, void, foo&&>
- ,invoke_case<true, void, std::reference_wrapper<foo>>
- ,invoke_case<false, int, std::reference_wrapper<foo>>
- ,invoke_case<false, void, foo const>
- ,invoke_case<false, void, foo const*>
- ,invoke_case<false, void, foo const&>
- ,invoke_case<false, void, foo const&&>
- ,invoke_case<false, void, std::reference_wrapper<foo const>>
- ,invoke_case<false, void, foo, int>
- ,invoke_case<false, void, foo*, int>
- ,invoke_case<false, void, foo&, int>
- ,invoke_case<false, void, foo&&, int>
- ,invoke_case<false, void, std::reference_wrapper<foo>, int>
- >();
- run_tests<void(foo::*)() RREF
- ,invoke_case<true, void, foo>
- ,invoke_case<false, int, foo>
- ,invoke_case<false, void, foo*>
- ,invoke_case<false, void, foo&>
- ,invoke_case<true, void, foo&&>
- ,invoke_case<false, int, foo&&>
- ,invoke_case<false, void, std::reference_wrapper<foo>>
- ,invoke_case<false, void, foo const>
- ,invoke_case<false, void, foo const*>
- ,invoke_case<false, void, foo const&>
- ,invoke_case<false, void, foo const&&>
- ,invoke_case<false, void, std::reference_wrapper<foo const>>
- ,invoke_case<false, void, foo, int>
- ,invoke_case<false, void, foo*, int>
- ,invoke_case<false, void, foo&, int>
- ,invoke_case<false, void, foo&&, int>
- ,invoke_case<false, void, std::reference_wrapper<foo>, int>
- >();
- run_tests<void(foo::*)() const
- ,invoke_case<true, void, foo>
- ,invoke_case<true, void, foo*>
- ,invoke_case<true, void, foo&>
- ,invoke_case<true, void, foo&&>
- ,invoke_case<true, void, std::reference_wrapper<foo>>
- ,invoke_case<true, void, foo const>
- ,invoke_case<true, void, foo const*>
- ,invoke_case<true, void, foo const&>
- ,invoke_case<true, void, foo const&&>
- ,invoke_case<true, void, std::reference_wrapper<foo const>>
- ,invoke_case<false, int, foo>
- ,invoke_case<false, int, foo*>
- ,invoke_case<false, int, foo&>
- ,invoke_case<false, int, foo&&>
- ,invoke_case<false, int, std::reference_wrapper<foo>>
- ,invoke_case<false, int, foo const>
- ,invoke_case<false, int, foo const*>
- ,invoke_case<false, int, foo const&>
- ,invoke_case<false, int, foo const&&>
- ,invoke_case<false, int, std::reference_wrapper<foo const>>
- ,invoke_case<false, void, foo, int>
- ,invoke_case<false, void, foo*, int>
- ,invoke_case<false, void, foo&, int>
- ,invoke_case<false, void, foo&&, int>
- ,invoke_case<false, void, std::reference_wrapper<foo>, int>
- >();
- // MSVC doesn't handle cv + ref qualifiers in expression sfinae correctly
- #ifndef BOOST_CLBL_TRTS_MSVC
- run_tests<void(foo::*)() const LREF
- ,invoke_case<false, void, foo>
- ,invoke_case<true, void, foo*>
- ,invoke_case<true, void, foo&>
- ,invoke_case<false, int, foo*>
- ,invoke_case<false, int, foo&>
- ,invoke_case<false, void, foo&&>
- ,invoke_case<true, void, std::reference_wrapper<foo>>
- ,invoke_case<false, int, std::reference_wrapper<foo>>
- ,invoke_case<false, void, foo const>
- ,invoke_case<true, void, foo const*>
- ,invoke_case<true, void, foo const&>
- ,invoke_case<false, int, foo const*>
- ,invoke_case<false, int, foo const&>
- ,invoke_case<false, void, foo const&&>
- ,invoke_case<true, void, std::reference_wrapper<foo const>>
- ,invoke_case<false, int, std::reference_wrapper<foo const>>
- ,invoke_case<false, void, foo, int>
- ,invoke_case<false, void, foo*, int>
- ,invoke_case<false, void, foo&, int>
- ,invoke_case<false, void, foo&&, int>
- ,invoke_case<false, void, std::reference_wrapper<foo>, int>
- >();
- run_tests<void(foo::*)() const RREF
- ,invoke_case<true, void, foo>
- ,invoke_case<false, int, foo>
- ,invoke_case<false, void, foo*>
- ,invoke_case<false, void, foo&>
- ,invoke_case<true, void, foo&&>
- ,invoke_case<false, int, foo&&>
- ,invoke_case<false, void, std::reference_wrapper<foo>>
- ,invoke_case<true, void, foo const>
- ,invoke_case<false, int, foo const>
- ,invoke_case<false, void, foo const*>
- ,invoke_case<false, void, foo const&>
- ,invoke_case<true, void, foo const&&>
- ,invoke_case<false, int, foo const&&>
- ,invoke_case<false, void, std::reference_wrapper<foo const>>
- ,invoke_case<false, void, foo, int>
- ,invoke_case<false, void, foo*, int>
- ,invoke_case<false, void, foo&, int>
- ,invoke_case<false, void, foo&&, int>
- ,invoke_case<false, void, std::reference_wrapper<foo>, int>
- >();
- #endif // #ifndef BOOST_CLBL_TRTS_MSVC
- run_tests<int
- ,invoke_case<false, void, foo>
- ,invoke_case<false, void, foo*>
- ,invoke_case<false, void, foo&>
- ,invoke_case<false, void, foo&&>
- ,invoke_case<false, void, std::reference_wrapper<foo>>
- ,invoke_case<false, void, foo const>
- ,invoke_case<false, void, foo const*>
- ,invoke_case<false, void, foo const&>
- ,invoke_case<false, void, foo const&&>
- ,invoke_case<false, void, std::reference_wrapper<foo const>>
- ,invoke_case<false, void, foo, int>
- ,invoke_case<false, void, foo*, int>
- ,invoke_case<false, void, foo&, int>
- ,invoke_case<false, void, foo&&, int>
- ,invoke_case<false, void, std::reference_wrapper<foo>, int>
- >();
- auto f = [](int){};
- run_tests<decltype(f)
- ,invoke_case<true, void, int>
- ,invoke_case<true, void, char>
- ,invoke_case<false, int, int>
- ,invoke_case<false, int, char>
- ,invoke_case<false, void, void*>
- >();
- auto g = [](){};
- run_tests<decltype(g)
- ,invoke_case<true, void>
- ,invoke_case<true, void>
- ,invoke_case<false, void, int>
- ,invoke_case<false, void, char>
- ,invoke_case<false, int, int>
- ,invoke_case<false, int, char>
- ,invoke_case<false, void, void*>
- >();
- // libc++ requires constructible types be passed to std::is_invocable
- #ifndef _LIBCPP_VERSION
- run_tests<void(int)
- ,invoke_case<true, void, int>
- ,invoke_case<true, void, char>
- ,invoke_case<false, int, int>
- ,invoke_case<false, int, char>
- ,invoke_case<false, void, void*>
- >();
- run_tests<void()
- ,invoke_case<false, void, int>
- ,invoke_case<false, void, char>
- ,invoke_case<false, void, void*>
- >();
- run_tests<void
- ,invoke_case<false, void, foo>
- ,invoke_case<false, void, foo*>
- ,invoke_case<false, void, foo&>
- ,invoke_case<false, void, foo&&>
- ,invoke_case<false, void, std::reference_wrapper<foo>>
- ,invoke_case<false, void, foo const>
- ,invoke_case<false, void, foo const*>
- ,invoke_case<false, void, foo const&>
- ,invoke_case<false, void, foo const&&>
- ,invoke_case<false, void, std::reference_wrapper<foo const>>
- ,invoke_case<false, void, foo, int>
- ,invoke_case<false, void, foo*, int>
- ,invoke_case<false, void, foo&, int>
- ,invoke_case<false, void, foo&&, int>
- ,invoke_case<false, void, std::reference_wrapper<foo>, int>
- >();
- #endif
- run_tests<int
- ,invoke_case<false, void, foo>
- ,invoke_case<false, void, foo*>
- ,invoke_case<false, void, foo&>
- ,invoke_case<false, void, foo&&>
- ,invoke_case<false, void, std::reference_wrapper<foo>>
- ,invoke_case<false, void, foo const>
- ,invoke_case<false, void, foo const*>
- ,invoke_case<false, void, foo const&>
- ,invoke_case<false, void, foo const&&>
- ,invoke_case<false, void, std::reference_wrapper<foo const>>
- ,invoke_case<false, void, foo, int>
- ,invoke_case<false, void, foo*, int>
- ,invoke_case<false, void, foo&, int>
- ,invoke_case<false, void, foo&&, int>
- ,invoke_case<false, void, std::reference_wrapper<foo>, int>
- >();
- run_tests<void*
- ,invoke_case<false, void, foo>
- ,invoke_case<false, void, foo*>
- ,invoke_case<false, void, foo&>
- ,invoke_case<false, void, foo&&>
- ,invoke_case<false, void, std::reference_wrapper<foo>>
- ,invoke_case<false, void, foo const>
- ,invoke_case<false, void, foo const*>
- ,invoke_case<false, void, foo const&>
- ,invoke_case<false, void, foo const&&>
- ,invoke_case<false, void, std::reference_wrapper<foo const>>
- ,invoke_case<false, void, foo, int>
- ,invoke_case<false, void, foo*, int>
- ,invoke_case<false, void, foo&, int>
- ,invoke_case<false, void, foo&&, int>
- ,invoke_case<false, void, std::reference_wrapper<foo>, int>
- >();
- }
- #endif //#ifdef BOOST_CLBL_TRTS_GCC_OLDER_THAN_4_9_2
|