1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
//===----------------------------------------------------------------------===//
//
// 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++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(int, char**) {
#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);
return 0;
}
// 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>());
|