1
2// Copyright Oliver Kowalke 2009.
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#include <iostream>
8#include <memory>
9#include <sstream>
10#include <stdexcept>
11#include <string>
12#include <tuple>
13#include <utility>
14
15#include <boost/config.hpp>
16#include <boost/assert.hpp>
17#include <boost/core/lightweight_test.hpp>
18
19#if defined(BOOST_NO_CXX17_STD_INVOKE)
20#include <boost/context/detail/invoke.hpp>
21#include <boost/context/detail/config.hpp>
22
23#define BOOST_CHECK_EQUAL(a, b) BOOST_TEST_EQ(a, b)
24
25namespace ctx = boost::context;
26
27struct callable {
28 int k{ 0 };
29
30 callable() = default;
31
32 callable( int k_) :
33 k{ k_ } {
34 }
35
36 int foo( int i, int j) const {
37 return i + j + k;
38 }
39
40 int operator()( int i, int j) const {
41 return foo( i, j);
42 }
43};
44
45struct movable {
46 int k{ 0 };
47
48 movable() = default;
49
50 movable( int k_) :
51 k{ k_ } {
52 }
53
54 movable( movable const&) = delete;
55 movable & operator=( movable const&) = delete;
56
57 movable( movable && other) :
58 k{ other.k } {
59 other.k = -1;
60 }
61
62 movable & operator=( movable && other) {
63 if ( this == & other) return * this;
64 k = other.k;
65 other.k = -1;
66 return * this;
67 }
68
69 int foo( int i, int j) const {
70 return i + j + k;
71 }
72
73 int operator()( int i, int j) const {
74 return foo( i, j);
75 }
76};
77
78int fn1( int i, int j) {
79 return i + j;
80}
81
82int * fn2( int * ip) {
83 return ip;
84}
85
86int * fn3( int & ir) {
87 return & ir;
88}
89
90int & fn4( int & ir) {
91 return ir;
92}
93
94template< typename T >
95int fn5( int i, T && t_) {
96 T t = std::forward< T >( t_);
97 return i + t.k;
98}
99
100void test1() {
101 int result = ctx::detail::invoke( fn1, 1, 2);
102 BOOST_CHECK_EQUAL( result, 3);
103}
104
105void test2() {
106 {
107 int i = 3;
108 int * ip = & i;
109 int * result = ctx::detail::invoke( fn2, ip);
110 BOOST_CHECK_EQUAL( result, ip);
111 BOOST_CHECK_EQUAL( * result, i);
112 }
113 {
114 int i = 3;
115 int * result = ctx::detail::invoke( fn2, & i);
116 BOOST_CHECK_EQUAL( result, & i);
117 BOOST_CHECK_EQUAL( * result, i);
118 }
119}
120
121void test3() {
122 {
123 int i = 3;
124 int & ir = i;
125 int * result = ctx::detail::invoke( fn3, ir);
126 BOOST_CHECK_EQUAL( result, & ir);
127 BOOST_CHECK_EQUAL( * result, i);
128 }
129 {
130 int i = 3;
131 int * result = ctx::detail::invoke( fn3, i);
132 BOOST_CHECK_EQUAL( result, & i);
133 BOOST_CHECK_EQUAL( * result, i);
134 }
135}
136
137void test4() {
138 {
139 int i = 3;
140 int & ir = i;
141 int & result = ctx::detail::invoke( fn4, ir);
142 BOOST_CHECK_EQUAL( result, ir);
143 BOOST_CHECK_EQUAL( & result, & ir);
144 BOOST_CHECK_EQUAL( result, i);
145 }
146 {
147 int i = 3;
148 int & result = ctx::detail::invoke( fn4, i);
149 BOOST_CHECK_EQUAL( & result, & i);
150 BOOST_CHECK_EQUAL( result, i);
151 }
152}
153
154void test5() {
155 {
156 callable c( 5);
157 int result = ctx::detail::invoke( fn5< callable >, 1, std::move( c) );
158 BOOST_CHECK_EQUAL( result, 6);
159 BOOST_CHECK_EQUAL( c.k, 5);
160 }
161 {
162 movable m( 5);
163 int result = ctx::detail::invoke( fn5< movable >, 1, std::move( m) );
164 BOOST_CHECK_EQUAL( result, 6);
165 BOOST_CHECK_EQUAL( m.k, -1);
166 }
167}
168
169void test6() {
170 {
171 callable c;
172 int result = ctx::detail::invoke( c, 1, 2);
173 BOOST_CHECK_EQUAL( result, 3);
174 BOOST_CHECK_EQUAL( c.k, 0);
175 }
176 {
177 callable c;
178 int result = ctx::detail::invoke( & callable::foo, c, 1, 2);
179 BOOST_CHECK_EQUAL( result, 3);
180 BOOST_CHECK_EQUAL( c.k, 0);
181 }
182}
183
184void test7() {
185 {
186 int result = ctx::detail::invoke( movable{}, 1, 2);
187 BOOST_CHECK_EQUAL( result, 3);
188 }
189 {
190 int result = ctx::detail::invoke( & movable::foo, movable{}, 1, 2);
191 BOOST_CHECK_EQUAL( result, 3);
192 }
193}
194
195template< typename R, typename Fn, typename ... Args >
196R apply( Fn && fn, Args && ... args) {
197 return ctx::detail::invoke(
198 std::forward< Fn >( fn),
199 std::forward< Args >( args) ... );
200}
201
202void test8() {
203 {
204 int result = apply< int >( fn1, 1, 2);
205 BOOST_CHECK_EQUAL( result, 3);
206 }
207 {
208 int i = 3;
209 int & ir = i;
210 int * result = apply< int * >( fn3, ir);
211 BOOST_CHECK_EQUAL( result, & ir);
212 BOOST_CHECK_EQUAL( * result, i);
213 }
214 {
215 movable m( 5);
216 int result = apply< int >( fn5< movable >, 1, std::move( m) );
217 BOOST_CHECK_EQUAL( result, 6);
218 BOOST_CHECK_EQUAL( m.k, -1);
219 }
220}
221#else
222void dummy() {}
223#endif
224
225int main()
226{
227#if defined(BOOST_NO_CXX17_STD_INVOKE)
228 test1();
229 test2();
230 test3();
231 test4();
232 test5();
233 test6();
234 test7();
235 test8();
236#else
237 dummy();
238#endif
239
240 return boost::report_errors();
241}
242

source code of boost/libs/context/test/test_invoke.cpp