[libc++] Add C++17 deduction guides for std::function

Summary: http://llvm.org/PR39606

Reviewers: Quuxplusone

Subscribers: christof, dexonsmith, libcxx-commits

Differential Revision: https://reviews.llvm.org/D54410

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@366484 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/functional b/include/functional
index bcd74a9..865a281 100644
--- a/include/functional
+++ b/include/functional
@@ -440,6 +440,13 @@
     template <typename T> const T* target() const noexcept;
 };
 
+// Deduction guides
+template<class R, class ...Args>
+function(R(*)(Args...)) -> function<R(Args...)>; // since C++17
+
+template<class F>
+function(F) -> function<see-below>; // since C++17
+
 // Null pointer comparisons:
 template <class R, class ... ArgTypes>
   bool operator==(const function<R(ArgTypes...)>&, nullptr_t) noexcept;
@@ -2335,6 +2342,53 @@
 #endif  // _LIBCPP_NO_RTTI
 };
 
+#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES
+template<class _Rp, class ..._Ap>
+function(_Rp(*)(_Ap...)) -> function<_Rp(_Ap...)>;
+
+template<class _Fp>
+struct __strip_signature;
+
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...)> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) const> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile> { using type = _Rp(_Ap...); };
+
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) &> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) const &> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile &> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile &> { using type = _Rp(_Ap...); };
+
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) noexcept> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) const noexcept> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile noexcept> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile noexcept> { using type = _Rp(_Ap...); };
+
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) & noexcept> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) const & noexcept> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile & noexcept> { using type = _Rp(_Ap...); };
+template<class _Rp, class _Gp, class ..._Ap>
+struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile & noexcept> { using type = _Rp(_Ap...); };
+
+template<class _Fp, class _Stripped = typename __strip_signature<decltype(&_Fp::operator())>::type>
+function(_Fp) -> function<_Stripped>;
+#endif // !_LIBCPP_HAS_NO_DEDUCTION_GUIDES
+
 template<class _Rp, class ..._ArgTypes>
 function<_Rp(_ArgTypes...)>::function(const function& __f) : __f_(__f.__f_) {}
 
diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.fail.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.fail.cpp
new file mode 100644
index 0000000..cb1c563
--- /dev/null
+++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.fail.cpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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
+
+// 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.
+
+#include <functional>
+#include <type_traits>
+
+
+struct R { };
+struct f0 { R operator()() && { return {}; } };
+struct f1 { R operator()(int, ...) { return {}; } };
+
+int main() {
+    std::function f = f0{}; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'function'}}
+    std::function g = f1{}; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'function'}}
+    std::function h = nullptr; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'function'}}
+}
diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.pass.cpp
new file mode 100644
index 0000000..e39675a
--- /dev/null
+++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.pass.cpp
@@ -0,0 +1,137 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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>());
diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_ptr.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_ptr.pass.cpp
new file mode 100644
index 0000000..5f5c1ee
--- /dev/null
+++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_ptr.pass.cpp
@@ -0,0 +1,112 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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 R, class ...Args>
+// function(R(*)(Args...)) -> function<R(Args...)>;
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// UNSUPPORTED: libcpp-no-deduction-guides
+
+#include <functional>
+#include <type_traits>
+
+#include "test_macros.h"
+
+
+struct R { };
+struct A1 { };
+struct A2 { };
+struct A3 { };
+
+R f0() { return {}; }
+R f1(A1) { return {}; }
+R f2(A1, A2) { return {}; }
+R f3(A1, A2, A3) { return {}; }
+R f4(A1 = {}) { return {}; }
+
+int main() {
+  {
+    // implicit
+    std::function a = f0;
+    ASSERT_SAME_TYPE(decltype(a), std::function<R()>);
+
+    std::function b = &f0;
+    ASSERT_SAME_TYPE(decltype(b), std::function<R()>);
+
+    // explicit
+    std::function c{f0};
+    ASSERT_SAME_TYPE(decltype(c), std::function<R()>);
+
+    std::function d{&f0};
+    ASSERT_SAME_TYPE(decltype(d), std::function<R()>);
+  }
+  {
+    // implicit
+    std::function a = f1;
+    ASSERT_SAME_TYPE(decltype(a), std::function<R(A1)>);
+
+    std::function b = &f1;
+    ASSERT_SAME_TYPE(decltype(b), std::function<R(A1)>);
+
+    // explicit
+    std::function c{f1};
+    ASSERT_SAME_TYPE(decltype(c), std::function<R(A1)>);
+
+    std::function d{&f1};
+    ASSERT_SAME_TYPE(decltype(d), std::function<R(A1)>);
+  }
+  {
+    // implicit
+    std::function a = f2;
+    ASSERT_SAME_TYPE(decltype(a), std::function<R(A1, A2)>);
+
+    std::function b = &f2;
+    ASSERT_SAME_TYPE(decltype(b), std::function<R(A1, A2)>);
+
+    // explicit
+    std::function c{f2};
+    ASSERT_SAME_TYPE(decltype(c), std::function<R(A1, A2)>);
+
+    std::function d{&f2};
+    ASSERT_SAME_TYPE(decltype(d), std::function<R(A1, A2)>);
+  }
+  {
+    // implicit
+    std::function a = f3;
+    ASSERT_SAME_TYPE(decltype(a), std::function<R(A1, A2, A3)>);
+
+    std::function b = &f3;
+    ASSERT_SAME_TYPE(decltype(b), std::function<R(A1, A2, A3)>);
+
+    // explicit
+    std::function c{f3};
+    ASSERT_SAME_TYPE(decltype(c), std::function<R(A1, A2, A3)>);
+
+    std::function d{&f3};
+    ASSERT_SAME_TYPE(decltype(d), std::function<R(A1, A2, A3)>);
+  }
+  // Make sure defaulted arguments don't mess up the deduction
+  {
+    // implicit
+    std::function a = f4;
+    ASSERT_SAME_TYPE(decltype(a), std::function<R(A1)>);
+
+    std::function b = &f4;
+    ASSERT_SAME_TYPE(decltype(b), std::function<R(A1)>);
+
+    // explicit
+    std::function c{f4};
+    ASSERT_SAME_TYPE(decltype(c), std::function<R(A1)>);
+
+    std::function d{&f4};
+    ASSERT_SAME_TYPE(decltype(d), std::function<R(A1)>);
+  }
+}