File: deduct_F.pass.cpp

package info (click to toggle)
llvm-toolchain-13 1%3A13.0.1-6~deb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,418,812 kB
  • sloc: cpp: 5,290,827; ansic: 996,570; asm: 544,593; python: 188,212; objc: 72,027; lisp: 30,291; f90: 25,395; sh: 24,900; javascript: 9,780; pascal: 9,398; perl: 7,484; ml: 5,432; awk: 3,523; makefile: 2,892; xml: 953; cs: 573; fortran: 539
file content (139 lines) | stat: -rw-r--r-- 6,354 bytes parent folder | download | duplicates (3)
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>());