1/*
2 * Copyright Andrey Semashev 2024.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
6 */
7/*!
8 * \file functor_test.cpp
9 * \author Andrey Semashev
10 * \date 2024-01-23
11 *
12 * This file contains tests for \c boost::core::functor.
13 */
14
15#include <boost/config.hpp>
16
17#if !defined(BOOST_NO_CXX17_AUTO_NONTYPE_TEMPLATE_PARAMS)
18
19#include <boost/core/functor.hpp>
20#include <boost/core/lightweight_test.hpp>
21#include <boost/core/lightweight_test_trait.hpp>
22#include <type_traits>
23
24#if (defined(__cpp_lib_is_invocable) && (__cpp_lib_is_invocable >= 201703l)) || \
25 (defined(BOOST_MSSTL_VERSION) && (BOOST_MSSTL_VERSION >= 140) && (BOOST_CXX_VERSION >= 201703l))
26
27namespace test {
28
29using std::is_invocable;
30
31} // namespace test
32
33#else
34
35namespace test {
36
37// A simplified implementation that does not support member function pointers
38template< typename Func, typename... Args >
39struct is_invocable_impl
40{
41 template< typename F = Func, typename = decltype(std::declval< F >()(std::declval< Args >()...)) >
42 static std::true_type _check_invocable(int);
43 static std::false_type _check_invocable(...);
44
45 typedef decltype(is_invocable_impl::_check_invocable(0)) type;
46};
47
48template< typename Func, typename... Args >
49struct is_invocable : public is_invocable_impl< Func, Args... >::type { };
50
51} // namespace test
52
53#endif
54
55int g_n = 0;
56
57void void_func()
58{
59 ++g_n;
60}
61
62int int_func()
63{
64 return ++g_n;
65}
66
67int& int_ref_func()
68{
69 ++g_n;
70 return g_n;
71}
72
73void void_add1(int x)
74{
75 g_n += x;
76}
77
78int add2(int x, int y)
79{
80 return x + y;
81}
82
83namespace test_ns {
84
85int add3(int x, int y, int z)
86{
87 return x + y + z;
88}
89
90} // namespace test_ns
91
92int int_func_noexcept() noexcept
93{
94 return ++g_n;
95}
96
97int main()
98{
99 {
100 boost::core::functor< void_func > fun;
101 BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< void_func >& >));
102 BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< void_func > const& >));
103 BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< void_func > const&, int >));
104 BOOST_TEST_EQ(noexcept(fun()), false);
105 fun();
106 BOOST_TEST_EQ(g_n, 1);
107 fun();
108 BOOST_TEST_EQ(g_n, 2);
109 }
110
111 g_n = 0;
112 {
113 boost::core::functor< int_func > fun;
114 int res = fun();
115 BOOST_TEST_EQ(res, 1);
116 BOOST_TEST_EQ(g_n, 1);
117 res = fun();
118 BOOST_TEST_EQ(res, 2);
119 BOOST_TEST_EQ(g_n, 2);
120 }
121
122 g_n = 0;
123 {
124 boost::core::functor< int_ref_func > fun;
125 int& res1 = fun();
126 BOOST_TEST_EQ(&res1, &g_n);
127 BOOST_TEST_EQ(res1, 1);
128 int& res2 = fun();
129 BOOST_TEST_EQ(&res2, &g_n);
130 BOOST_TEST_EQ(res2, 2);
131 }
132
133 g_n = 0;
134 {
135 boost::core::functor< void_add1 > fun;
136 BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< void_add1 >& >));
137 BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< void_add1 > const& >));
138 BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< void_add1 >&, int >));
139 BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< void_add1 > const&, int >));
140 BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< void_add1 >&, short int >));
141 BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< void_add1 > const&, short int >));
142 BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< void_add1 > const&, int, int >));
143 BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< void_add1 > const&, const char* >));
144 fun(10);
145 BOOST_TEST_EQ(g_n, 10);
146 fun(20);
147 BOOST_TEST_EQ(g_n, 30);
148 }
149
150 {
151 boost::core::functor< add2 > fun;
152 BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< add2 >& >));
153 BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< add2 > const& >));
154 BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< add2 >&, int >));
155 BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< add2 > const&, int >));
156 BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< add2 >&, int, int >));
157 BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< add2 > const&, int, int >));
158 BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< add2 >&, short int, signed char >));
159 BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< add2 > const&, short int, signed char >));
160 BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< add2 > const&, const char* >));
161 BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< add2 > const&, const char*, float >));
162 int res = fun(10, 20);
163 BOOST_TEST_EQ(res, 30);
164 res = fun(30, 40);
165 BOOST_TEST_EQ(res, 70);
166 }
167
168 {
169 boost::core::functor< test_ns::add3 > fun;
170 int res = fun(10, 20, 30);
171 BOOST_TEST_EQ(res, 60);
172 res = fun(40, 50, 60);
173 BOOST_TEST_EQ(res, 150);
174 }
175
176 g_n = 0;
177 {
178 boost::core::functor< int_func_noexcept > fun;
179 BOOST_TEST_EQ(noexcept(fun()), true);
180 int res = fun();
181 BOOST_TEST_EQ(res, 1);
182 BOOST_TEST_EQ(g_n, 1);
183 res = fun();
184 BOOST_TEST_EQ(res, 2);
185 BOOST_TEST_EQ(g_n, 2);
186 }
187
188 return boost::report_errors();
189}
190
191#else // !defined(BOOST_NO_CXX17_AUTO_NONTYPE_TEMPLATE_PARAMS)
192
193#include <boost/config/pragma_message.hpp>
194
195BOOST_PRAGMA_MESSAGE("Test skipped because C++17 auto non-type template parameters are not supported")
196
197int main()
198{
199 return 0;
200}
201
202#endif // !defined(BOOST_NO_CXX17_AUTO_NONTYPE_TEMPLATE_PARAMS)
203

source code of boost/libs/core/test/functor_test.cpp