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 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// <functional>
// template<class F>
// function(F) -> function<see-below>;
// UNSUPPORTED: c++03, c++11, c++14
#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_test(int) { return true; }
template <typename F>
constexpr bool can_deduce_test(...) { return false; }
template <typename F>
constexpr bool can_deduce = can_deduce_test<F>(0);
struct valid { int operator()() const; };
struct invalid1 { };
struct invalid2 {
template <typename ...Args>
void operator()(Args ...);
};
struct invalid3 {
void operator()(int);
void operator()(long);
};
static_assert( can_deduce<valid>);
static_assert(!can_deduce<invalid1>);
static_assert(!can_deduce<invalid2>);
static_assert(!can_deduce<invalid3>);
// LWG 3238. Insufficiently-defined behavior of std::function deduction guides
// https://cplusplus.github.io/LWG/issue3238
// The deduction guides for std::function do not handle rvalue-ref qualified
// call operators and C-style variadics. It also doesn't deduce from nullptr_t.
// Make sure we stick to the specification.
struct invalid_rvalue_ref { R operator()() && { return {}; } };
struct invalid_c_vararg { R operator()(int, ...) { return {}; } };
static_assert(!can_deduce<invalid_rvalue_ref>);
static_assert(!can_deduce<invalid_c_vararg>);
static_assert(!can_deduce<std::nullptr_t>);
|