|
@@ -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>());
|