Skip to content

Commit c3db5d9

Browse files
author
apple-llvm-mt
committed
Merge libcxx: [libc++] Add C++17 deduction guides for std::function
apple-llvm-split-dir: libcxx/
2 parents 2ca73de + e1eabcd commit c3db5d9

File tree

217 files changed

+614
-35630
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

217 files changed

+614
-35630
lines changed

libcxx/include/functional

+54
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,13 @@ public:
440440
template <typename T> const T* target() const noexcept;
441441
};
442442
443+
// Deduction guides
444+
template<class R, class ...Args>
445+
function(R(*)(Args...)) -> function<R(Args...)>; // since C++17
446+
447+
template<class F>
448+
function(F) -> function<see-below>; // since C++17
449+
443450
// Null pointer comparisons:
444451
template <class R, class ... ArgTypes>
445452
bool operator==(const function<R(ArgTypes...)>&, nullptr_t) noexcept;
@@ -2335,6 +2342,53 @@ public:
23352342
#endif // _LIBCPP_NO_RTTI
23362343
};
23372344

2345+
#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES
2346+
template<class _Rp, class ..._Ap>
2347+
function(_Rp(*)(_Ap...)) -> function<_Rp(_Ap...)>;
2348+
2349+
template<class _Fp>
2350+
struct __strip_signature;
2351+
2352+
template<class _Rp, class _Gp, class ..._Ap>
2353+
struct __strip_signature<_Rp (_Gp::*) (_Ap...)> { using type = _Rp(_Ap...); };
2354+
template<class _Rp, class _Gp, class ..._Ap>
2355+
struct __strip_signature<_Rp (_Gp::*) (_Ap...) const> { using type = _Rp(_Ap...); };
2356+
template<class _Rp, class _Gp, class ..._Ap>
2357+
struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile> { using type = _Rp(_Ap...); };
2358+
template<class _Rp, class _Gp, class ..._Ap>
2359+
struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile> { using type = _Rp(_Ap...); };
2360+
2361+
template<class _Rp, class _Gp, class ..._Ap>
2362+
struct __strip_signature<_Rp (_Gp::*) (_Ap...) &> { using type = _Rp(_Ap...); };
2363+
template<class _Rp, class _Gp, class ..._Ap>
2364+
struct __strip_signature<_Rp (_Gp::*) (_Ap...) const &> { using type = _Rp(_Ap...); };
2365+
template<class _Rp, class _Gp, class ..._Ap>
2366+
struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile &> { using type = _Rp(_Ap...); };
2367+
template<class _Rp, class _Gp, class ..._Ap>
2368+
struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile &> { using type = _Rp(_Ap...); };
2369+
2370+
template<class _Rp, class _Gp, class ..._Ap>
2371+
struct __strip_signature<_Rp (_Gp::*) (_Ap...) noexcept> { using type = _Rp(_Ap...); };
2372+
template<class _Rp, class _Gp, class ..._Ap>
2373+
struct __strip_signature<_Rp (_Gp::*) (_Ap...) const noexcept> { using type = _Rp(_Ap...); };
2374+
template<class _Rp, class _Gp, class ..._Ap>
2375+
struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile noexcept> { using type = _Rp(_Ap...); };
2376+
template<class _Rp, class _Gp, class ..._Ap>
2377+
struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile noexcept> { using type = _Rp(_Ap...); };
2378+
2379+
template<class _Rp, class _Gp, class ..._Ap>
2380+
struct __strip_signature<_Rp (_Gp::*) (_Ap...) & noexcept> { using type = _Rp(_Ap...); };
2381+
template<class _Rp, class _Gp, class ..._Ap>
2382+
struct __strip_signature<_Rp (_Gp::*) (_Ap...) const & noexcept> { using type = _Rp(_Ap...); };
2383+
template<class _Rp, class _Gp, class ..._Ap>
2384+
struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile & noexcept> { using type = _Rp(_Ap...); };
2385+
template<class _Rp, class _Gp, class ..._Ap>
2386+
struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile & noexcept> { using type = _Rp(_Ap...); };
2387+
2388+
template<class _Fp, class _Stripped = typename __strip_signature<decltype(&_Fp::operator())>::type>
2389+
function(_Fp) -> function<_Stripped>;
2390+
#endif // !_LIBCPP_HAS_NO_DEDUCTION_GUIDES
2391+
23382392
template<class _Rp, class ..._ArgTypes>
23392393
function<_Rp(_ArgTypes...)>::function(const function& __f) : __f_(__f.__f_) {}
23402394

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is dual licensed under the MIT and the University of Illinois Open
6+
// Source Licenses. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
// <functional>
11+
12+
// template<class F>
13+
// function(F) -> function<see-below>;
14+
15+
// UNSUPPORTED: c++98, c++03, c++11, c++14
16+
// UNSUPPORTED: libcpp-no-deduction-guides
17+
18+
// The deduction guides for std::function do not handle rvalue-ref qualified
19+
// call operators and C-style variadics. It also doesn't deduce from nullptr_t.
20+
// Make sure we stick to the specification.
21+
22+
#include <functional>
23+
#include <type_traits>
24+
25+
26+
struct R { };
27+
struct f0 { R operator()() && { return {}; } };
28+
struct f1 { R operator()(int, ...) { return {}; } };
29+
30+
int main() {
31+
std::function f = f0{}; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'function'}}
32+
std::function g = f1{}; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'function'}}
33+
std::function h = nullptr; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'function'}}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is dual licensed under the MIT and the University of Illinois Open
6+
// Source Licenses. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
// <functional>
11+
12+
// template<class F>
13+
// function(F) -> function<see-below>;
14+
15+
// UNSUPPORTED: c++98, c++03, c++11, c++14
16+
// UNSUPPORTED: libcpp-no-deduction-guides
17+
18+
#include <functional>
19+
#include <type_traits>
20+
#include <utility>
21+
22+
#include "test_macros.h"
23+
24+
25+
struct R { };
26+
struct A1 { };
27+
struct A2 { };
28+
struct A3 { };
29+
30+
#define DECLARE_FUNCTIONS_WITH_QUALS(N, ...) \
31+
struct f0_##N { R operator()() __VA_ARGS__ { return {}; } }; \
32+
struct f1_##N { R operator()(A1) __VA_ARGS__ { return {}; } }; \
33+
struct f2_##N { R operator()(A1, A2) __VA_ARGS__ { return {}; } }; \
34+
struct f3_##N { R operator()(A1, A2, A3) __VA_ARGS__ { return {}; } } \
35+
/**/
36+
37+
DECLARE_FUNCTIONS_WITH_QUALS(0, /* nothing */);
38+
DECLARE_FUNCTIONS_WITH_QUALS(1, const);
39+
DECLARE_FUNCTIONS_WITH_QUALS(2, volatile);
40+
DECLARE_FUNCTIONS_WITH_QUALS(3, const volatile);
41+
DECLARE_FUNCTIONS_WITH_QUALS(4, &);
42+
DECLARE_FUNCTIONS_WITH_QUALS(5 , const &);
43+
DECLARE_FUNCTIONS_WITH_QUALS(6 , volatile &);
44+
DECLARE_FUNCTIONS_WITH_QUALS(7 , const volatile &);
45+
DECLARE_FUNCTIONS_WITH_QUALS(8 , noexcept);
46+
DECLARE_FUNCTIONS_WITH_QUALS(9 , const noexcept);
47+
DECLARE_FUNCTIONS_WITH_QUALS(10, volatile noexcept);
48+
DECLARE_FUNCTIONS_WITH_QUALS(11, const volatile noexcept);
49+
DECLARE_FUNCTIONS_WITH_QUALS(12, & noexcept);
50+
DECLARE_FUNCTIONS_WITH_QUALS(13, const & noexcept);
51+
DECLARE_FUNCTIONS_WITH_QUALS(14, volatile & noexcept);
52+
DECLARE_FUNCTIONS_WITH_QUALS(15, const volatile & noexcept);
53+
54+
int main() {
55+
#define CHECK_FUNCTIONS(N) \
56+
do { \
57+
/* implicit */ \
58+
std::function g0 = f0_##N{}; \
59+
ASSERT_SAME_TYPE(decltype(g0), std::function<R()>); \
60+
\
61+
std::function g1 = f1_##N{}; \
62+
ASSERT_SAME_TYPE(decltype(g1), std::function<R(A1)>); \
63+
\
64+
std::function g2 = f2_##N{}; \
65+
ASSERT_SAME_TYPE(decltype(g2), std::function<R(A1, A2)>); \
66+
\
67+
std::function g3 = f3_##N{}; \
68+
ASSERT_SAME_TYPE(decltype(g3), std::function<R(A1, A2, A3)>); \
69+
\
70+
/* explicit */ \
71+
std::function g4{f0_##N{}}; \
72+
ASSERT_SAME_TYPE(decltype(g4), std::function<R()>); \
73+
\
74+
std::function g5{f1_##N{}}; \
75+
ASSERT_SAME_TYPE(decltype(g5), std::function<R(A1)>); \
76+
\
77+
std::function g6{f2_##N{}}; \
78+
ASSERT_SAME_TYPE(decltype(g6), std::function<R(A1, A2)>); \
79+
\
80+
std::function g7{f3_##N{}}; \
81+
ASSERT_SAME_TYPE(decltype(g7), std::function<R(A1, A2, A3)>); \
82+
\
83+
/* from std::function */ \
84+
std::function<R(A1)> unary; \
85+
std::function g8 = unary; \
86+
ASSERT_SAME_TYPE(decltype(g8), std::function<R(A1)>); \
87+
\
88+
std::function g9 = std::move(unary); \
89+
ASSERT_SAME_TYPE(decltype(g9), std::function<R(A1)>); \
90+
\
91+
std::function<R(A1&&)> unary_ref; \
92+
std::function g10 = unary_ref; \
93+
ASSERT_SAME_TYPE(decltype(g10), std::function<R(A1&&)>); \
94+
\
95+
std::function g11 = std::move(unary_ref); \
96+
ASSERT_SAME_TYPE(decltype(g11), std::function<R(A1&&)>); \
97+
} while (false) \
98+
/**/
99+
100+
// Make sure we can deduce from function objects with valid call operators
101+
CHECK_FUNCTIONS(0);
102+
CHECK_FUNCTIONS(1);
103+
CHECK_FUNCTIONS(2);
104+
CHECK_FUNCTIONS(3);
105+
CHECK_FUNCTIONS(4);
106+
CHECK_FUNCTIONS(5);
107+
CHECK_FUNCTIONS(6);
108+
CHECK_FUNCTIONS(7);
109+
CHECK_FUNCTIONS(8);
110+
CHECK_FUNCTIONS(9);
111+
CHECK_FUNCTIONS(10);
112+
CHECK_FUNCTIONS(11);
113+
CHECK_FUNCTIONS(12);
114+
CHECK_FUNCTIONS(13);
115+
CHECK_FUNCTIONS(14);
116+
CHECK_FUNCTIONS(15);
117+
}
118+
119+
// Make sure we fail in a SFINAE-friendly manner when we try to deduce
120+
// from a type without a valid call operator.
121+
template <typename F, typename = decltype(std::function{std::declval<F>()})>
122+
constexpr bool can_deduce() { return true; }
123+
template <typename F>
124+
constexpr bool can_deduce(...) { return false; }
125+
126+
struct invalid1 { };
127+
struct invalid2 {
128+
template <typename ...Args>
129+
void operator()(Args ...);
130+
};
131+
struct invalid3 {
132+
void operator()(int);
133+
void operator()(long);
134+
};
135+
static_assert(!can_deduce<invalid1>());
136+
static_assert(!can_deduce<invalid2>());
137+
static_assert(!can_deduce<invalid3>());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is dual licensed under the MIT and the University of Illinois Open
6+
// Source Licenses. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
// <functional>
11+
12+
// template<class R, class ...Args>
13+
// function(R(*)(Args...)) -> function<R(Args...)>;
14+
15+
// UNSUPPORTED: c++98, c++03, c++11, c++14
16+
// UNSUPPORTED: libcpp-no-deduction-guides
17+
18+
#include <functional>
19+
#include <type_traits>
20+
21+
#include "test_macros.h"
22+
23+
24+
struct R { };
25+
struct A1 { };
26+
struct A2 { };
27+
struct A3 { };
28+
29+
R f0() { return {}; }
30+
R f1(A1) { return {}; }
31+
R f2(A1, A2) { return {}; }
32+
R f3(A1, A2, A3) { return {}; }
33+
R f4(A1 = {}) { return {}; }
34+
35+
int main() {
36+
{
37+
// implicit
38+
std::function a = f0;
39+
ASSERT_SAME_TYPE(decltype(a), std::function<R()>);
40+
41+
std::function b = &f0;
42+
ASSERT_SAME_TYPE(decltype(b), std::function<R()>);
43+
44+
// explicit
45+
std::function c{f0};
46+
ASSERT_SAME_TYPE(decltype(c), std::function<R()>);
47+
48+
std::function d{&f0};
49+
ASSERT_SAME_TYPE(decltype(d), std::function<R()>);
50+
}
51+
{
52+
// implicit
53+
std::function a = f1;
54+
ASSERT_SAME_TYPE(decltype(a), std::function<R(A1)>);
55+
56+
std::function b = &f1;
57+
ASSERT_SAME_TYPE(decltype(b), std::function<R(A1)>);
58+
59+
// explicit
60+
std::function c{f1};
61+
ASSERT_SAME_TYPE(decltype(c), std::function<R(A1)>);
62+
63+
std::function d{&f1};
64+
ASSERT_SAME_TYPE(decltype(d), std::function<R(A1)>);
65+
}
66+
{
67+
// implicit
68+
std::function a = f2;
69+
ASSERT_SAME_TYPE(decltype(a), std::function<R(A1, A2)>);
70+
71+
std::function b = &f2;
72+
ASSERT_SAME_TYPE(decltype(b), std::function<R(A1, A2)>);
73+
74+
// explicit
75+
std::function c{f2};
76+
ASSERT_SAME_TYPE(decltype(c), std::function<R(A1, A2)>);
77+
78+
std::function d{&f2};
79+
ASSERT_SAME_TYPE(decltype(d), std::function<R(A1, A2)>);
80+
}
81+
{
82+
// implicit
83+
std::function a = f3;
84+
ASSERT_SAME_TYPE(decltype(a), std::function<R(A1, A2, A3)>);
85+
86+
std::function b = &f3;
87+
ASSERT_SAME_TYPE(decltype(b), std::function<R(A1, A2, A3)>);
88+
89+
// explicit
90+
std::function c{f3};
91+
ASSERT_SAME_TYPE(decltype(c), std::function<R(A1, A2, A3)>);
92+
93+
std::function d{&f3};
94+
ASSERT_SAME_TYPE(decltype(d), std::function<R(A1, A2, A3)>);
95+
}
96+
// Make sure defaulted arguments don't mess up the deduction
97+
{
98+
// implicit
99+
std::function a = f4;
100+
ASSERT_SAME_TYPE(decltype(a), std::function<R(A1)>);
101+
102+
std::function b = &f4;
103+
ASSERT_SAME_TYPE(decltype(b), std::function<R(A1)>);
104+
105+
// explicit
106+
std::function c{f4};
107+
ASSERT_SAME_TYPE(decltype(c), std::function<R(A1)>);
108+
109+
std::function d{&f4};
110+
ASSERT_SAME_TYPE(decltype(d), std::function<R(A1)>);
111+
}
112+
}

0 commit comments

Comments
 (0)