123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- /*
- 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... 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<Callable, Args...>() == boost::callable_traits::is_invocable<Callable, Args...>()));
- #else
- CT_ASSERT((Expect == boost::callable_traits::is_invocable<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, foo>
- ,invoke_case<true, foo*>
- ,invoke_case<true, foo&>
- ,invoke_case<true, foo&&>
- ,invoke_case<true, std::reference_wrapper<foo>>
- ,invoke_case<false, foo const>
- ,invoke_case<false, foo const*>
- ,invoke_case<false, foo const&>
- ,invoke_case<false, foo const&&>
- ,invoke_case<false, std::reference_wrapper<foo const>>
- ,invoke_case<false, foo, int>
- ,invoke_case<false, foo*, int>
- ,invoke_case<false, foo&, int>
- ,invoke_case<false, foo&&, int>
- ,invoke_case<false, std::reference_wrapper<foo>, int>
- >();
- run_tests<void(foo::*)() LREF
- ,invoke_case<false, foo>
- ,invoke_case<true, foo*>
- ,invoke_case<true, foo&>
- ,invoke_case<false, foo&&>
- ,invoke_case<true, std::reference_wrapper<foo>>
- ,invoke_case<false, foo const>
- ,invoke_case<false, foo const*>
- ,invoke_case<false, foo const&>
- ,invoke_case<false, foo const&&>
- ,invoke_case<false, std::reference_wrapper<foo const>>
- ,invoke_case<false, foo, int>
- ,invoke_case<false, foo*, int>
- ,invoke_case<false, foo&, int>
- ,invoke_case<false, foo&&, int>
- ,invoke_case<false, std::reference_wrapper<foo>, int>
- >();
- run_tests<void(foo::*)() RREF
- ,invoke_case<true, foo>
- ,invoke_case<false, foo*>
- ,invoke_case<false, foo&>
- ,invoke_case<true, foo&&>
- ,invoke_case<false, std::reference_wrapper<foo>>
- ,invoke_case<false, foo const>
- ,invoke_case<false, foo const*>
- ,invoke_case<false, foo const&>
- ,invoke_case<false, foo const&&>
- ,invoke_case<false, std::reference_wrapper<foo const>>
- ,invoke_case<false, foo, int>
- ,invoke_case<false, foo*, int>
- ,invoke_case<false, foo&, int>
- ,invoke_case<false, foo&&, int>
- ,invoke_case<false, std::reference_wrapper<foo>, int>
- >();
- run_tests<void(foo::*)() const
- ,invoke_case<true, foo>
- ,invoke_case<true, foo*>
- ,invoke_case<true, foo&>
- ,invoke_case<true, foo&&>
- ,invoke_case<true, std::reference_wrapper<foo>>
- ,invoke_case<true, foo const>
- ,invoke_case<true, foo const*>
- ,invoke_case<true, foo const&>
- ,invoke_case<true, foo const&&>
- ,invoke_case<true, std::reference_wrapper<foo const>>
- ,invoke_case<false, foo, int>
- ,invoke_case<false, foo*, int>
- ,invoke_case<false, foo&, int>
- ,invoke_case<false, foo&&, int>
- ,invoke_case<false, 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, foo>
- ,invoke_case<true, foo*>
- ,invoke_case<true, foo&>
- ,invoke_case<false, foo&&>
- ,invoke_case<true, std::reference_wrapper<foo>>
- ,invoke_case<false, foo const>
- ,invoke_case<true, foo const*>
- ,invoke_case<true, foo const&>
- ,invoke_case<false, foo const&&>
- ,invoke_case<true, std::reference_wrapper<foo const>>
- ,invoke_case<false, foo, int>
- ,invoke_case<false, foo*, int>
- ,invoke_case<false, foo&, int>
- ,invoke_case<false, foo&&, int>
- ,invoke_case<false, std::reference_wrapper<foo>, int>
- >();
- run_tests<void(foo::*)() const RREF
- ,invoke_case<true, foo>
- ,invoke_case<false, foo*>
- ,invoke_case<false, foo&>
- ,invoke_case<true, foo&&>
- ,invoke_case<false, std::reference_wrapper<foo>>
- ,invoke_case<true, foo const>
- ,invoke_case<false, foo const*>
- ,invoke_case<false, foo const&>
- ,invoke_case<true, foo const&&>
- ,invoke_case<false, std::reference_wrapper<foo const>>
- ,invoke_case<false, foo, int>
- ,invoke_case<false, foo*, int>
- ,invoke_case<false, foo&, int>
- ,invoke_case<false, foo&&, int>
- ,invoke_case<false, std::reference_wrapper<foo>, int>
- >();
- #endif // #ifndef BOOST_CLBL_TRTS_MSVC
- run_tests<int
- ,invoke_case<false, foo>
- ,invoke_case<false, foo*>
- ,invoke_case<false, foo&>
- ,invoke_case<false, foo&&>
- ,invoke_case<false, std::reference_wrapper<foo>>
- ,invoke_case<false, foo const>
- ,invoke_case<false, foo const*>
- ,invoke_case<false, foo const&>
- ,invoke_case<false, foo const&&>
- ,invoke_case<false, std::reference_wrapper<foo const>>
- ,invoke_case<false, foo, int>
- ,invoke_case<false, foo*, int>
- ,invoke_case<false, foo&, int>
- ,invoke_case<false, foo&&, int>
- ,invoke_case<false, std::reference_wrapper<foo>, int>
- >();
- auto f = [](int){};
- run_tests<decltype(f)
- ,invoke_case<true, int>
- ,invoke_case<true, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(f)&
- ,invoke_case<true, int>
- ,invoke_case<true, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(std::ref(f))
- ,invoke_case<true, int>
- ,invoke_case<true, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(std::ref(f))&
- ,invoke_case<true, int>
- ,invoke_case<true, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(std::ref(f))&&
- ,invoke_case<true, int>
- ,invoke_case<true, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(std::ref(f)) const &
- ,invoke_case<true, int>
- ,invoke_case<true, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(std::ref(f)) const &&
- ,invoke_case<true, int>
- ,invoke_case<true, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(f)&&
- ,invoke_case<true, int>
- ,invoke_case<true, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(f) const &
- ,invoke_case<true, int>
- ,invoke_case<true, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(f) const &&
- ,invoke_case<true, int>
- ,invoke_case<true, char>
- ,invoke_case<false, void*>
- >();
- auto g = [](){};
- run_tests<decltype(g)
- ,invoke_case<true>
- ,invoke_case<false, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(g)&
- ,invoke_case<true>
- ,invoke_case<false, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(std::ref(g))
- ,invoke_case<true>
- ,invoke_case<false, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(std::ref(g))&
- ,invoke_case<true>
- ,invoke_case<false, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(std::ref(g))&&
- ,invoke_case<true>
- ,invoke_case<false, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(std::ref(g)) const &
- ,invoke_case<true>
- ,invoke_case<false, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(std::ref(g)) const &&
- ,invoke_case<true>
- ,invoke_case<false, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(g)&&
- ,invoke_case<true>
- ,invoke_case<false, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(g) const &
- ,invoke_case<true>
- ,invoke_case<false, char>
- ,invoke_case<false, void*>
- >();
- run_tests<decltype(g) const &&
- ,invoke_case<true>
- ,invoke_case<false, char>
- ,invoke_case<false, void*>
- >();
- // libc++ requires constructible types be passed to std::is_invocable
- #ifndef _LIBCPP_VERSION
- run_tests<void(int)
- ,invoke_case<true, int>
- ,invoke_case<true, char>
- ,invoke_case<false, void*>
- >();
- run_tests<void(int) const
- ,invoke_case<false, int>
- ,invoke_case<false, char>
- ,invoke_case<false, void*>
- >();
- run_tests<void()
- ,invoke_case<false, int>
- ,invoke_case<false, char>
- ,invoke_case<false, void*>
- >();
- run_tests<void
- ,invoke_case<false, foo>
- ,invoke_case<false, foo*>
- ,invoke_case<false, foo&>
- ,invoke_case<false, foo&&>
- ,invoke_case<false, std::reference_wrapper<foo>>
- ,invoke_case<false, foo const>
- ,invoke_case<false, foo const*>
- ,invoke_case<false, foo const&>
- ,invoke_case<false, foo const&&>
- ,invoke_case<false, std::reference_wrapper<foo const>>
- ,invoke_case<false, foo, int>
- ,invoke_case<false, foo*, int>
- ,invoke_case<false, foo&, int>
- ,invoke_case<false, foo&&, int>
- ,invoke_case<false, std::reference_wrapper<foo>, int>
- >();
- #endif
- run_tests<int
- ,invoke_case<false, foo>
- ,invoke_case<false, foo*>
- ,invoke_case<false, foo&>
- ,invoke_case<false, foo&&>
- ,invoke_case<false, std::reference_wrapper<foo>>
- ,invoke_case<false, foo const>
- ,invoke_case<false, foo const*>
- ,invoke_case<false, foo const&>
- ,invoke_case<false, foo const&&>
- ,invoke_case<false, std::reference_wrapper<foo const>>
- ,invoke_case<false, foo, int>
- ,invoke_case<false, foo*, int>
- ,invoke_case<false, foo&, int>
- ,invoke_case<false, foo&&, int>
- ,invoke_case<false, std::reference_wrapper<foo>, int>
- >();
- run_tests<void*
- ,invoke_case<false, foo>
- ,invoke_case<false, foo*>
- ,invoke_case<false, foo&>
- ,invoke_case<false, foo&&>
- ,invoke_case<false, std::reference_wrapper<foo>>
- ,invoke_case<false, foo const>
- ,invoke_case<false, foo const*>
- ,invoke_case<false, foo const&>
- ,invoke_case<false, foo const&&>
- ,invoke_case<false, std::reference_wrapper<foo const>>
- ,invoke_case<false, foo, int>
- ,invoke_case<false, foo*, int>
- ,invoke_case<false, foo&, int>
- ,invoke_case<false, foo&&, int>
- ,invoke_case<false, std::reference_wrapper<foo>, int>
- >();
- }
- #endif //#ifdef BOOST_CLBL_TRTS_GCC_OLDER_THAN_4_9_2
|