123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- //===----------------------------------------------------------------------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is dual licensed under the MIT and the University of Illinois Open
- // Source Licenses. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- // <functional>
- // template<class F>
- // function(F) -> function<see-below>;
- // UNSUPPORTED: c++98, c++03, c++11, c++14
- // UNSUPPORTED: libcpp-no-deduction-guides
- #include <functional>
- #include <type_traits>
- #include <utility>
- #include "test_macros.h"
- struct R { };
- struct A1 { };
- struct A2 { };
- struct A3 { };
- #define DECLARE_FUNCTIONS_WITH_QUALS(N, ...) \
- struct f0_##N { R operator()() __VA_ARGS__ { return {}; } }; \
- struct f1_##N { R operator()(A1) __VA_ARGS__ { return {}; } }; \
- struct f2_##N { R operator()(A1, A2) __VA_ARGS__ { return {}; } }; \
- struct f3_##N { R operator()(A1, A2, A3) __VA_ARGS__ { return {}; } } \
- /**/
- DECLARE_FUNCTIONS_WITH_QUALS(0, /* nothing */);
- DECLARE_FUNCTIONS_WITH_QUALS(1, const);
- DECLARE_FUNCTIONS_WITH_QUALS(2, volatile);
- DECLARE_FUNCTIONS_WITH_QUALS(3, const volatile);
- DECLARE_FUNCTIONS_WITH_QUALS(4, &);
- DECLARE_FUNCTIONS_WITH_QUALS(5 , const &);
- DECLARE_FUNCTIONS_WITH_QUALS(6 , volatile &);
- DECLARE_FUNCTIONS_WITH_QUALS(7 , const volatile &);
- DECLARE_FUNCTIONS_WITH_QUALS(8 , noexcept);
- DECLARE_FUNCTIONS_WITH_QUALS(9 , const noexcept);
- DECLARE_FUNCTIONS_WITH_QUALS(10, volatile noexcept);
- DECLARE_FUNCTIONS_WITH_QUALS(11, const volatile noexcept);
- DECLARE_FUNCTIONS_WITH_QUALS(12, & noexcept);
- DECLARE_FUNCTIONS_WITH_QUALS(13, const & noexcept);
- DECLARE_FUNCTIONS_WITH_QUALS(14, volatile & noexcept);
- DECLARE_FUNCTIONS_WITH_QUALS(15, const volatile & noexcept);
- int main() {
- #define CHECK_FUNCTIONS(N) \
- do { \
- /* implicit */ \
- std::function g0 = f0_##N{}; \
- ASSERT_SAME_TYPE(decltype(g0), std::function<R()>); \
- \
- std::function g1 = f1_##N{}; \
- ASSERT_SAME_TYPE(decltype(g1), std::function<R(A1)>); \
- \
- std::function g2 = f2_##N{}; \
- ASSERT_SAME_TYPE(decltype(g2), std::function<R(A1, A2)>); \
- \
- std::function g3 = f3_##N{}; \
- ASSERT_SAME_TYPE(decltype(g3), std::function<R(A1, A2, A3)>); \
- \
- /* explicit */ \
- std::function g4{f0_##N{}}; \
- ASSERT_SAME_TYPE(decltype(g4), std::function<R()>); \
- \
- std::function g5{f1_##N{}}; \
- ASSERT_SAME_TYPE(decltype(g5), std::function<R(A1)>); \
- \
- std::function g6{f2_##N{}}; \
- ASSERT_SAME_TYPE(decltype(g6), std::function<R(A1, A2)>); \
- \
- std::function g7{f3_##N{}}; \
- ASSERT_SAME_TYPE(decltype(g7), std::function<R(A1, A2, A3)>); \
- \
- /* from std::function */ \
- std::function<R(A1)> unary; \
- std::function g8 = unary; \
- ASSERT_SAME_TYPE(decltype(g8), std::function<R(A1)>); \
- \
- std::function g9 = std::move(unary); \
- ASSERT_SAME_TYPE(decltype(g9), std::function<R(A1)>); \
- \
- std::function<R(A1&&)> unary_ref; \
- std::function g10 = unary_ref; \
- ASSERT_SAME_TYPE(decltype(g10), std::function<R(A1&&)>); \
- \
- std::function g11 = std::move(unary_ref); \
- ASSERT_SAME_TYPE(decltype(g11), std::function<R(A1&&)>); \
- } while (false) \
- /**/
- // Make sure we can deduce from function objects with valid call operators
- CHECK_FUNCTIONS(0);
- CHECK_FUNCTIONS(1);
- CHECK_FUNCTIONS(2);
- CHECK_FUNCTIONS(3);
- CHECK_FUNCTIONS(4);
- CHECK_FUNCTIONS(5);
- CHECK_FUNCTIONS(6);
- CHECK_FUNCTIONS(7);
- CHECK_FUNCTIONS(8);
- CHECK_FUNCTIONS(9);
- CHECK_FUNCTIONS(10);
- CHECK_FUNCTIONS(11);
- CHECK_FUNCTIONS(12);
- CHECK_FUNCTIONS(13);
- CHECK_FUNCTIONS(14);
- CHECK_FUNCTIONS(15);
- }
- // Make sure we fail in a SFINAE-friendly manner when we try to deduce
- // from a type without a valid call operator.
- template <typename F, typename = decltype(std::function{std::declval<F>()})>
- constexpr bool can_deduce() { return true; }
- template <typename F>
- constexpr bool can_deduce(...) { return false; }
- struct invalid1 { };
- struct invalid2 {
- template <typename ...Args>
- void operator()(Args ...);
- };
- struct invalid3 {
- void operator()(int);
- void operator()(long);
- };
- static_assert(!can_deduce<invalid1>());
- static_assert(!can_deduce<invalid2>());
- static_assert(!can_deduce<invalid3>());
|