1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // <functional>
10 
11 // template<Returnable R, CopyConstructible... ArgTypes>
12 // class function<R(ArgTypes...)> {
13 // public:
14 //   typedef R result_type;
15 //   typedef T1 argument_type;          // iff sizeof...(ArgTypes) == 1 and
16 //                                      // the type in ArgTypes is T1
17 //   typedef T1 first_argument_type;    // iff sizeof...(ArgTypes) == 2 and
18 //                                      // ArgTypes contains T1 and T2
19 //   typedef T2 second_argument_type;   // iff sizeof...(ArgTypes) == 2 and
20 //                                      // ArgTypes contains T1 and T2
21 //  ...
22 //  };
23 
24 // This test runs in C++03, but we have deprecated using std::function in C++03.
25 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
26 
27 #include <functional>
28 #include <type_traits>
29 
30 #include "test_macros.h"
31 
32 
33 template <typename T>
34 class has_argument_type
35 {
36     typedef char yes;
37     typedef long no;
38 
39     template <typename C> static yes check( typename C::argument_type * );
40     template <typename C> static no  check(...);
41 public:
42     enum { value = sizeof(check<T>(0)) == sizeof(yes) };
43 };
44 
45 template <typename T>
46 class has_first_argument_type
47 {
48     typedef char yes;
49     typedef long no;
50 
51     template <typename C> static yes check( typename C::first_argument_type * );
52     template <typename C> static no  check(...);
53 public:
54     enum { value = sizeof(check<T>(0)) == sizeof(yes) };
55 };
56 
57 
58 template <typename T>
59 class has_second_argument_type
60 {
61     typedef char yes;
62     typedef long no;
63 
64     template <typename C> static yes check( typename C::second_argument_type *);
65     template <typename C> static no  check(...);
66 public:
67     enum { value = sizeof(check<T>(0)) == sizeof(yes) };
68 };
69 
70 template <class F, class return_type>
test_nullary_function()71 void test_nullary_function ()
72 {
73 #if TEST_STD_VER <= 17
74     static_assert((std::is_same<typename F::result_type, return_type>::value), "" );
75 #endif
76     static_assert((!has_argument_type<F>::value), "" );
77     static_assert((!has_first_argument_type<F>::value), "" );
78     static_assert((!has_second_argument_type<F>::value), "" );
79 }
80 
81 template <class F, class return_type, class arg_type>
test_unary_function()82 void test_unary_function ()
83 {
84 #if TEST_STD_VER <= 17
85     static_assert((std::is_same<typename F::result_type, return_type>::value), "" );
86     static_assert((std::is_same<typename F::argument_type,  arg_type>::value), "" );
87 #endif
88     static_assert((!has_first_argument_type<F>::value), "" );
89     static_assert((!has_second_argument_type<F>::value), "" );
90 }
91 
92 template <class F, class return_type, class arg_type1, class arg_type2>
test_binary_function()93 void test_binary_function ()
94 {
95 #if TEST_STD_VER <= 17
96     static_assert((std::is_same<typename F::result_type,        return_type>::value), "" );
97     static_assert((std::is_same<typename F::first_argument_type,  arg_type1>::value), "" );
98     static_assert((std::is_same<typename F::second_argument_type, arg_type2>::value), "" );
99 #endif
100     static_assert((!has_argument_type<F>::value), "" );
101 }
102 
103 template <class F, class return_type>
test_other_function()104 void test_other_function ()
105 {
106 #if TEST_STD_VER <= 17
107     static_assert((std::is_same<typename F::result_type, return_type>::value), "" );
108 #endif
109     static_assert((!has_argument_type<F>::value), "" );
110     static_assert((!has_first_argument_type<F>::value), "" );
111     static_assert((!has_second_argument_type<F>::value), "" );
112 }
113 
main(int,char **)114 int main(int, char**)
115 {
116     test_nullary_function<std::function<int()>, int>();
117     test_unary_function  <std::function<double(int)>, double, int>();
118     test_binary_function <std::function<double(int, char)>, double, int, char>();
119     test_other_function  <std::function<double(int, char, double)>, double>();
120 
121   return 0;
122 }
123