[libcxx-commits] [libcxx] r366484 - [libc++] Add C++17 deduction guides for std::function
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Jul 18 12:50:56 PDT 2019
Author: ldionne
Date: Thu Jul 18 12:50:56 2019
New Revision: 366484
URL: http://llvm.org/viewvc/llvm-project?rev=366484&view=rev
Log:
[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
Added:
libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.fail.cpp
libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.pass.cpp
libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_ptr.pass.cpp
Modified:
libcxx/trunk/include/functional
Modified: libcxx/trunk/include/functional
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/functional?rev=366484&r1=366483&r2=366484&view=diff
==============================================================================
--- libcxx/trunk/include/functional (original)
+++ libcxx/trunk/include/functional Thu Jul 18 12:50:56 2019
@@ -440,6 +440,13 @@ public:
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 @@ public:
#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_) {}
Added: libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.fail.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.fail.cpp?rev=366484&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.fail.cpp (added)
+++ libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.fail.cpp Thu Jul 18 12:50:56 2019
@@ -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'}}
+}
Added: libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.pass.cpp?rev=366484&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_F.pass.cpp Thu Jul 18 12:50:56 2019
@@ -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>());
Added: libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_ptr.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_ptr.pass.cpp?rev=366484&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_ptr.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct_ptr.pass.cpp Thu Jul 18 12:50:56 2019
@@ -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)>);
+ }
+}
More information about the libcxx-commits
mailing list