trompeloeil.hpp (159589B)
1 /* 2 * Trompeloeil C++ mocking framework 3 * 4 * Copyright (C) Björn Fahller 2014-2021 5 * Copyright (C) 2017, 2018 Andrew Paxie 6 * Copyright Tore Martin Hagen 2019 7 * 8 * Use, modification and distribution is subject to the 9 * Boost Software License, Version 1.0. (See accompanying 10 * file LICENSE_1_0.txt or copy at 11 * http://www.boost.org/LICENSE_1_0.txt) 12 * 13 * Project home: https://github.com/rollbear/trompeloeil 14 */ 15 16 #ifndef TROMPELOEIL_HPP_ 17 #define TROMPELOEIL_HPP_ 18 19 20 // trompe l'oeil noun (Concise Encyclopedia) 21 // Style of representation in which a painted object is intended 22 // to deceive the viewer into believing it is the object itself... 23 24 // project home: https://github.com/rollbear/trompeloeil 25 26 27 // Deficiencies and missing features 28 // * Mocking function templates is not supported 29 // * If a macro kills a kitten, this threatens extinction of all felines! 30 31 #if defined(_MSC_VER) 32 33 # define TROMPELOEIL_NORETURN __declspec(noreturn) 34 35 # if (!defined(__cplusplus) || _MSC_VER < 1900) 36 # error requires C++ in Visual Studio 2015 RC or later 37 # endif 38 39 #else 40 41 # define TROMPELOEIL_NORETURN [[noreturn]] 42 43 # if (!defined(__cplusplus) || __cplusplus < 201103L) 44 # error requires C++11 or higher 45 # endif 46 47 #endif 48 49 #if defined(__clang__) 50 51 # define TROMPELOEIL_CLANG 1 52 # define TROMPELOEIL_GCC 0 53 # define TROMPELOEIL_MSVC 0 54 55 # define TROMPELOEIL_CLANG_VERSION \ 56 (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) 57 58 # define TROMPELOEIL_GCC_VERSION 0 59 60 # define TROMPELOEIL_CPLUSPLUS __cplusplus 61 62 # define TROMPELOEIL_NOT_IMPLEMENTED(...) \ 63 _Pragma("clang diagnostic push") \ 64 _Pragma("clang diagnostic ignored \"-Wunneeded-member-function\"") \ 65 __VA_ARGS__ \ 66 _Pragma("clang diagnostic pop") 67 68 #elif defined(__GNUC__) 69 70 # define TROMPELOEIL_CLANG 0 71 # define TROMPELOEIL_GCC 1 72 # define TROMPELOEIL_MSVC 0 73 74 # define TROMPELOEIL_CLANG_VERSION 0 75 # define TROMPELOEIL_GCC_VERSION \ 76 (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) 77 78 # define TROMPELOEIL_CPLUSPLUS __cplusplus 79 80 #elif defined(_MSC_VER) 81 82 # define TROMPELOEIL_CLANG 0 83 # define TROMPELOEIL_GCC 0 84 # define TROMPELOEIL_MSVC 1 85 86 # define TROMPELOEIL_CLANG_VERSION 0 87 # define TROMPELOEIL_GCC_VERSION 0 88 89 # if defined(_MSVC_LANG) 90 91 // Compiler is at least Microsoft Visual Studio 2015 Update 3. 92 # define TROMPELOEIL_CPLUSPLUS _MSVC_LANG 93 94 # else /* defined(_MSVC_LANG) */ 95 96 /* 97 * This version of Microsoft Visual C++ is released 98 * in a version of Microsoft Visual Studio between 99 * 2015 RC and less than 2015 Update 3. 100 * 101 * It is an amalgam of C++ versions, with no provision 102 * to specify C++11 mode. 103 * 104 * It also has a __cplusplus macro stuck at 199711L with 105 * no way to change it, such as /Zc:__cplusplus. 106 * 107 * Assume the C++14 code path, but don't promise that it is a 108 * fully conforming implementation of C++14 either. 109 * Hence a value of 201401L, which less than 201402L, 110 * the standards conforming value of __cplusplus. 111 */ 112 # define TROMPELOEIL_CPLUSPLUS 201401L 113 114 # endif /* !defined(_MSVC_LANG) */ 115 116 #endif 117 118 119 #ifndef TROMPELOEIL_NOT_IMPLEMENTED 120 #define TROMPELOEIL_NOT_IMPLEMENTED(...) __VA_ARGS__ 121 #endif 122 123 #include <tuple> 124 #include <iomanip> 125 #include <sstream> 126 #include <exception> 127 #include <functional> 128 #include <memory> 129 #include <cstring> 130 #include <regex> 131 #include <mutex> 132 #include <atomic> 133 #include <array> 134 #include <initializer_list> 135 #include <type_traits> 136 #include <utility> 137 138 139 #ifndef TROMPELOEIL_CUSTOM_ATOMIC 140 #include <atomic> 141 namespace trompeloeil { using std::atomic; } 142 #else 143 #include <trompeloeil/custom_atomic.hpp> 144 #endif 145 146 #ifndef TROMPELOEIL_CUSTOM_UNIQUE_LOCK 147 namespace trompeloeil { using std::unique_lock; } 148 #else 149 #include <trompeloeil/custom_unique_lock.hpp> 150 #endif 151 152 #ifdef TROMPELOEIL_SANITY_CHECKS 153 #include <cassert> 154 #define TROMPELOEIL_ASSERT(x) assert(x) 155 #else 156 #define TROMPELOEIL_ASSERT(x) do {} while (false) 157 #endif 158 159 #define TROMPELOEIL_IDENTITY(...) __VA_ARGS__ // work around stupid MS VS2015 RC bug 160 161 #define TROMPELOEIL_ARG16(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15, ...) _15 162 163 #define TROMPELOEIL_COUNT(...) \ 164 TROMPELOEIL_IDENTITY(TROMPELOEIL_ARG16(__VA_ARGS__, \ 165 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) 166 167 #if defined(_MSC_VER) 168 169 #define TROMPELOEIL_CONCAT_(x, y, ...) x ## y __VA_ARGS__ 170 #define TROMPELOEIL_CONCAT(x, ...) TROMPELOEIL_CONCAT_(x, __VA_ARGS__) 171 172 #else /* defined(_MSC_VER) */ 173 174 #define TROMPELOEIL_CONCAT_(x, ...) x ## __VA_ARGS__ 175 #define TROMPELOEIL_CONCAT(x, ...) TROMPELOEIL_CONCAT_(x, __VA_ARGS__) 176 177 #endif /* !defined(_MSC_VER) */ 178 179 #define TROMPELOEIL_SEPARATE1(p1) p1 180 #define TROMPELOEIL_SEPARATE2(p1,p2) p1 p2 181 #define TROMPELOEIL_SEPARATE3(p1,...) p1 TROMPELOEIL_SEPARATE2(__VA_ARGS__) 182 #define TROMPELOEIL_SEPARATE4(p1,...) p1 TROMPELOEIL_SEPARATE3(__VA_ARGS__) 183 #define TROMPELOEIL_SEPARATE5(p1,...) p1 TROMPELOEIL_SEPARATE4(__VA_ARGS__) 184 #define TROMPELOEIL_SEPARATE6(p1,...) p1 TROMPELOEIL_SEPARATE5(__VA_ARGS__) 185 #define TROMPELOEIL_SEPARATE7(p1,...) p1 TROMPELOEIL_SEPARATE6(__VA_ARGS__) 186 #define TROMPELOEIL_SEPARATE8(p1,...) p1 TROMPELOEIL_SEPARATE7(__VA_ARGS__) 187 #define TROMPELOEIL_SEPARATE9(p1,...) p1 TROMPELOEIL_SEPARATE8(__VA_ARGS__) 188 #define TROMPELOEIL_SEPARATE(...) \ 189 TROMPELOEIL_CONCAT(TROMPELOEIL_SEPARATE,\ 190 TROMPELOEIL_COUNT(__VA_ARGS__))(__VA_ARGS__) 191 192 193 #define TROMPELOEIL_REMOVE_PAREN(...) TROMPELOEIL_CONCAT(TROMPELOEIL_CLEAR_, \ 194 TROMPELOEIL_REMOVE_PAREN_INTERNAL __VA_ARGS__) 195 #define TROMPELOEIL_REMOVE_PAREN_INTERNAL(...) \ 196 TROMPELOEIL_REMOVE_PAREN_INTERNAL __VA_ARGS__ 197 #define TROMPELOEIL_CLEAR_TROMPELOEIL_REMOVE_PAREN_INTERNAL 198 199 #define TROMPELOEIL_INIT_WITH_STR15(base, x, ...) \ 200 base{#x, x}, TROMPELOEIL_INIT_WITH_STR14(base, __VA_ARGS__) 201 202 #define TROMPELOEIL_INIT_WITH_STR14(base, x, ...) \ 203 base{#x, x}, TROMPELOEIL_INIT_WITH_STR13(base, __VA_ARGS__) 204 205 #define TROMPELOEIL_INIT_WITH_STR13(base, x, ...) \ 206 base{#x, x}, TROMPELOEIL_INIT_WITH_STR12(base, __VA_ARGS__) 207 208 #define TROMPELOEIL_INIT_WITH_STR12(base, x, ...) \ 209 base{#x, x}, TROMPELOEIL_INIT_WITH_STR11(base, __VA_ARGS__) 210 211 #define TROMPELOEIL_INIT_WITH_STR11(base, x, ...) \ 212 base{#x, x}, TROMPELOEIL_INIT_WITH_STR10(base, __VA_ARGS__) 213 214 #define TROMPELOEIL_INIT_WITH_STR10(base, x, ...) \ 215 base{#x, x}, TROMPELOEIL_INIT_WITH_STR9(base, __VA_ARGS__) 216 217 #define TROMPELOEIL_INIT_WITH_STR9(base, x, ...) \ 218 base{#x, x}, TROMPELOEIL_INIT_WITH_STR8(base, __VA_ARGS__) 219 220 #define TROMPELOEIL_INIT_WITH_STR8(base, x, ...) \ 221 base{#x, x}, TROMPELOEIL_INIT_WITH_STR7(base, __VA_ARGS__) 222 223 #define TROMPELOEIL_INIT_WITH_STR7(base, x, ...) \ 224 base{#x, x}, TROMPELOEIL_INIT_WITH_STR6(base, __VA_ARGS__) 225 226 #define TROMPELOEIL_INIT_WITH_STR6(base, x, ...) \ 227 base{#x, x}, TROMPELOEIL_INIT_WITH_STR5(base, __VA_ARGS__) 228 229 #define TROMPELOEIL_INIT_WITH_STR5(base, x, ...) \ 230 base{#x, x}, TROMPELOEIL_INIT_WITH_STR4(base, __VA_ARGS__) 231 232 #define TROMPELOEIL_INIT_WITH_STR4(base, x, ...) \ 233 base{#x, x}, TROMPELOEIL_INIT_WITH_STR3(base, __VA_ARGS__) 234 235 #define TROMPELOEIL_INIT_WITH_STR3(base, x, ...) \ 236 base{#x, x}, TROMPELOEIL_INIT_WITH_STR2(base, __VA_ARGS__) 237 238 #define TROMPELOEIL_INIT_WITH_STR2(base, x, ...) \ 239 base{#x, x}, TROMPELOEIL_INIT_WITH_STR1(base, __VA_ARGS__) 240 241 #define TROMPELOEIL_INIT_WITH_STR1(base, x) \ 242 base{#x, x} 243 244 #define TROMPELOEIL_INIT_WITH_STR0(base) 245 246 #define TROMPELOEIL_INIT_WITH_STR(base, ...) \ 247 TROMPELOEIL_CONCAT(TROMPELOEIL_INIT_WITH_STR, \ 248 TROMPELOEIL_COUNT(__VA_ARGS__))(base, __VA_ARGS__) 249 250 #define TROMPELOEIL_PARAM_LIST15(...) \ 251 TROMPELOEIL_PARAM_LIST14(__VA_ARGS__), \ 252 ::trompeloeil::param_list_t<__VA_ARGS__, 14> p15 253 254 #define TROMPELOEIL_PARAM_LIST14(...) \ 255 TROMPELOEIL_PARAM_LIST13(__VA_ARGS__), \ 256 ::trompeloeil::param_list_t<__VA_ARGS__, 13> p14 257 258 #define TROMPELOEIL_PARAM_LIST13(...) \ 259 TROMPELOEIL_PARAM_LIST12(__VA_ARGS__), \ 260 ::trompeloeil::param_list_t<__VA_ARGS__, 12> p13 261 262 #define TROMPELOEIL_PARAM_LIST12(...) \ 263 TROMPELOEIL_PARAM_LIST11(__VA_ARGS__), \ 264 ::trompeloeil::param_list_t<__VA_ARGS__, 11> p12 265 266 #define TROMPELOEIL_PARAM_LIST11(...) \ 267 TROMPELOEIL_PARAM_LIST10(__VA_ARGS__), \ 268 ::trompeloeil::param_list_t<__VA_ARGS__, 10> p11 269 270 #define TROMPELOEIL_PARAM_LIST10(...) \ 271 TROMPELOEIL_PARAM_LIST9(__VA_ARGS__), \ 272 ::trompeloeil::param_list_t<__VA_ARGS__, 9> p10 273 274 #define TROMPELOEIL_PARAM_LIST9(...) \ 275 TROMPELOEIL_PARAM_LIST8(__VA_ARGS__), \ 276 ::trompeloeil::param_list_t<__VA_ARGS__, 8> p9 277 278 #define TROMPELOEIL_PARAM_LIST8(...) \ 279 TROMPELOEIL_PARAM_LIST7(__VA_ARGS__), \ 280 ::trompeloeil::param_list_t<__VA_ARGS__, 7> p8 281 282 #define TROMPELOEIL_PARAM_LIST7(...) \ 283 TROMPELOEIL_PARAM_LIST6(__VA_ARGS__), \ 284 ::trompeloeil::param_list_t<__VA_ARGS__, 6> p7 285 286 #define TROMPELOEIL_PARAM_LIST6(...) \ 287 TROMPELOEIL_PARAM_LIST5(__VA_ARGS__), \ 288 ::trompeloeil::param_list_t<__VA_ARGS__, 5> p6 289 290 #define TROMPELOEIL_PARAM_LIST5(...) \ 291 TROMPELOEIL_PARAM_LIST4(__VA_ARGS__), \ 292 ::trompeloeil::param_list_t<__VA_ARGS__, 4> p5 293 294 #define TROMPELOEIL_PARAM_LIST4(...) \ 295 TROMPELOEIL_PARAM_LIST3(__VA_ARGS__), \ 296 ::trompeloeil::param_list_t<__VA_ARGS__, 3> p4 297 298 #define TROMPELOEIL_PARAM_LIST3(...) \ 299 TROMPELOEIL_PARAM_LIST2(__VA_ARGS__), \ 300 ::trompeloeil::param_list_t<__VA_ARGS__, 2> p3 301 302 #define TROMPELOEIL_PARAM_LIST2(...) \ 303 TROMPELOEIL_PARAM_LIST1(__VA_ARGS__), \ 304 ::trompeloeil::param_list_t<__VA_ARGS__, 1> p2 305 306 #define TROMPELOEIL_PARAM_LIST1(...) \ 307 ::trompeloeil::param_list_t<__VA_ARGS__, 0> p1 308 309 #define TROMPELOEIL_PARAM_LIST0(func_type) 310 311 #define TROMPELOEIL_PARAM_LIST(num, func_type) \ 312 TROMPELOEIL_CONCAT(TROMPELOEIL_PARAM_LIST, num) \ 313 (TROMPELOEIL_REMOVE_PAREN(func_type)) 314 315 316 #define TROMPELOEIL_PARAMS15 TROMPELOEIL_PARAMS14, p15 317 #define TROMPELOEIL_PARAMS14 TROMPELOEIL_PARAMS13, p14 318 #define TROMPELOEIL_PARAMS13 TROMPELOEIL_PARAMS12, p13 319 #define TROMPELOEIL_PARAMS12 TROMPELOEIL_PARAMS11, p12 320 #define TROMPELOEIL_PARAMS11 TROMPELOEIL_PARAMS10, p11 321 #define TROMPELOEIL_PARAMS10 TROMPELOEIL_PARAMS9, p10 322 #define TROMPELOEIL_PARAMS9 TROMPELOEIL_PARAMS8, p9 323 #define TROMPELOEIL_PARAMS8 TROMPELOEIL_PARAMS7, p8 324 #define TROMPELOEIL_PARAMS7 TROMPELOEIL_PARAMS6, p7 325 #define TROMPELOEIL_PARAMS6 TROMPELOEIL_PARAMS5, p6 326 #define TROMPELOEIL_PARAMS5 TROMPELOEIL_PARAMS4, p5 327 #define TROMPELOEIL_PARAMS4 TROMPELOEIL_PARAMS3, p4 328 #define TROMPELOEIL_PARAMS3 TROMPELOEIL_PARAMS2, p3 329 #define TROMPELOEIL_PARAMS2 TROMPELOEIL_PARAMS1, p2 330 #define TROMPELOEIL_PARAMS1 , p1 331 #define TROMPELOEIL_PARAMS0 332 333 #define TROMPELOEIL_PARAMS(num) TROMPELOEIL_CONCAT(TROMPELOEIL_PARAMS, num) 334 335 #if defined(__cxx_rtti) || defined(__GXX_RTTI) || defined(_CPPRTTI) 336 # define TROMPELOEIL_TYPE_ID_NAME(x) typeid(x).name() 337 #else 338 # define TROMPELOEIL_TYPE_ID_NAME(x) "object" 339 #endif 340 341 #if (TROMPELOEIL_CPLUSPLUS == 201103L) 342 343 #define TROMPELOEIL_DECLTYPE_AUTO \ 344 auto 345 346 #define TROMPELOEIL_TRAILING_RETURN_TYPE(return_type) \ 347 -> return_type 348 349 #else /* (TROMPELOEIL_CPLUSPLUS == 201103L) */ 350 351 #define TROMPELOEIL_DECLTYPE_AUTO \ 352 decltype(auto) 353 354 #define TROMPELOEIL_TRAILING_RETURN_TYPE(return_type) \ 355 /**/ 356 357 #endif /* !(TROMPELOEIL_CPLUSPLUS == 201103L) */ 358 #if TROMPELOEIL_CPLUSPLUS > 201403L && (!TROMPELOEIL_GCC || TROMPELOEIL_GCC_VERSION >= 70000) 359 # define TROMPELOEIL_INLINE_VAR [[maybe_unused]] static inline 360 #else 361 # define TROMPELOEIL_INLINE_VAR static 362 #endif 363 364 static constexpr bool trompeloeil_movable_mock = false; 365 366 namespace trompeloeil 367 { 368 template <typename T> 369 struct identity_type 370 { 371 using type = T; 372 }; 373 374 template <typename R, typename C, typename ... Args> 375 identity_type<R(Args...)> 376 nonconst_member_signature(R (C::*)(Args...)) 377 { 378 return {}; 379 } 380 381 template <typename R, typename C, typename ... Args> 382 identity_type<R(Args...)> 383 const_member_signature(R (C::*)(Args...) const) 384 { 385 return {}; 386 } 387 388 template <typename ...> 389 struct void_t_ 390 { 391 using type = void; 392 }; 393 394 template <typename ... T> 395 using void_t = typename void_t_<T...>::type; 396 397 template <template <typename ...> class, typename, typename ...> 398 struct is_detected_{ 399 using type = std::false_type; 400 }; 401 402 template <template <typename ...> class D, typename ... Ts> 403 struct is_detected_<D, void_t<D<Ts...>>, Ts...> 404 { 405 using type = std::true_type; 406 }; 407 408 template <template <typename ...> class D, typename ... Ts> 409 using is_detected = typename is_detected_<D, void, Ts...>::type; 410 411 # if (TROMPELOEIL_CPLUSPLUS == 201103L) 412 413 namespace detail 414 { 415 template <typename T> 416 struct unwrap_type 417 { 418 using type = T; 419 }; 420 template <typename T> 421 struct unwrap_type<std::reference_wrapper<T>> 422 { 423 using type = T&; 424 }; 425 template <typename ... Ts> 426 std::tuple<typename unwrap_type<typename std::decay<Ts>::type>::type...> 427 make_tuple(Ts&& ... ts) 428 { 429 return { std::forward<Ts>(ts)... }; 430 } 431 432 /* Implement C++14 features using only C++11 entities. */ 433 434 /* <memory> */ 435 436 /* Implementation of make_unique is from 437 * 438 * Stephan T. Lavavej, "make_unique (Revision 1)," 439 * ISO/IEC JTC1 SC22 WG21 N3656, 18 April 2013. 440 * Available: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3656.htm 441 * Accessed: 14 June 2017 442 * 443 * Renamed types to avoid the use of reserved identifiers. 444 */ 445 template <class T> 446 struct unique_if 447 { 448 typedef std::unique_ptr<T> single_object; 449 }; 450 451 template <class T> 452 struct unique_if<T[]> 453 { 454 typedef std::unique_ptr<T[]> unknown_bound; 455 }; 456 457 template <class T, size_t N> 458 struct unique_if<T[N]> 459 { 460 typedef void known_bound; 461 }; 462 463 template <class T, class... Args> 464 typename unique_if<T>::single_object 465 make_unique(Args&&... args) 466 { 467 return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); 468 } 469 470 template <class T> 471 typename unique_if<T>::unknown_bound 472 make_unique(size_t n) 473 { 474 typedef typename std::remove_extent<T>::type U; 475 return std::unique_ptr<T>(new U[n]()); 476 } 477 478 template <class T, class... Args> 479 typename unique_if<T>::known_bound 480 make_unique(Args&&...) = delete; 481 482 /* <type_traits> */ 483 484 /* The implementation of these is from 485 * 486 * Walter E. Brown, "TransformationTraits Redux, v2," 487 * ISO/IEC JTC1 SC22 WG21 N3655, 18 April 2013. 488 * Available: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3655.pdf 489 * Accessed: 2 November 2017 490 * 491 * Minor changes to capitalize template parameter `bool B` has been made. 492 * 493 * See also: 494 * http://en.cppreference.com/w/cpp/types/conditional 495 * http://en.cppreference.com/w/cpp/types/decay 496 * http://en.cppreference.com/w/cpp/types/enable_if 497 * http://en.cppreference.com/w/cpp/types/remove_pointer 498 * http://en.cppreference.com/w/cpp/types/remove_reference 499 * Accessed: 17 May 2017 500 */ 501 template <bool B, typename T, typename F> 502 using conditional_t = typename std::conditional<B, T, F>::type; 503 504 template <typename T> 505 using decay_t = typename std::decay<T>::type; 506 507 template <bool B, typename T = void> 508 using enable_if_t = typename std::enable_if<B, T>::type; 509 510 template <typename T> 511 using remove_pointer_t = typename std::remove_pointer<T>::type; 512 513 template <typename T> 514 using remove_reference_t = typename std::remove_reference<T>::type; 515 516 /* <utility> */ 517 518 /* This implementation of exchange is from 519 * 520 * Jeffrey Yasskin, "exchange() utility function, revision 3," 521 * ISO/IEC JTC1 SC22 WG21 N3688, 19 April 2013. 522 * Available: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3668.html 523 * Accessed: 2 November 2017 524 * 525 * See also: 526 * http://en.cppreference.com/w/cpp/utility/exchange 527 * Accessed: 17 May 2017 528 */ 529 template<class T, class U = T> 530 inline 531 T 532 exchange( 533 T& obj, 534 U&& new_value) 535 { 536 T old_value = std::move(obj); 537 obj = std::forward<U>(new_value); 538 return old_value; 539 } 540 541 /* integer_sequence and index_sequence implementations are from 542 * 543 * Jonathan Wakely, "Compile-time integer sequences," 544 * ISO/IEC JTC1 SC22 WG21 N3658, 18 April 2013. 545 * Available: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html 546 * Accessed: 2 November 2017 547 * 548 * See also: 549 * http://en.cppreference.com/w/cpp/utility/integer_sequence 550 * Accessed: 17 May 2017 551 */ 552 template <typename T, T... I> 553 struct integer_sequence 554 { 555 // Replaces a typedef used in the definition found in N3658. 556 using value_type = T; 557 558 static constexpr size_t size() noexcept 559 { 560 return sizeof...(I); 561 } 562 }; 563 564 template <size_t... I> 565 using index_sequence = integer_sequence<size_t, I...>; 566 567 /* This implementation of make_integer_sequence is from boost/mp11, 568 * 569 * Copyright 2015, 2017 Peter Dimov 570 * 571 * Distributed under the Boost Software License, Version 1.0. 572 * 573 * Implemented here: 574 * 575 * https://github.com/pdimov/mp11/blob/master/include/boost/ 576 * integer_sequence.hpp 577 * Accessed: 17 May 2017 578 * 579 * (now missing) and here: 580 * 581 * https://github.com/boostorg/mp11/blob/develop/include/boost/ 582 * mp11/integer_sequence.hpp 583 * Accessed: 13 August 2017 584 */ 585 namespace impl 586 { 587 // iseq_if_c 588 template <bool C, class T, class E> 589 struct iseq_if_c_impl; 590 591 template <class T, class E> 592 struct iseq_if_c_impl<true, T, E> 593 { 594 using type = T; 595 }; 596 597 template <class T, class E> 598 struct iseq_if_c_impl<false, T, E> 599 { 600 using type = E; 601 }; 602 603 template <bool C, class T, class E> 604 using iseq_if_c = typename iseq_if_c_impl<C, T, E>::type; 605 606 // iseq_identity 607 template <class T> 608 struct iseq_identity 609 { 610 using type = T; 611 }; 612 613 template <class S1, class S2> 614 struct append_integer_sequence; 615 616 template <class T, T... I, T... J> 617 struct append_integer_sequence<integer_sequence<T, I...>, integer_sequence<T, J...>> 618 { 619 using type = integer_sequence<T, I..., ( J + sizeof...(I) )...>; 620 }; 621 622 template <class T, T N> 623 struct make_integer_sequence_impl; 624 625 template <class T, T N> 626 struct make_integer_sequence_impl_ 627 { 628 private: 629 630 static_assert( N >= 0, "make_integer_sequence<T, N>: N must not be negative" ); 631 632 static T const M = N / 2; 633 static T const R = N % 2; 634 635 using S1 = typename make_integer_sequence_impl<T, M>::type; 636 using S2 = typename append_integer_sequence<S1, S1>::type; 637 using S3 = typename make_integer_sequence_impl<T, R>::type; 638 using S4 = typename append_integer_sequence<S2, S3>::type; 639 640 public: 641 642 using type = S4; 643 }; 644 645 template <class T, T N> 646 struct make_integer_sequence_impl: 647 iseq_if_c<N == 0, 648 iseq_identity<integer_sequence<T>>, 649 iseq_if_c<N == 1, 650 iseq_identity<integer_sequence<T, 0>>, 651 make_integer_sequence_impl_<T, N>>> 652 { 653 }; 654 } 655 656 template<class T, T N> 657 using make_integer_sequence = typename impl::make_integer_sequence_impl<T, N>::type; 658 659 template <size_t N> 660 using make_index_sequence = make_integer_sequence<size_t, N>; 661 662 template <typename... T> 663 using index_sequence_for = make_index_sequence<sizeof...(T)>; 664 665 } /* namespace detail */ 666 667 # else /* (TROMPELOEIL_CPLUSPLUS == 201103L) */ 668 669 /* Only these entities really need to 670 * be available in namespace detail, but 671 * VS 2015 has a problem with this approach. 672 * 673 * namespace detail { 674 * 675 * using std::make_unique; 676 * 677 * using std::conditional_t; 678 * using std::decay_t; 679 * using std::enable_if_t; 680 * using std::remove_pointer_t; 681 * using std::remove_reference_t; 682 * 683 * using std::exchange; 684 * using std::index_sequence; 685 * using std::index_sequence_for; 686 * using std::integer_sequence; 687 * using std::make_index_sequence; 688 * 689 * } 690 * 691 * Instead, use a namespace alias. 692 */ 693 namespace detail = std; 694 695 # endif /* !(TROMPELOEIL_CPLUSPLUS == 201103L) */ 696 697 # if TROMPELOEIL_CPLUSPLUS >= 201703L 698 # if TROMPELOEIL_CLANG && TROMPELOEIL_CLANG_VERSION >= 60000 699 700 // these are mostly added to work around clang++ bugs 701 // https://bugs.llvm.org/show_bug.cgi?id=38033 702 // https://bugs.llvm.org/show_bug.cgi?id=38010 703 704 template <typename T> 705 using move_construct_type = decltype(T(std::declval<T&&>())); 706 707 template <typename T> 708 using copy_construct_type = decltype(T(std::declval<const T&>())); 709 710 template <typename T> 711 using can_move_construct = is_detected<move_construct_type, detail::decay_t<T>>; 712 713 template <typename T> 714 using can_copy_construct = is_detected<copy_construct_type, detail::decay_t<T>>; 715 716 # else 717 template <typename T> 718 using can_move_construct = std::is_move_constructible<T>; 719 720 template <typename T> 721 using can_copy_construct = std::is_copy_constructible<T>; 722 # endif 723 724 template <typename F, typename ... A> 725 using invoke_result_type = decltype(std::declval<F&>()(std::declval<A>()...)); 726 727 # else 728 729 template <typename T> 730 using can_move_construct = std::is_move_constructible<T>; 731 732 template <typename T> 733 using can_copy_construct = std::is_copy_constructible<T>; 734 735 template <typename F, typename ... A> 736 using invoke_result_type = decltype(std::declval<F&>()(std::declval<A>()...)); 737 738 # endif 739 740 class specialized; 741 742 template <typename T> 743 using aligned_storage_for = 744 typename std::aligned_storage<sizeof(T), alignof(T)>::type; 745 746 #ifndef TROMPELOEIL_CUSTOM_RECURSIVE_MUTEX 747 748 template <typename T = void> 749 unique_lock<std::recursive_mutex> get_lock() 750 { 751 // Ugly hack for lifetime of mutex. The statically allocated 752 // recursive_mutex is intentionally leaked, to ensure that the 753 // mutex is available and valid even if the last use is from 754 // the destructor of a global object in a translation unit 755 // without #include <trompeloeil.hpp> 756 757 static aligned_storage_for<std::recursive_mutex> buffer; 758 static auto mutex = new (&buffer) std::recursive_mutex; 759 return unique_lock<std::recursive_mutex>{*mutex}; 760 } 761 762 #else 763 764 class custom_recursive_mutex { 765 public: 766 virtual ~custom_recursive_mutex() = default; 767 virtual void lock() = 0; 768 virtual void unlock() = 0; 769 }; 770 771 // User has to provide an own recursive mutex. 772 std::unique_ptr<custom_recursive_mutex> create_custom_recursive_mutex(); 773 774 template <typename T = void> 775 unique_lock<custom_recursive_mutex> get_lock() 776 { 777 static std::unique_ptr<custom_recursive_mutex> mtx = 778 create_custom_recursive_mutex(); 779 return unique_lock<custom_recursive_mutex>{*mtx}; 780 } 781 782 #endif 783 784 template <size_t N, typename T> 785 using conditional_tuple_element 786 = detail::conditional_t<(N < std::tuple_size<T>::value), 787 typename std::tuple_element<N, T>::type, 788 int>; 789 790 template <typename T> 791 struct param_list; 792 793 template <typename R, typename ... P> 794 struct param_list<R(P...)> 795 { 796 static size_t constexpr const size = sizeof...(P); 797 template <size_t N> 798 using type = conditional_tuple_element<N, std::tuple<P...>>; 799 }; 800 801 template <typename Sig, size_t N> 802 using param_list_t = typename param_list<Sig>::template type<N>; 803 804 class expectation_violation : public std::logic_error 805 { 806 public: 807 using std::logic_error::logic_error; 808 }; 809 810 struct location 811 { 812 location() 813 noexcept 814 : file("") 815 , line(0U) 816 {} 817 818 location( 819 char const* file_, 820 unsigned long line_ 821 ) 822 noexcept 823 : file{file_} 824 , line{line_} 825 {} 826 827 char const *file; 828 unsigned long line; 829 }; 830 831 inline 832 std::ostream& 833 operator<<( 834 std::ostream& os, 835 const location& loc) 836 { 837 if (loc.line != 0U) os << loc.file << ':' << loc.line; 838 return os; 839 } 840 841 enum class severity { fatal, nonfatal }; 842 843 using reporter_func = std::function<void(severity, 844 char const *file, 845 unsigned long line, 846 std::string const &msg)>; 847 848 using ok_reporter_func = std::function<void(char const *msg)>; 849 850 inline 851 void 852 default_reporter( 853 severity, 854 char const *file, 855 unsigned long line, 856 std::string const &msg) 857 { 858 if (!std::current_exception()) 859 { 860 std::stringstream os; 861 os << location{ file, line } << "\n" << msg; 862 throw expectation_violation(os.str()); 863 } 864 } 865 866 inline 867 void 868 default_ok_reporter(char const* /*msg*/) 869 { 870 /* OK reporter defaults to doing nothing. */ 871 } 872 873 inline 874 reporter_func& 875 reporter_obj() 876 { 877 static reporter_func obj = default_reporter; 878 return obj; 879 } 880 881 inline 882 ok_reporter_func& 883 ok_reporter_obj() 884 { 885 static ok_reporter_func obj = default_ok_reporter; 886 return obj; 887 } 888 889 inline 890 reporter_func 891 set_reporter( 892 reporter_func f) 893 { 894 return detail::exchange(reporter_obj(), std::move(f)); 895 } 896 897 inline 898 std::pair<reporter_func, ok_reporter_func> 899 set_reporter( 900 reporter_func rf, 901 ok_reporter_func orf) 902 { 903 return { 904 set_reporter(rf), 905 detail::exchange(ok_reporter_obj(), std::move(orf)) 906 }; 907 } 908 909 class tracer; 910 911 inline 912 tracer*& 913 tracer_obj() 914 noexcept 915 { 916 static tracer* ptr = nullptr; 917 return ptr; 918 } 919 920 inline 921 tracer* 922 set_tracer( 923 tracer* obj) 924 noexcept 925 { 926 // std::exchange would be sane here, but it costs compilation time 927 auto& ptr = tracer_obj(); 928 auto rv = ptr; 929 ptr = obj; 930 return rv; 931 } 932 933 class tracer 934 { 935 public: 936 virtual 937 void 938 trace( 939 char const *file, 940 unsigned long line, 941 std::string const &call) = 0; 942 protected: 943 tracer() = default; 944 tracer(tracer const&) = delete; 945 tracer& operator=(tracer const&) = delete; 946 virtual 947 ~tracer() 948 { 949 set_tracer(previous); 950 } 951 private: 952 tracer* previous = set_tracer(this); 953 }; 954 955 class stream_tracer : public tracer 956 { 957 public: 958 stream_tracer( 959 std::ostream& stream_) 960 : stream(stream_) {} 961 void 962 trace( 963 char const *file, 964 unsigned long line, 965 std::string const &call) 966 override 967 { 968 stream << location{file, line} << '\n' << call << '\n'; 969 } 970 private: 971 std::ostream& stream; 972 }; 973 974 class trace_agent; 975 976 template <typename T> 977 struct reporter; 978 979 template <typename T> 980 void 981 send_report( 982 severity s, 983 location loc, 984 std::string const &msg) 985 { 986 reporter<T>::send(s, loc.file, loc.line, msg.c_str()); 987 } 988 989 template <typename T> 990 void 991 send_ok_report( 992 std::string const &msg) 993 { 994 reporter<T>::sendOk(msg.c_str()); 995 } 996 997 template <typename T> 998 struct reporter 999 { 1000 static 1001 void 1002 send( 1003 severity s, 1004 char const *file, 1005 unsigned long line, 1006 char const *msg); 1007 1008 static 1009 void 1010 sendOk( 1011 char const *msg); 1012 1013 }; 1014 1015 template <typename T> 1016 void reporter<T>:: 1017 send( 1018 severity s, 1019 char const *file, 1020 unsigned long line, 1021 char const *msg) 1022 { 1023 reporter_obj()(s, file, line, msg); 1024 } 1025 1026 template <typename T> 1027 void reporter<T>:: 1028 sendOk(char const* msg) 1029 { 1030 ok_reporter_obj()(msg); 1031 } 1032 1033 template <typename ... T> 1034 inline 1035 constexpr 1036 bool 1037 ignore( 1038 T const& ...) 1039 noexcept 1040 { 1041 return true; 1042 } 1043 1044 struct illegal_argument 1045 { 1046 template <bool b = false> 1047 constexpr 1048 illegal_argument const& operator&() const 1049 { 1050 static_assert(b, "illegal argument"); 1051 return *this; 1052 } 1053 1054 template <bool b = false> 1055 constexpr 1056 illegal_argument const& operator*() const 1057 { 1058 static_assert(b, "illegal argument"); 1059 return *this; 1060 } 1061 1062 template <typename T, bool b = false> 1063 constexpr 1064 illegal_argument const& operator=(T const&) const 1065 { 1066 static_assert(b, "illegal argument"); 1067 return *this; 1068 } 1069 1070 template <typename T, bool b = false> 1071 constexpr 1072 operator T() const 1073 { 1074 static_assert(b, "illegal argument"); 1075 return {}; 1076 } 1077 }; 1078 1079 struct matcher { }; 1080 1081 struct wildcard : public matcher 1082 { 1083 template <typename T 1084 #if TROMPELOEIL_GCC && TROMPELOEIL_GCC_VERSION >= 50000 1085 ,detail::enable_if_t<!std::is_convertible<wildcard&, T>{}>* = nullptr 1086 #endif 1087 > 1088 operator T&&() 1089 const; 1090 1091 template <typename T 1092 #if TROMPELOEIL_GCC && TROMPELOEIL_GCC_VERSION >= 50000 1093 ,detail::enable_if_t<!std::is_convertible<wildcard&, T>{}>* = nullptr 1094 #endif 1095 > 1096 operator T&() 1097 volatile const; // less preferred than T&& above 1098 1099 template <typename T> 1100 constexpr 1101 bool 1102 matches( 1103 T const&) 1104 const 1105 noexcept 1106 { 1107 return true; 1108 } 1109 1110 friend 1111 std::ostream& 1112 operator<<( 1113 std::ostream& os, 1114 wildcard const&) 1115 noexcept 1116 { 1117 return os << " matching _"; 1118 } 1119 }; 1120 1121 TROMPELOEIL_INLINE_VAR wildcard _{}; 1122 1123 template <typename T> 1124 using matcher_access = decltype(static_cast<matcher*>(std::declval<typename std::add_pointer<T>::type>())); 1125 1126 template <typename T> 1127 using is_matcher = typename is_detected<matcher_access, T>::type; 1128 1129 template <typename T> 1130 struct typed_matcher : matcher 1131 { 1132 operator T() const; 1133 }; 1134 1135 template <> 1136 struct typed_matcher<std::nullptr_t> : matcher 1137 { 1138 template <typename T, typename = decltype(std::declval<T>() == nullptr)> 1139 operator T&&() const; 1140 1141 template <typename T, 1142 typename = decltype(std::declval<T>() == nullptr)> 1143 operator T&()const volatile; 1144 1145 template <typename T, typename C> 1146 operator T C::*() const; 1147 }; 1148 1149 template <typename Pred, typename ... T> 1150 class duck_typed_matcher : public matcher 1151 { 1152 public: 1153 #if (!TROMPELOEIL_GCC) || \ 1154 (TROMPELOEIL_GCC && TROMPELOEIL_GCC_VERSION >= 40900) 1155 1156 // g++ 4.8 gives a "conversion from <T> to <U> is ambiguous" error 1157 // if this operator is defined. 1158 template <typename V, 1159 typename = detail::enable_if_t<!is_matcher<V>{}>, 1160 typename = invoke_result_type<Pred, V&&, T...>> 1161 operator V&&() const; 1162 1163 #endif 1164 1165 template <typename V, 1166 typename = detail::enable_if_t<!is_matcher<V>{}>, 1167 typename = invoke_result_type<Pred, V&, T...>> 1168 operator V&() const volatile; 1169 }; 1170 1171 template <typename T> 1172 using ostream_insertion = decltype(std::declval<std::ostream&>() << std::declval<T>()); 1173 1174 template <typename T> 1175 using is_output_streamable = std::integral_constant<bool, is_detected<ostream_insertion, T>::value && !std::is_array<T>::value>; 1176 1177 struct stream_sentry 1178 { 1179 stream_sentry( 1180 std::ostream& os_) 1181 : os(os_) 1182 , width(os.width(0)) 1183 , flags(os.flags(std::ios_base::dec | std::ios_base::left)) 1184 , fill(os.fill(' ')) 1185 { } 1186 ~stream_sentry() 1187 { 1188 os.flags(flags); 1189 os.fill(fill); 1190 os.width(width); 1191 } 1192 private: 1193 std::ostream& os; 1194 std::streamsize width; 1195 std::ios_base::fmtflags flags; 1196 char fill; 1197 }; 1198 1199 struct indirect_null { 1200 #if !TROMPELOEIL_CLANG 1201 template < 1202 typename T, 1203 typename = detail::enable_if_t<std::is_convertible<std::nullptr_t, T>::value> 1204 > 1205 operator T&&() const = delete; 1206 #endif 1207 #if TROMPELOEIL_GCC || TROMPELOEIL_MSVC 1208 1209 template <typename T, typename C, typename ... As> 1210 using memfunptr = T (C::*)(As...); 1211 1212 template <typename T> 1213 operator T*() const; 1214 template <typename T, typename C> 1215 operator T C::*() const; 1216 template <typename T, typename C, typename ... As> 1217 operator memfunptr<T,C,As...>() const; 1218 #endif /* TROMPELOEIL_GCC */ 1219 operator std::nullptr_t() const; 1220 }; 1221 1222 template <typename T, typename U> 1223 using equality_comparison = decltype((std::declval<T const&>() == std::declval<U const&>()) 1224 ? true 1225 : false); 1226 1227 template <typename T, typename U> 1228 using is_equal_comparable = is_detected<equality_comparison, T, U>; 1229 1230 #if defined(_MSC_VER) && (_MSC_VER < 1910) 1231 template <typename T> 1232 using is_null_comparable = is_equal_comparable<T, std::nullptr_t>; 1233 #else 1234 template <typename T> 1235 using is_null_comparable = is_equal_comparable<T, indirect_null>; 1236 #endif 1237 1238 template <typename T, typename = decltype(std::declval<T const&>() == nullptr)> 1239 inline 1240 constexpr 1241 auto 1242 is_null_redirect( 1243 T const &t) 1244 noexcept(noexcept(std::declval<T const&>() == nullptr)) 1245 -> decltype(t == nullptr) 1246 { 1247 return t == nullptr; 1248 } 1249 1250 template <typename T> 1251 inline 1252 constexpr 1253 auto 1254 is_null( 1255 T const &t, 1256 std::true_type) 1257 noexcept(noexcept(is_null_redirect(t))) 1258 -> decltype(is_null_redirect(t)) 1259 { 1260 // Redirect evaluation to suppress wrong non-null warnings in g++ 9 and 10. 1261 return is_null_redirect(t); 1262 } 1263 1264 template <typename T, typename V> 1265 inline 1266 constexpr 1267 bool 1268 is_null( 1269 T const &, 1270 V) 1271 noexcept 1272 { 1273 return false; 1274 } 1275 1276 template <typename T> 1277 inline 1278 constexpr 1279 bool 1280 is_null( 1281 T const &, 1282 std::false_type) 1283 noexcept 1284 { 1285 return false; 1286 } 1287 1288 template <typename T> 1289 inline 1290 constexpr 1291 bool 1292 is_null( 1293 T const &t) 1294 { 1295 // g++-4.9 uses C++11 rules for constexpr function, so can't 1296 // break this up into smaller bits 1297 using tag = std::integral_constant<bool, is_null_comparable<T>::value 1298 && !is_matcher<T>::value 1299 && !std::is_array<T>::value>; 1300 1301 return ::trompeloeil::is_null(t, tag{}); 1302 } 1303 1304 template <typename T> 1305 void 1306 print( 1307 std::ostream& os, 1308 T const &t); 1309 1310 template <typename T> 1311 using iterable = decltype(std::begin(std::declval<T&>()) == std::end(std::declval<T&>())); 1312 1313 template <typename T> 1314 using is_collection = is_detected<iterable, T>; 1315 1316 template <typename T, 1317 bool = is_output_streamable<T>::value, 1318 bool = is_collection<detail::remove_reference_t<T>>::value> 1319 struct streamer 1320 { 1321 static 1322 void 1323 print( 1324 std::ostream& os, 1325 T const &t) 1326 { 1327 stream_sentry s(os); 1328 os << t; 1329 } 1330 }; 1331 1332 template <typename ... T> 1333 struct streamer<std::tuple<T...>, false, false> 1334 { 1335 static 1336 void 1337 print( 1338 std::ostream& os, 1339 std::tuple<T...> const& t) 1340 { 1341 print_tuple(os, t, detail::index_sequence_for<T...>{}); 1342 } 1343 template <size_t ... I> 1344 static 1345 void 1346 print_tuple( 1347 std::ostream& os, 1348 std::tuple<T...> const& t, 1349 detail::index_sequence<I...>) 1350 { 1351 os << "{ "; 1352 const char* sep = ""; 1353 std::initializer_list<const char*> v{((os << sep), 1354 ::trompeloeil::print(os, std::get<I>(t)), 1355 (sep = ", "))...}; 1356 ignore(v); 1357 os << " }"; 1358 } 1359 }; 1360 1361 template <typename T, typename U> 1362 struct streamer<std::pair<T, U>, false, false> 1363 { 1364 static 1365 void 1366 print( 1367 std::ostream& os, 1368 std::pair<T, U> const& t) 1369 { 1370 os << "{ "; 1371 ::trompeloeil::print(os, t.first); 1372 os << ", "; 1373 ::trompeloeil::print(os, t.second); 1374 os << " }"; 1375 } 1376 }; 1377 1378 template <typename T> 1379 struct streamer<T, false, true> 1380 { 1381 static 1382 void 1383 print( 1384 std::ostream& os, 1385 T const& t) 1386 { 1387 os << "{ "; 1388 const char* sep = ""; 1389 auto const end = std::end(t); 1390 for (auto i = std::begin(t); i != end; ++i) 1391 { 1392 os << sep; 1393 ::trompeloeil::print(os, *i); 1394 sep = ", "; 1395 } 1396 os << " }"; 1397 } 1398 }; 1399 1400 template <typename T> 1401 struct streamer<T, false, false> 1402 { 1403 static 1404 void 1405 print( 1406 std::ostream& os, 1407 T const &t) 1408 { 1409 stream_sentry s(os); 1410 static const char *linebreak = "\n"; 1411 os << sizeof(T) << "-byte object={"; 1412 os << (linebreak + (sizeof(T) <= 8)); // stupid construction silences VS2015 warning 1413 os << std::setfill('0') << std::hex; 1414 auto p = reinterpret_cast<uint8_t const*>(&t); 1415 for (size_t i = 0; i < sizeof(T); ++i) 1416 { 1417 os << " 0x" << std::setw(2) << unsigned(p[i]); 1418 if ((i & 0xf) == 0xf) os << '\n'; 1419 } 1420 os << " }"; 1421 } 1422 }; 1423 1424 template <typename T> 1425 struct printer 1426 { 1427 static 1428 void 1429 print( 1430 std::ostream& os, 1431 T const & t) 1432 { 1433 streamer<T>::print(os, t); 1434 } 1435 }; 1436 1437 template <typename T> 1438 void 1439 print( 1440 std::ostream& os, 1441 T const &t) 1442 { 1443 if (is_null(t)) 1444 { 1445 os << "nullptr"; 1446 } 1447 else 1448 { 1449 printer<T>::print(os, t); 1450 } 1451 } 1452 1453 inline 1454 void 1455 print( 1456 std::ostream& os, 1457 std::nullptr_t) 1458 { 1459 os << "nullptr"; 1460 } 1461 1462 inline 1463 constexpr 1464 auto 1465 param_compare_operator( 1466 ...) 1467 TROMPELOEIL_TRAILING_RETURN_TYPE(const char*) 1468 { 1469 return " == "; 1470 } 1471 1472 inline 1473 constexpr 1474 auto 1475 param_compare_operator( 1476 matcher const*) 1477 TROMPELOEIL_TRAILING_RETURN_TYPE(const char*) 1478 { 1479 return ""; 1480 } 1481 1482 template <typename T> 1483 void 1484 print_expectation( 1485 std::ostream& os, 1486 T const& t) 1487 { 1488 os << param_compare_operator(&t); 1489 print(os, t); 1490 os << '\n'; 1491 } 1492 1493 template <typename T> 1494 class list_elem 1495 { 1496 public: 1497 list_elem( 1498 const list_elem&) 1499 = delete; 1500 1501 list_elem( 1502 list_elem &&r) 1503 noexcept 1504 { 1505 *this = std::move(r); 1506 } 1507 1508 list_elem& 1509 operator=( 1510 list_elem &&r) 1511 noexcept 1512 { 1513 if (this != &r) 1514 { 1515 next = r.next; 1516 prev = &r; 1517 r.invariant_check(); 1518 1519 next->prev = this; 1520 r.next = this; 1521 1522 TROMPELOEIL_ASSERT(next->prev == this); 1523 TROMPELOEIL_ASSERT(prev->next == this); 1524 1525 r.unlink(); 1526 1527 TROMPELOEIL_ASSERT(!r.is_linked()); 1528 invariant_check(); 1529 } 1530 return *this; 1531 } 1532 1533 list_elem& 1534 operator=( 1535 const list_elem&) 1536 = delete; 1537 1538 virtual 1539 ~list_elem() 1540 { 1541 unlink(); 1542 } 1543 1544 void 1545 unlink() 1546 noexcept 1547 { 1548 invariant_check(); 1549 auto n = next; 1550 auto p = prev; 1551 n->prev = p; 1552 p->next = n; 1553 next = this; 1554 prev = this; 1555 invariant_check(); 1556 } 1557 1558 void 1559 invariant_check() 1560 const 1561 noexcept 1562 { 1563 #ifdef TROMPELOEIL_SANITY_CHECKS 1564 TROMPELOEIL_ASSERT(next->prev == this); 1565 TROMPELOEIL_ASSERT(prev->next == this); 1566 TROMPELOEIL_ASSERT((next == this) == (prev == this)); 1567 TROMPELOEIL_ASSERT((prev->next == next) == (next == this)); 1568 TROMPELOEIL_ASSERT((next->prev == prev) == (prev == this)); 1569 auto pp = prev; 1570 auto nn = next; 1571 do { 1572 TROMPELOEIL_ASSERT((nn == this) == (pp == this)); 1573 TROMPELOEIL_ASSERT(nn->next->prev == nn); 1574 TROMPELOEIL_ASSERT(nn->prev->next == nn); 1575 TROMPELOEIL_ASSERT(pp->next->prev == pp); 1576 TROMPELOEIL_ASSERT(pp->prev->next == pp); 1577 TROMPELOEIL_ASSERT((nn->next == nn) == (nn == this)); 1578 TROMPELOEIL_ASSERT((pp->prev == pp) == (pp == this)); 1579 nn = nn->next; 1580 pp = pp->prev; 1581 } while (nn != this); 1582 #endif 1583 } 1584 1585 bool 1586 is_linked() 1587 const 1588 noexcept 1589 { 1590 invariant_check(); 1591 return next != this; 1592 } 1593 protected: 1594 list_elem() noexcept = default; 1595 public: 1596 list_elem* next = this; 1597 list_elem* prev = this; 1598 }; 1599 1600 class ignore_disposer 1601 { 1602 protected: 1603 template <typename T> 1604 TROMPELOEIL_NORETURN 1605 void 1606 dispose( 1607 T*) 1608 const 1609 noexcept 1610 { 1611 std::abort(); // must never be called 1612 } 1613 }; 1614 1615 class delete_disposer 1616 { 1617 protected: 1618 template <typename T> 1619 void 1620 dispose( 1621 T* t) 1622 const 1623 { 1624 delete t; 1625 } 1626 }; 1627 1628 template <typename T, typename Disposer = ignore_disposer> 1629 class list : private list_elem<T>, private Disposer 1630 { 1631 public: 1632 list() noexcept; 1633 list(list&&) noexcept; 1634 list(const list&) = delete; 1635 list& operator=(list&&) noexcept; 1636 list& operator=(const list&) = delete; 1637 ~list() override; 1638 class iterator; 1639 iterator begin() const noexcept; 1640 iterator end() const noexcept; 1641 iterator push_front(T* t) noexcept; 1642 iterator push_back(T* t) noexcept; 1643 bool empty() const noexcept { return begin() == end(); } 1644 private: 1645 using list_elem<T>::invariant_check; 1646 using list_elem<T>::next; 1647 using list_elem<T>::prev; 1648 }; 1649 1650 template <typename T, typename Disposer> 1651 class list<T, Disposer>::iterator 1652 { 1653 friend class list<T, Disposer>; 1654 typedef std::bidirectional_iterator_tag iterator_category; 1655 typedef T value_type; 1656 typedef std::ptrdiff_t difference_type; 1657 typedef T* pointer; 1658 typedef T& reference; 1659 public: 1660 iterator() 1661 noexcept 1662 : p{nullptr} 1663 {} 1664 1665 friend 1666 bool 1667 operator==( 1668 iterator const &lh, 1669 iterator const &rh) 1670 noexcept 1671 { 1672 return lh.p == rh.p; 1673 } 1674 1675 friend 1676 bool 1677 operator!=( 1678 iterator const &lh, 1679 iterator const &rh) 1680 noexcept 1681 { 1682 return !(lh == rh); 1683 } 1684 1685 iterator& 1686 operator++() 1687 noexcept 1688 { 1689 p = p->next; 1690 return *this; 1691 } 1692 1693 iterator 1694 operator++(int) 1695 noexcept 1696 { 1697 auto rv = *this; 1698 operator++(); 1699 return rv; 1700 } 1701 1702 T& 1703 operator*() 1704 noexcept 1705 { 1706 return static_cast<T&>(*p); 1707 } 1708 1709 T* 1710 operator->() 1711 noexcept 1712 { 1713 return static_cast<T*>(p); 1714 } 1715 1716 private: 1717 iterator( 1718 list_elem<T> const *t) 1719 noexcept 1720 : p{const_cast<list_elem<T>*>(t)} 1721 {} 1722 1723 list_elem<T>* p; 1724 }; 1725 1726 template <typename T, typename Disposer> 1727 list<T, Disposer>::list() noexcept = default; 1728 1729 template <typename T, typename Disposer> 1730 list<T, Disposer>::list(list&&) noexcept = default; 1731 1732 template <typename T, typename Disposer> 1733 list<T, Disposer>& list<T, Disposer>::operator=(list&&) noexcept = default; 1734 1735 template <typename T, typename Disposer> 1736 list<T, Disposer>::~list() 1737 { 1738 auto i = this->begin(); 1739 while (i != this->end()) 1740 { 1741 auto p = i++; 1742 Disposer::dispose(&*p); 1743 } 1744 } 1745 1746 template <typename T, typename Disposer> 1747 auto 1748 list<T, Disposer>::begin() 1749 const 1750 noexcept 1751 -> iterator 1752 { 1753 return {next}; 1754 } 1755 1756 template <typename T, typename Disposer> 1757 auto 1758 list<T, Disposer>::end() 1759 const 1760 noexcept 1761 -> iterator 1762 { 1763 return {this}; 1764 } 1765 1766 template <typename T, typename Disposer> 1767 auto 1768 list<T, Disposer>::push_front( 1769 T* t) 1770 noexcept 1771 -> iterator 1772 { 1773 invariant_check(); 1774 t->next = next; 1775 t->prev = this; 1776 next->prev = t; 1777 next = t; 1778 invariant_check(); 1779 return {t}; 1780 } 1781 1782 template <typename T, typename Disposer> 1783 auto 1784 list<T, Disposer>::push_back( 1785 T* t) 1786 noexcept 1787 -> iterator 1788 { 1789 invariant_check(); 1790 t->prev = prev; 1791 t->next = this; 1792 prev->next = t; 1793 prev = t; 1794 invariant_check(); 1795 return {t}; 1796 } 1797 1798 class sequence_matcher; 1799 1800 class sequence_type 1801 { 1802 public: 1803 sequence_type() noexcept = default; 1804 sequence_type(sequence_type&&) noexcept = delete; 1805 sequence_type(const sequence_type&) = delete; 1806 sequence_type& operator=(sequence_type&&) noexcept = delete; 1807 sequence_type& operator=(const sequence_type&) = delete; 1808 ~sequence_type(); 1809 1810 bool 1811 is_completed() 1812 const 1813 noexcept; 1814 1815 bool 1816 is_first( 1817 sequence_matcher const *m) 1818 const 1819 noexcept; 1820 1821 unsigned 1822 cost( 1823 sequence_matcher const *m) 1824 const 1825 noexcept; 1826 1827 void 1828 retire_until( 1829 sequence_matcher const* m) 1830 noexcept; 1831 1832 void 1833 add_last( 1834 sequence_matcher *m) 1835 noexcept; 1836 1837 void 1838 validate_match( 1839 severity s, 1840 sequence_matcher const *matcher, 1841 char const *seq_name, 1842 char const *match_name, 1843 location loc) 1844 const; 1845 1846 private: 1847 list<sequence_matcher> matchers; 1848 }; 1849 1850 class sequence 1851 { 1852 public: 1853 sequence() : obj(new sequence_type) {} 1854 sequence_type& operator*() { return *obj; } 1855 bool is_completed() const { return obj->is_completed(); } 1856 private: 1857 std::unique_ptr<sequence_type> obj; 1858 }; 1859 1860 struct sequence_handler_base; 1861 1862 class sequence_matcher : public list_elem<sequence_matcher> 1863 { 1864 public: 1865 using init_type = std::pair<char const*, sequence&>; 1866 1867 sequence_matcher( 1868 char const *exp, 1869 location loc, 1870 const sequence_handler_base& handler, 1871 init_type i) 1872 noexcept 1873 : seq_name(i.first) 1874 , exp_name(exp) 1875 , exp_loc(loc) 1876 , sequence_handler(handler) 1877 , seq(*i.second) 1878 { 1879 auto lock = get_lock(); 1880 seq.add_last(this); 1881 } 1882 1883 void 1884 validate_match( 1885 severity s, 1886 char const *match_name, 1887 location loc) 1888 const 1889 { 1890 seq.validate_match(s, this, seq_name, match_name, loc); 1891 } 1892 1893 unsigned 1894 cost() 1895 const 1896 noexcept 1897 { 1898 return seq.cost(this); 1899 } 1900 1901 bool 1902 is_satisfied() 1903 const 1904 noexcept; 1905 1906 void 1907 retire() 1908 noexcept 1909 { 1910 this->unlink(); 1911 } 1912 1913 void 1914 retire_predecessors() 1915 noexcept 1916 { 1917 seq.retire_until(this); 1918 } 1919 1920 void 1921 print_expectation(std::ostream& os) 1922 const 1923 { 1924 os << exp_name << " at " << exp_loc; 1925 } 1926 1927 char const* 1928 sequence_name() 1929 noexcept 1930 { 1931 return seq_name; 1932 } 1933 private: 1934 char const *seq_name; 1935 char const *exp_name; 1936 location exp_loc; 1937 const sequence_handler_base& sequence_handler; 1938 sequence_type& seq; 1939 }; 1940 1941 inline 1942 bool 1943 sequence_type::is_completed() 1944 const 1945 noexcept 1946 { 1947 return matchers.empty(); 1948 } 1949 1950 inline 1951 bool 1952 sequence_type::is_first( 1953 sequence_matcher const *m) 1954 const 1955 noexcept 1956 { 1957 return !matchers.empty() && &*matchers.begin() == m; 1958 } 1959 1960 inline 1961 unsigned 1962 sequence_type::cost( 1963 sequence_matcher const* m) 1964 const 1965 noexcept 1966 { 1967 unsigned sequence_cost = 0U; 1968 for (auto& e : matchers) 1969 { 1970 if (&e == m) return sequence_cost; 1971 if (!e.is_satisfied()) 1972 { 1973 return ~0U; 1974 } 1975 ++sequence_cost; 1976 } 1977 return ~0U; 1978 } 1979 1980 inline 1981 void 1982 sequence_type::retire_until( 1983 sequence_matcher const* m) 1984 noexcept 1985 { 1986 while (!matchers.empty()) 1987 { 1988 auto first = &*matchers.begin(); 1989 if (first == m) return; 1990 first->retire(); 1991 } 1992 } 1993 1994 inline 1995 void 1996 sequence_type::validate_match( 1997 severity s, 1998 sequence_matcher const *matcher, 1999 char const* seq_name, 2000 char const* match_name, 2001 location loc) 2002 const 2003 { 2004 if (is_first(matcher)) return; 2005 for (auto& m : matchers) 2006 { 2007 std::ostringstream os; 2008 os << "Sequence mismatch for sequence \"" << seq_name 2009 << "\" with matching call of " << match_name 2010 << " at " << loc 2011 << ". Sequence \"" << seq_name << "\" has "; 2012 m.print_expectation(os); 2013 os << " first in line\n"; 2014 send_report<specialized>(s, loc, os.str()); 2015 } 2016 } 2017 2018 inline 2019 sequence_type::~sequence_type() 2020 { 2021 bool touched = false; 2022 std::ostringstream os; 2023 while (!matchers.empty()) 2024 { 2025 auto m = matchers.begin(); 2026 if (!touched) 2027 { 2028 os << "Sequence expectations not met at destruction of sequence object \"" 2029 << m->sequence_name() << "\":"; 2030 touched = true; 2031 } 2032 os << "\n missing "; 2033 m->print_expectation(os); 2034 m->unlink(); 2035 } 2036 if (touched) 2037 { 2038 os << "\n"; 2039 send_report<specialized>(severity::nonfatal, location{}, os.str()); 2040 } 2041 } 2042 2043 inline 2044 void 2045 sequence_type::add_last( 2046 sequence_matcher *m) 2047 noexcept 2048 { 2049 matchers.push_back(m); 2050 } 2051 2052 template <typename T> 2053 void can_match_parameter(T&); 2054 2055 template <typename T> 2056 void can_match_parameter(T&&); 2057 2058 template <typename M> 2059 class ptr_deref : public matcher 2060 { 2061 public: 2062 template <typename U, 2063 typename = decltype(can_match_parameter<detail::remove_reference_t<decltype(*std::declval<U>())>>(std::declval<M>()))> 2064 operator U() const; 2065 2066 template <typename U> 2067 explicit 2068 ptr_deref( 2069 U&& m_) 2070 : m( std::forward<U>(m_) ) 2071 {} 2072 2073 template <typename U> 2074 bool 2075 matches( 2076 const U& u) 2077 const 2078 noexcept(noexcept(std::declval<M>().matches(*u))) 2079 { 2080 return (u != nullptr) && m.matches(*u); 2081 } 2082 2083 friend 2084 std::ostream& 2085 operator<<( 2086 std::ostream& os, 2087 ptr_deref<M> const& p) 2088 { 2089 return os << p.m; 2090 } 2091 private: 2092 M m; 2093 }; 2094 2095 template <typename M> 2096 class neg_matcher : public matcher 2097 { 2098 public: 2099 template <typename U, 2100 typename = decltype(can_match_parameter<detail::remove_reference_t<decltype(std::declval<U>())>>(std::declval<M>()))> 2101 operator U() const; 2102 2103 template <typename U> 2104 explicit 2105 neg_matcher( 2106 U&& m_) 2107 : m( std::forward<U>(m_) ) 2108 {} 2109 2110 template <typename U> 2111 bool 2112 matches( 2113 const U& u) 2114 const 2115 noexcept(noexcept(!std::declval<M>().matches(u))) 2116 { 2117 return !m.matches(u); 2118 } 2119 2120 friend 2121 std::ostream& 2122 operator<<( 2123 std::ostream& os, 2124 neg_matcher<M> const& p) 2125 { 2126 return os << p.m; 2127 } 2128 private: 2129 M m; 2130 }; 2131 2132 template <typename MatchType, typename Predicate, typename ... ActualType> 2133 struct matcher_kind 2134 { 2135 using type = typed_matcher<MatchType>; 2136 }; 2137 2138 template <typename Predicate, typename ... ActualType> 2139 struct matcher_kind<wildcard, Predicate, ActualType...> 2140 { 2141 using type = duck_typed_matcher<Predicate, ActualType...>; 2142 }; 2143 2144 template <typename MatchType, typename Predicate, typename ... ActualType> 2145 using matcher_kind_t = 2146 typename matcher_kind<MatchType, Predicate, ActualType...>::type; 2147 2148 template <typename Predicate, typename Printer, typename MatcherType, typename ... T> 2149 class predicate_matcher 2150 : private Predicate 2151 , private Printer 2152 , public MatcherType 2153 { 2154 public: 2155 template <typename ... U> 2156 constexpr 2157 predicate_matcher( 2158 Predicate&& pred, 2159 Printer&& printer, 2160 U&& ... v) 2161 noexcept(noexcept(std::tuple<T...>(std::declval<U>()...)) && noexcept(Predicate(std::declval<Predicate&&>())) && noexcept(Printer(std::declval<Printer&&>()))) 2162 : Predicate(std::move(pred)) 2163 , Printer(std::move(printer)) 2164 , value(std::forward<U>(v)...) 2165 {} 2166 2167 template <typename V> 2168 constexpr 2169 bool 2170 matches( 2171 V&& v) 2172 const 2173 noexcept(noexcept(std::declval<Predicate const&>()(std::declval<V&&>(), std::declval<const T&>()...))) 2174 { 2175 return matches_(std::forward<V>(v), detail::make_index_sequence<sizeof...(T)>{}); 2176 } 2177 2178 friend 2179 std::ostream& 2180 operator<<( 2181 std::ostream& os, 2182 predicate_matcher const& v) 2183 { 2184 return v.print_(os, detail::make_index_sequence<sizeof...(T)>{}); 2185 } 2186 private: 2187 // The below function call operator must be declared to 2188 // work around gcc bug 78446 2189 // 2190 // For some reason microsoft compiler from VS2015 update 3 2191 // requires the function call operator to be private to avoid 2192 // ambiguities. 2193 template <typename ... U> 2194 void operator()(U&&...) const = delete; 2195 2196 template <typename V, size_t ... I> 2197 bool matches_(V&& v, detail::index_sequence<I...>) const 2198 { 2199 return Predicate::operator()(std::forward<V>(v), std::get<I>(value)...); 2200 } 2201 2202 template <size_t ... I> 2203 std::ostream& print_(std::ostream& os_, detail::index_sequence<I...>) const 2204 { 2205 Printer::operator()(os_, std::get<I>(value)...); 2206 return os_; 2207 } 2208 2209 std::tuple<T...> value; 2210 }; 2211 2212 template <typename MatchType, typename Predicate, typename Printer, typename ... T> 2213 using make_matcher_return = 2214 predicate_matcher<Predicate, 2215 Printer, 2216 matcher_kind_t<MatchType, Predicate, detail::decay_t<T>...>, 2217 detail::decay_t<T>...>; 2218 2219 namespace lambdas { 2220 2221 struct any_predicate 2222 { 2223 template <typename T> 2224 bool 2225 operator()( 2226 T&&) 2227 const 2228 { 2229 return true; 2230 } 2231 }; 2232 2233 // The below must be classes/structs to work with VS 2015 update 3 2234 // since it doesn't respect the trailing return type declaration on 2235 // the lambdas of template deduction context 2236 2237 #define TROMPELOEIL_MK_PRED_BINOP(name, op) \ 2238 struct name { \ 2239 template <typename X, typename Y> \ 2240 auto operator()(X const& x, Y const& y) const -> decltype(x op y) \ 2241 { \ 2242 ::trompeloeil::ignore(x,y); \ 2243 return x op y; \ 2244 } \ 2245 } 2246 TROMPELOEIL_MK_PRED_BINOP(equal, ==); 2247 TROMPELOEIL_MK_PRED_BINOP(not_equal, !=); 2248 TROMPELOEIL_MK_PRED_BINOP(less, <); 2249 TROMPELOEIL_MK_PRED_BINOP(less_equal, <=); 2250 TROMPELOEIL_MK_PRED_BINOP(greater, >); 2251 TROMPELOEIL_MK_PRED_BINOP(greater_equal, >=); 2252 #undef TROMPELOEIL_MK_PRED_BINOP 2253 2254 // Define `struct` with `operator()` to replace generic lambdas. 2255 2256 struct any_printer 2257 { 2258 explicit 2259 any_printer( 2260 char const* type_name_) 2261 : type_name(type_name_) 2262 {} 2263 2264 void 2265 operator()( 2266 std::ostream& os) 2267 const 2268 { 2269 os << " matching ANY(" << type_name << ")"; 2270 } 2271 2272 private: 2273 char const* type_name; 2274 }; 2275 2276 // These structures replace the `op` printer lambdas. 2277 2278 #define TROMPELOEIL_MK_OP_PRINTER(name, op_string) \ 2279 struct name ## _printer \ 2280 { \ 2281 template <typename T> \ 2282 void \ 2283 operator()( \ 2284 std::ostream& os, \ 2285 T const& value) \ 2286 const \ 2287 { \ 2288 os << op_string; \ 2289 ::trompeloeil::print(os, value); \ 2290 } \ 2291 } 2292 TROMPELOEIL_MK_OP_PRINTER(equal, " == "); 2293 TROMPELOEIL_MK_OP_PRINTER(not_equal, " != "); 2294 TROMPELOEIL_MK_OP_PRINTER(less, " < "); 2295 TROMPELOEIL_MK_OP_PRINTER(less_equal, " <= "); 2296 TROMPELOEIL_MK_OP_PRINTER(greater, " > "); 2297 TROMPELOEIL_MK_OP_PRINTER(greater_equal, " >= "); 2298 #undef TROMPELOEIL_MK_OP_PRINTER 2299 2300 } 2301 2302 template <typename MatchType, typename Predicate, typename Printer, typename ... T> 2303 inline 2304 make_matcher_return<MatchType, Predicate, Printer, T...> 2305 make_matcher(Predicate pred, Printer print, T&& ... t) 2306 { 2307 return {std::move(pred), std::move(print), std::forward<T>(t)...}; 2308 } 2309 2310 2311 template < 2312 typename T, 2313 typename R = make_matcher_return<T, lambdas::any_predicate, lambdas::any_printer>> 2314 inline 2315 auto 2316 any_matcher_impl(char const* type_name, std::false_type) 2317 TROMPELOEIL_TRAILING_RETURN_TYPE(R) 2318 { 2319 return make_matcher<T>(lambdas::any_predicate(), lambdas::any_printer(type_name)); 2320 } 2321 2322 template <typename T> 2323 wildcard 2324 any_matcher_impl(char const*, std::true_type); 2325 2326 template <typename T> 2327 inline 2328 auto 2329 any_matcher(char const* name) 2330 TROMPELOEIL_TRAILING_RETURN_TYPE(decltype(any_matcher_impl<T>(name, std::is_array<T>{}))) 2331 { 2332 static_assert(!std::is_array<T>::value, 2333 "array parameter type decays to pointer type for ANY()" 2334 " matcher. Please rephrase as pointer instead"); 2335 return any_matcher_impl<T>(name, std::is_array<T>{}); 2336 } 2337 template < 2338 typename T = wildcard, 2339 typename V, 2340 typename R = make_matcher_return<T, lambdas::equal, lambdas::equal_printer, V>> 2341 inline 2342 auto 2343 eq( 2344 V&& v) 2345 TROMPELOEIL_TRAILING_RETURN_TYPE(R) 2346 { 2347 return make_matcher<T>(lambdas::equal(), 2348 lambdas::equal_printer(), 2349 std::forward<V>(v)); 2350 } 2351 2352 template < 2353 typename T = wildcard, 2354 typename V, 2355 typename R = make_matcher_return<T, lambdas::not_equal, lambdas::not_equal_printer, V>> 2356 inline 2357 auto 2358 ne( 2359 V&& v) 2360 TROMPELOEIL_TRAILING_RETURN_TYPE(R) 2361 { 2362 return make_matcher<T>(lambdas::not_equal(), 2363 lambdas::not_equal_printer(), 2364 std::forward<V>(v)); 2365 } 2366 2367 template < 2368 typename T = wildcard, 2369 typename V, 2370 typename R = make_matcher_return<T, lambdas::greater_equal, lambdas::greater_equal_printer, V>> 2371 inline 2372 auto 2373 ge( 2374 V&& v) 2375 TROMPELOEIL_TRAILING_RETURN_TYPE(R) 2376 { 2377 return make_matcher<T>(lambdas::greater_equal(), 2378 lambdas::greater_equal_printer(), 2379 std::forward<V>(v)); 2380 } 2381 2382 template < 2383 typename T = wildcard, 2384 typename V, 2385 typename R = make_matcher_return<T, lambdas::greater, lambdas::greater_printer, V>> 2386 inline 2387 auto 2388 gt( 2389 V&& v) 2390 TROMPELOEIL_TRAILING_RETURN_TYPE(R) 2391 { 2392 return make_matcher<T>(lambdas::greater(), 2393 lambdas::greater_printer(), 2394 std::forward<V>(v)); 2395 } 2396 2397 template < 2398 typename T = wildcard, 2399 typename V, 2400 typename R = make_matcher_return<T, lambdas::less, lambdas::less_printer, V>> 2401 inline 2402 auto 2403 lt( 2404 V&& v) 2405 TROMPELOEIL_TRAILING_RETURN_TYPE(R) 2406 { 2407 return make_matcher<T>(lambdas::less(), 2408 lambdas::less_printer(), 2409 std::forward<V>(v)); 2410 } 2411 2412 template < 2413 typename T = wildcard, 2414 typename V, 2415 typename R = make_matcher_return<T, lambdas::less_equal, lambdas::less_equal_printer, V>> 2416 inline 2417 auto 2418 le( 2419 V&& v) 2420 TROMPELOEIL_TRAILING_RETURN_TYPE(R) 2421 { 2422 return make_matcher<T>(lambdas::less_equal(), 2423 lambdas::less_equal_printer(), 2424 std::forward<V>(v)); 2425 } 2426 2427 namespace lambdas { 2428 2429 struct regex_check 2430 { 2431 2432 class string_helper // a vastly simplified string_view type of class 2433 { 2434 public: 2435 string_helper( 2436 std::string const& s) 2437 noexcept 2438 : str(s.c_str()) 2439 {} 2440 2441 constexpr 2442 string_helper( 2443 char const* s) 2444 noexcept 2445 : str(s) 2446 {} 2447 2448 char const* 2449 c_str() 2450 const 2451 noexcept 2452 { 2453 return str; 2454 } 2455 private: 2456 char const* str; 2457 }; 2458 2459 regex_check( 2460 std::regex&& re_, 2461 std::regex_constants::match_flag_type match_type_) 2462 : re(std::move(re_)), 2463 match_type(match_type_) 2464 {} 2465 2466 template <typename T> 2467 bool 2468 operator()( 2469 string_helper str, 2470 T const&) 2471 const 2472 { 2473 return str.c_str() 2474 && std::regex_search(str.c_str(), re, match_type); 2475 } 2476 2477 private: 2478 std::regex re; 2479 std::regex_constants::match_flag_type match_type; 2480 }; 2481 2482 struct regex_printer 2483 { 2484 template <typename T> 2485 void 2486 operator()( 2487 std::ostream& os, 2488 T const& str) 2489 const 2490 { 2491 os << " matching regular expression /" << str << "/"; 2492 } 2493 }; 2494 } 2495 2496 template < 2497 typename Kind = wildcard, 2498 typename R = make_matcher_return<Kind, lambdas::regex_check, lambdas::regex_printer, std::string&&>> 2499 auto 2500 re( 2501 std::string s, 2502 std::regex_constants::syntax_option_type opt = std::regex_constants::ECMAScript, 2503 std::regex_constants::match_flag_type match_type = std::regex_constants::match_default) 2504 TROMPELOEIL_TRAILING_RETURN_TYPE(R) 2505 { 2506 return make_matcher<Kind>(lambdas::regex_check(std::regex(s, opt), 2507 match_type), 2508 lambdas::regex_printer(), 2509 std::move(s)); 2510 } 2511 2512 template < 2513 typename Kind = wildcard, 2514 typename R = make_matcher_return<Kind, lambdas::regex_check, lambdas::regex_printer, std::string&&>> 2515 auto 2516 re( 2517 std::string s, 2518 std::regex_constants::match_flag_type match_type) 2519 TROMPELOEIL_TRAILING_RETURN_TYPE(R) 2520 { 2521 return make_matcher<Kind>(lambdas::regex_check(std::regex(s), match_type), 2522 lambdas::regex_printer(), 2523 std::move(s)); 2524 } 2525 2526 inline 2527 std::string 2528 param_name_prefix( 2529 ...) 2530 { 2531 return ""; 2532 } 2533 2534 template <typename M> 2535 std::string 2536 param_name_prefix( 2537 const ptr_deref<M>*) 2538 { 2539 return "*" + ::trompeloeil::param_name_prefix(static_cast<M*>(nullptr)); 2540 } 2541 2542 template <typename M> 2543 std::string 2544 param_name_prefix( 2545 const neg_matcher<M>*) 2546 { 2547 return "not " + ::trompeloeil::param_name_prefix(static_cast<M*>(nullptr)); 2548 } 2549 2550 template <typename T> 2551 struct null_on_move 2552 { 2553 public: 2554 null_on_move() 2555 noexcept 2556 : p{nullptr} 2557 {} 2558 2559 null_on_move( 2560 T* p_) 2561 noexcept 2562 : p{p_} 2563 {} 2564 2565 null_on_move( 2566 null_on_move&&) 2567 noexcept 2568 : p{nullptr} 2569 {} 2570 2571 null_on_move( 2572 null_on_move const&) 2573 noexcept 2574 : p{nullptr} 2575 {} 2576 2577 null_on_move& 2578 operator=( 2579 const null_on_move&) 2580 noexcept 2581 { 2582 p = nullptr; 2583 return *this; 2584 } 2585 2586 null_on_move& 2587 operator=( 2588 null_on_move&&) 2589 noexcept 2590 { 2591 p = nullptr; 2592 return *this; 2593 } 2594 2595 null_on_move& 2596 operator=( 2597 T* t) 2598 noexcept 2599 { 2600 p = t; 2601 return *this; 2602 } 2603 2604 T*& 2605 leak() 2606 noexcept 2607 { 2608 return p; 2609 } 2610 2611 T& 2612 operator*() 2613 const 2614 noexcept 2615 { 2616 return *p; 2617 } 2618 2619 T* 2620 operator->() 2621 const 2622 noexcept 2623 { 2624 return p; 2625 } 2626 2627 explicit 2628 operator bool() 2629 const 2630 noexcept 2631 { 2632 return p != nullptr; 2633 } 2634 private: 2635 T* p; 2636 }; 2637 2638 struct sequence_handler_base 2639 { 2640 private: 2641 size_t min_calls{1}; 2642 size_t max_calls{1}; 2643 size_t call_count{0}; 2644 public: 2645 2646 virtual 2647 ~sequence_handler_base() 2648 noexcept = default; 2649 2650 void 2651 increment_call() 2652 noexcept 2653 { 2654 ++call_count; 2655 } 2656 bool 2657 is_satisfied() 2658 const 2659 noexcept 2660 { 2661 return call_count >= min_calls; 2662 } 2663 2664 bool 2665 is_saturated() 2666 const 2667 noexcept 2668 { 2669 return call_count == max_calls; 2670 } 2671 2672 bool 2673 is_forbidden() 2674 const 2675 noexcept 2676 { 2677 return max_calls == 0ULL; 2678 } 2679 2680 void 2681 set_limits(size_t L, size_t H) 2682 noexcept 2683 { 2684 min_calls = L; 2685 max_calls = H; 2686 } 2687 2688 size_t 2689 get_min_calls() 2690 const 2691 noexcept 2692 { 2693 return min_calls; 2694 } 2695 2696 size_t 2697 get_calls() 2698 const 2699 noexcept 2700 { 2701 return call_count; 2702 } 2703 2704 virtual 2705 void 2706 validate(severity s, char const *, location) = 0; 2707 2708 virtual 2709 bool 2710 can_be_called() 2711 const 2712 noexcept = 0; 2713 2714 virtual 2715 unsigned 2716 order() 2717 const 2718 noexcept = 0; 2719 2720 virtual 2721 void 2722 retire() 2723 noexcept = 0; 2724 2725 virtual 2726 void 2727 retire_predecessors() 2728 noexcept = 0; 2729 protected: 2730 sequence_handler_base() = default; 2731 sequence_handler_base(const sequence_handler_base&) = default; 2732 }; 2733 2734 inline 2735 bool 2736 sequence_matcher::is_satisfied() 2737 const 2738 noexcept 2739 { 2740 return sequence_handler.is_satisfied(); 2741 } 2742 2743 template <size_t N> 2744 struct sequence_handler : public sequence_handler_base 2745 { 2746 public: 2747 template <size_t M = N, typename detail::enable_if_t<M == 0>* = nullptr> 2748 sequence_handler() 2749 noexcept 2750 {} 2751 2752 template <typename ... S> 2753 sequence_handler( 2754 const sequence_handler_base& base, 2755 char const *name, 2756 location loc, 2757 S&& ... s) 2758 noexcept 2759 : sequence_handler_base(base) 2760 , matchers{{sequence_matcher{name, loc, *this, std::forward<S>(s)}...}} 2761 { 2762 } 2763 2764 void 2765 validate( 2766 severity s, 2767 char const *match_name, 2768 location loc) 2769 override 2770 { 2771 for (auto& e : matchers) 2772 { 2773 e.validate_match(s, match_name, loc); 2774 } 2775 } 2776 2777 unsigned 2778 order() 2779 const 2780 noexcept 2781 override 2782 { 2783 unsigned highest_order = 0U; 2784 for (auto& m : matchers) 2785 { 2786 auto cost = m.cost(); 2787 if (cost > highest_order) 2788 { 2789 highest_order = cost; 2790 } 2791 } 2792 return highest_order; 2793 } 2794 2795 bool 2796 can_be_called() 2797 const 2798 noexcept 2799 override 2800 { 2801 return order() != ~0U; 2802 } 2803 2804 void 2805 retire() 2806 noexcept 2807 override 2808 { 2809 for (auto& e : matchers) 2810 { 2811 e.retire(); 2812 } 2813 } 2814 2815 void 2816 retire_predecessors() 2817 noexcept 2818 override 2819 { 2820 for (auto& e : matchers) 2821 { 2822 e.retire_predecessors(); 2823 } 2824 } 2825 private: 2826 // work around for MS STL issue 942 2827 // https://github.com/microsoft/STL/issues/942 2828 detail::conditional_t<N == 0, 2829 std::vector<sequence_matcher>, 2830 std::array<sequence_matcher, N>> matchers; 2831 }; 2832 2833 struct lifetime_monitor; 2834 2835 template <typename T> 2836 class deathwatched : public T 2837 { 2838 static_assert(std::has_virtual_destructor<T>::value, 2839 "virtual destructor is a necessity for deathwatched to work"); 2840 public: 2841 template <typename ... U, 2842 typename = detail::enable_if_t<std::is_constructible<T,U...>::value>> 2843 deathwatched( 2844 U&& ...u) 2845 noexcept(noexcept(T(std::declval<U>()...))) 2846 : T(std::forward<U>(u)...) 2847 {} 2848 2849 ~deathwatched() override; 2850 2851 trompeloeil::lifetime_monitor*& 2852 trompeloeil_expect_death( 2853 trompeloeil::lifetime_monitor* monitor) 2854 const 2855 noexcept 2856 { 2857 auto lock = get_lock(); 2858 trompeloeil_lifetime_monitor = monitor; 2859 return trompeloeil_lifetime_monitor.leak(); 2860 } 2861 private: 2862 mutable null_on_move<trompeloeil::lifetime_monitor> trompeloeil_lifetime_monitor; 2863 }; 2864 2865 struct expectation { 2866 virtual ~expectation() = default; 2867 virtual bool is_satisfied() const noexcept = 0; 2868 virtual bool is_saturated() const noexcept = 0; 2869 }; 2870 2871 struct lifetime_monitor : public expectation 2872 { 2873 template <typename T> 2874 lifetime_monitor( 2875 ::trompeloeil::deathwatched<T> const &obj, 2876 char const* obj_name_, 2877 char const* invocation_name_, 2878 char const* call_name_, 2879 location loc_) 2880 noexcept 2881 : object_monitor(obj.trompeloeil_expect_death(this)) 2882 , loc(loc_) 2883 , object_name(obj_name_) 2884 , invocation_name(invocation_name_) 2885 , call_name(call_name_) 2886 { 2887 } 2888 2889 bool is_satisfied() const noexcept override 2890 { 2891 return died; 2892 } 2893 2894 bool is_saturated() const noexcept override 2895 { 2896 return died; 2897 } 2898 2899 lifetime_monitor(lifetime_monitor const&) = delete; 2900 2901 ~lifetime_monitor() override 2902 { 2903 auto lock = get_lock(); 2904 if (!died) 2905 { 2906 std::ostringstream os; 2907 os << "Object " << object_name << " is still alive"; 2908 send_report<specialized>(severity::nonfatal, loc, os.str()); 2909 object_monitor = nullptr; // prevent its death poking this cadaver 2910 } 2911 } 2912 2913 void 2914 notify() 2915 noexcept 2916 { 2917 died = true; 2918 sequences->validate(severity::nonfatal, call_name, loc); 2919 2920 sequences->increment_call(); 2921 if (sequences->is_satisfied()) 2922 { 2923 sequences->retire_predecessors(); 2924 } 2925 } 2926 2927 template <typename ... T> 2928 void 2929 set_sequence( 2930 T&& ... t) 2931 { 2932 using handler = sequence_handler<sizeof...(T)>; 2933 auto seq = detail::make_unique<handler>(*sequences, 2934 invocation_name, 2935 loc, 2936 std::forward<T>(t)...); 2937 sequences = std::move(seq); 2938 } 2939 private: 2940 atomic<bool> died{false}; 2941 lifetime_monitor *&object_monitor; 2942 location loc; 2943 char const *object_name; 2944 char const *invocation_name; 2945 char const *call_name; 2946 std::unique_ptr<sequence_handler_base> sequences = detail::make_unique<sequence_handler<0>>(); 2947 }; 2948 2949 template <typename T> 2950 deathwatched<T>::~deathwatched() 2951 { 2952 auto lock = get_lock(); 2953 if (trompeloeil_lifetime_monitor) 2954 { 2955 trompeloeil_lifetime_monitor->notify(); 2956 return; 2957 } 2958 std::ostringstream os; 2959 os << "Unexpected destruction of " 2960 << TROMPELOEIL_TYPE_ID_NAME(T) << "@" << this << '\n'; 2961 send_report<specialized>(severity::nonfatal, 2962 location{}, 2963 os.str()); 2964 } 2965 2966 template <typename T> 2967 struct return_of; 2968 2969 template <typename R, typename ... A> 2970 struct return_of<R(A...)> 2971 { 2972 using type = R; 2973 }; 2974 2975 template <typename T> 2976 using return_of_t = typename return_of<T>::type; 2977 2978 template <typename T> 2979 struct call_params_type; 2980 2981 template <typename R, typename ... T> 2982 struct call_params_type<R(T...)> 2983 { 2984 using type = std::tuple<typename std::add_lvalue_reference<T>::type...>; 2985 }; 2986 2987 template <typename T> 2988 using call_params_type_t = typename call_params_type<T>::type; 2989 2990 2991 template <typename R> 2992 struct default_return_t 2993 { 2994 TROMPELOEIL_NORETURN static R value() 2995 { 2996 std::abort(); // must never be called 2997 } 2998 }; 2999 3000 #if TROMPELOEIL_MSVC 3001 #pragma warning(push) 3002 #pragma warning(disable : 4702) 3003 #endif 3004 template <typename R> 3005 inline 3006 R 3007 default_return() 3008 { 3009 return default_return_t<R>::value(); 3010 } 3011 #if TROMPELOEIL_MSVC 3012 #pragma warning(pop) 3013 #endif 3014 3015 3016 3017 template <> 3018 inline 3019 void 3020 default_return<void>() 3021 { 3022 } 3023 3024 template <typename Sig> 3025 struct call_matcher_base; 3026 3027 template <typename Sig> 3028 struct call_matcher_list : public list<call_matcher_base<Sig>> 3029 { 3030 void decommission() 3031 { 3032 auto lock = get_lock(); 3033 auto iter = this->begin(); 3034 auto const e = this->end(); 3035 while (iter != e) 3036 { 3037 auto i = iter++; 3038 auto &m = *i; 3039 m.mock_destroyed(); 3040 m.unlink(); 3041 } 3042 } 3043 }; 3044 3045 template <typename Sig> 3046 struct call_matcher_base : public list_elem<call_matcher_base<Sig>> 3047 { 3048 call_matcher_base( 3049 location loc_, 3050 char const* name_) 3051 : loc{loc_} 3052 , name{name_} 3053 { 3054 } 3055 3056 call_matcher_base(call_matcher_base&&) = delete; 3057 3058 ~call_matcher_base() override = default; 3059 3060 virtual 3061 void 3062 mock_destroyed() = 0; 3063 3064 virtual 3065 bool 3066 matches( 3067 call_params_type_t<Sig> const&) 3068 const = 0; 3069 3070 virtual 3071 unsigned 3072 sequence_cost() 3073 const 3074 noexcept = 0; 3075 3076 virtual 3077 void 3078 run_actions( 3079 call_params_type_t<Sig> &, 3080 call_matcher_list<Sig> &saturated_list 3081 ) = 0; 3082 3083 virtual 3084 std::ostream& 3085 report_signature( 3086 std::ostream&) 3087 const = 0; 3088 3089 TROMPELOEIL_NORETURN 3090 virtual 3091 std::ostream& 3092 report_mismatch( 3093 std::ostream&, 3094 call_params_type_t<Sig> const &) = 0; 3095 3096 virtual 3097 return_of_t<Sig> 3098 return_value( 3099 trace_agent&, 3100 call_params_type_t<Sig>& p) = 0; 3101 3102 location loc; 3103 char const *name; 3104 }; 3105 3106 template <typename T, typename U> 3107 bool 3108 param_matches_impl( 3109 T const& t, 3110 U const& u, 3111 matcher const*) 3112 noexcept(noexcept(t.matches(u))) 3113 { 3114 return t.matches(u); 3115 } 3116 3117 template <typename T, 3118 typename U, 3119 typename = detail::enable_if_t<is_equal_comparable<T, U>::value>> 3120 inline 3121 U& 3122 identity( 3123 U& t) 3124 noexcept 3125 { 3126 return t; 3127 } 3128 3129 template <typename T, 3130 typename U, 3131 typename = detail::enable_if_t<!is_equal_comparable<T, U>::value>> 3132 inline 3133 T 3134 identity( 3135 const U& u) 3136 noexcept(noexcept(T(u))) 3137 { 3138 return u; 3139 } 3140 3141 template <typename T, typename U> 3142 bool 3143 param_matches_impl( 3144 T const& t, 3145 U const& u, 3146 ...) 3147 noexcept(noexcept(::trompeloeil::identity<U>(t) == u)) 3148 { 3149 return ::trompeloeil::identity<U>(t) == u; 3150 } 3151 3152 template <typename T, typename U> 3153 bool 3154 param_matches( 3155 T const& t, 3156 U const& u) 3157 noexcept(noexcept(param_matches_impl(t, u, &t))) 3158 { 3159 return ::trompeloeil::param_matches_impl(t, u, &t); 3160 } 3161 3162 template <size_t ... I, typename T, typename U> 3163 bool 3164 match_parameters( 3165 detail::index_sequence<I...>, 3166 T const& t, 3167 U const& u) 3168 noexcept(noexcept(std::initializer_list<bool>{trompeloeil::param_matches(std::get<I>(t),std::get<I>(u))...})) 3169 { 3170 bool all_true = true; 3171 ::trompeloeil::ignore(t, u); // Kills unmotivated VS2015 warning in the empty case 3172 ::trompeloeil::ignore(std::initializer_list<bool>{all_true = all_true && ::trompeloeil::param_matches(std::get<I>(t), std::get<I>(u))...}); 3173 return all_true; 3174 } 3175 3176 template <typename ... T, typename ... U> 3177 bool 3178 match_parameters( 3179 std::tuple<T...> const& t, 3180 std::tuple<U...> const& u) 3181 noexcept(noexcept(match_parameters(detail::make_index_sequence<sizeof...(T)>{}, t, u))) 3182 { 3183 return ::trompeloeil::match_parameters(detail::make_index_sequence<sizeof...(T)>{}, t, u); 3184 } 3185 3186 template <typename V, typename P> 3187 void print_mismatch( 3188 std::ostream& os, 3189 size_t num, 3190 V const& v, 3191 P const& p) 3192 { 3193 if (!::trompeloeil::param_matches(v, p)) 3194 { 3195 auto prefix = ::trompeloeil::param_name_prefix(&v) + "_"; 3196 os << " Expected " << std::setw((num < 9) + 1) << prefix << num+1; 3197 ::trompeloeil::print_expectation(os, v); 3198 } 3199 } 3200 3201 template <typename ... V, typename ... P, size_t ... I> 3202 void print_mismatch( 3203 std::ostream& os, 3204 detail::index_sequence<I...>, 3205 std::tuple<V...> const& v, 3206 std::tuple<P...> const& p) 3207 { 3208 ::trompeloeil::ignore(os, v, p); // Kills unmotivated VS2015 warning in the empty case 3209 ::trompeloeil::ignore(std::initializer_list<int>{(print_mismatch(os, I, std::get<I>(v), std::get<I>(p)),0)...}); 3210 } 3211 3212 template <typename ... V, typename ... P> 3213 void print_mismatch( 3214 std::ostream& os, 3215 std::tuple<V...> const& v, 3216 std::tuple<P...> const& p) 3217 { 3218 print_mismatch(os, detail::make_index_sequence<sizeof...(V)>{}, v, p); 3219 } 3220 3221 template <typename T> 3222 void missed_value( 3223 std::ostream& os, 3224 int i, 3225 T const& t) 3226 { 3227 auto prefix = ::trompeloeil::param_name_prefix(&t) + "_"; 3228 os << " param " << std::setw((i < 9) + 1) << prefix << i + 1 3229 << ::trompeloeil::param_compare_operator(&t); 3230 ::trompeloeil::print(os, t); 3231 os << '\n'; 3232 } 3233 3234 template <size_t ... I, typename ... T> 3235 void stream_params( 3236 std::ostream &os, 3237 detail::index_sequence<I...>, 3238 std::tuple<T...> const &t) 3239 { 3240 ::trompeloeil::ignore(os, t); // Kills unmotivated VS2015 warning in the empty case 3241 ::trompeloeil::ignore(std::initializer_list<int>{(missed_value(os, I, std::get<I>(t)),0)...}); 3242 } 3243 3244 template <typename ... T> 3245 void 3246 stream_params( 3247 std::ostream &os, 3248 std::tuple<T...> const &t) 3249 { 3250 stream_params(os, detail::make_index_sequence<sizeof...(T)>{}, t); 3251 } 3252 3253 template <typename ... T> 3254 std::string 3255 params_string( 3256 std::tuple<T...> const& t) 3257 { 3258 std::ostringstream os; 3259 stream_params(os, t); 3260 return os.str(); 3261 } 3262 3263 class trace_agent 3264 { 3265 public: 3266 trace_agent( 3267 location loc_, 3268 char const* name_, 3269 tracer* t_) 3270 : loc{loc_} 3271 , t{t_} 3272 { 3273 if (t) 3274 { 3275 os << name_ << " with.\n"; 3276 } 3277 } 3278 3279 trace_agent(trace_agent const&) = delete; 3280 3281 trace_agent(trace_agent &&) = delete; 3282 3283 ~trace_agent() 3284 { 3285 if (t) 3286 { 3287 t->trace(loc.file, loc.line, os.str()); 3288 } 3289 } 3290 3291 trace_agent& 3292 operator=(trace_agent const&) = delete; 3293 3294 trace_agent& 3295 operator=(trace_agent &&) = delete; 3296 3297 template <typename ... T> 3298 void 3299 trace_params( 3300 std::tuple<T...> const& params) 3301 { 3302 if (t) 3303 { 3304 stream_params(os, params); 3305 } 3306 } 3307 3308 template <typename T> 3309 auto 3310 trace_return( 3311 T&& rv) 3312 -> T 3313 { 3314 if (t) 3315 { 3316 os << " -> "; 3317 print(os, rv); 3318 os << '\n'; 3319 } 3320 return std::forward<T>(rv); 3321 } 3322 3323 void 3324 trace_exception() 3325 { 3326 if (t) 3327 { 3328 try { 3329 throw; 3330 } 3331 catch (std::exception& e) 3332 { 3333 os << "threw exception: what() = " << e.what() << '\n'; 3334 } 3335 catch (...) 3336 { 3337 os << "threw unknown exception\n"; 3338 } 3339 } 3340 } 3341 private: 3342 location loc; 3343 tracer* t; 3344 std::ostringstream os; 3345 }; 3346 3347 template <typename Sig> 3348 call_matcher_base <Sig> * 3349 find( 3350 call_matcher_list <Sig> &list, 3351 call_params_type_t <Sig> const &p) 3352 noexcept 3353 { 3354 call_matcher_base<Sig>* first_match = nullptr; 3355 unsigned lowest_cost = ~0U; 3356 for (auto& i : list) 3357 { 3358 if (i.matches(p)) 3359 { 3360 unsigned cost = i.sequence_cost(); 3361 if (cost == 0) 3362 { 3363 return &i; 3364 } 3365 if (!first_match || cost < lowest_cost) 3366 { 3367 first_match = &i; 3368 lowest_cost = cost; 3369 } 3370 } 3371 } 3372 return first_match; 3373 } 3374 3375 template <typename Sig> 3376 TROMPELOEIL_NORETURN 3377 void 3378 report_mismatch( 3379 call_matcher_list <Sig> &matcher_list, 3380 call_matcher_list <Sig> &saturated_list, 3381 std::string const &name, 3382 call_params_type_t <Sig> const &p) 3383 { 3384 std::ostringstream os; 3385 os << "No match for call of " << name << " with.\n"; 3386 stream_params(os, p); 3387 bool saturated_match = false; 3388 for (auto& m : saturated_list) 3389 { 3390 if (m.matches(p)) 3391 { 3392 if (!saturated_match) 3393 { 3394 os << "\nMatches saturated call requirement\n"; 3395 saturated_match = true; 3396 } 3397 os << " "; 3398 m.report_signature(os) << '\n'; 3399 } 3400 } 3401 if (!saturated_match) 3402 { 3403 for (auto& m : matcher_list) 3404 { 3405 os << "\nTried "; 3406 m.report_mismatch(os, p); 3407 } 3408 } 3409 send_report<specialized>(severity::fatal, location{}, os.str()); 3410 std::abort(); // must never get here. 3411 } 3412 3413 template <typename Sig> 3414 void 3415 report_match( 3416 call_matcher_list <Sig> &matcher_list) 3417 { 3418 if(! matcher_list.empty()) 3419 { 3420 send_ok_report<specialized>((matcher_list.begin())->name); 3421 } 3422 } 3423 3424 template <typename Sig> 3425 class return_handler 3426 { 3427 public: 3428 virtual 3429 ~return_handler() = default; 3430 3431 virtual 3432 return_of_t<Sig> 3433 call( 3434 trace_agent&, 3435 call_params_type_t<Sig>& params) = 0; 3436 }; 3437 3438 3439 template <typename Ret, typename F, typename P, typename = detail::enable_if_t<std::is_void<Ret>::value>> 3440 void 3441 trace_return( 3442 trace_agent&, 3443 F& func, 3444 P& params) 3445 { 3446 func(params); 3447 } 3448 3449 template <typename Ret, typename F, typename P, typename = detail::enable_if_t<!std::is_void<Ret>::value>> 3450 Ret 3451 trace_return( 3452 trace_agent& agent, 3453 F& func, 3454 P& params) 3455 { 3456 /* Work around VS 2017 15.7.x C4702 warning by 3457 * enclosing the operation in an otherwise 3458 * unnecessary try/catch block. 3459 */ 3460 try 3461 { 3462 return agent.trace_return(func(params)); 3463 } 3464 catch (...) 3465 { 3466 throw; 3467 } 3468 } 3469 3470 template <typename Sig, typename T> 3471 class return_handler_t : public return_handler<Sig> 3472 { 3473 public: 3474 template <typename U> 3475 return_handler_t( 3476 U&& u) 3477 : func(std::forward<U>(u)) 3478 {} 3479 3480 return_of_t<Sig> 3481 call( 3482 trace_agent& agent, 3483 call_params_type_t<Sig>& params) 3484 override 3485 { 3486 return trace_return<return_of_t<Sig>>(agent, func, params); 3487 } 3488 private: 3489 T func; 3490 }; 3491 3492 template <typename Sig> 3493 class condition_base : public list_elem<condition_base<Sig>> 3494 { 3495 public: 3496 condition_base( 3497 char const *n) 3498 noexcept 3499 : id(n) 3500 {} 3501 3502 ~condition_base() override = default; 3503 3504 virtual 3505 bool 3506 check( 3507 call_params_type_t<Sig> const&) 3508 const = 0; 3509 3510 virtual 3511 char const* 3512 name() 3513 const 3514 noexcept 3515 { 3516 return id; 3517 } 3518 private: 3519 char const *id; 3520 }; 3521 3522 template <typename Sig> 3523 using condition_list = list<condition_base<Sig>, delete_disposer>; 3524 3525 template <typename Sig, typename Cond> 3526 struct condition : public condition_base<Sig> 3527 { 3528 condition( 3529 char const *str_, 3530 Cond c_) 3531 : condition_base<Sig>(str_) 3532 , c(c_) {} 3533 3534 bool 3535 check( 3536 call_params_type_t<Sig> const & t) 3537 const 3538 override 3539 { 3540 return c(t); 3541 } 3542 3543 private: 3544 Cond c; 3545 }; 3546 3547 template <typename Sig> 3548 struct side_effect_base : public list_elem<side_effect_base<Sig>> 3549 { 3550 ~side_effect_base() override = default; 3551 3552 virtual 3553 void 3554 action( 3555 call_params_type_t<Sig> &) 3556 const = 0; 3557 }; 3558 3559 template <typename Sig> 3560 using side_effect_list = list<side_effect_base<Sig>, delete_disposer>; 3561 3562 template <typename Sig, typename Action> 3563 struct side_effect : public side_effect_base<Sig> 3564 { 3565 template <typename A> 3566 side_effect( 3567 A&& a_) 3568 : a(std::forward<A>(a_)) 3569 {} 3570 3571 void 3572 action( 3573 call_params_type_t<Sig> &t) 3574 const 3575 override 3576 { 3577 a(t); 3578 } 3579 private: 3580 Action a; 3581 }; 3582 3583 template <size_t L, size_t H = L> 3584 struct multiplicity { }; 3585 3586 template <typename R, typename Parent> 3587 struct return_injector : Parent 3588 { 3589 using return_type = R; 3590 }; 3591 3592 template <typename Parent> 3593 struct throw_injector : Parent 3594 { 3595 static bool const throws = true; 3596 }; 3597 3598 template <typename Parent> 3599 struct sideeffect_injector : Parent 3600 { 3601 static bool const side_effects = true; 3602 }; 3603 3604 template <typename Parent, size_t H> 3605 struct call_limit_injector : Parent 3606 { 3607 static bool const call_limit_set = true; 3608 static size_t const upper_call_limit = H; 3609 }; 3610 3611 template <typename Parent> 3612 struct call_limit_injector<Parent, 0> : Parent 3613 { 3614 static bool const call_limit_set = true; 3615 static size_t const upper_call_limit = 0; 3616 }; 3617 3618 template <typename Parent> 3619 struct sequence_injector : Parent 3620 { 3621 static bool const sequence_set = true; 3622 }; 3623 3624 template <typename Matcher, typename modifier_tag, typename Parent> 3625 struct call_modifier : public Parent 3626 { 3627 using typename Parent::signature; 3628 using typename Parent::return_type; 3629 using Parent::call_limit_set; 3630 using Parent::upper_call_limit; 3631 using Parent::sequence_set; 3632 using Parent::throws; 3633 using Parent::side_effects; 3634 3635 call_modifier( 3636 Matcher* m) 3637 noexcept 3638 : matcher{m} 3639 {} 3640 3641 template <typename D> 3642 call_modifier&& 3643 with( 3644 char const* str, 3645 D&& d) 3646 && 3647 { 3648 matcher->add_condition(str, std::forward<D>(d)); 3649 return std::move(*this); 3650 } 3651 3652 template <typename A> 3653 call_modifier<Matcher, modifier_tag, sideeffect_injector<Parent>> 3654 sideeffect( 3655 A&& a) 3656 { 3657 constexpr bool forbidden = upper_call_limit == 0U; 3658 static_assert(!forbidden, 3659 "SIDE_EFFECT for forbidden call does not make sense"); 3660 matcher->add_side_effect(std::forward<A>(a)); 3661 return {std::move(matcher)}; 3662 } 3663 3664 template <typename H> 3665 call_modifier<Matcher, modifier_tag, return_injector<return_of_t<signature>, Parent >> 3666 handle_return( 3667 H&& h) 3668 { 3669 using params_type = call_params_type_t<signature>&; 3670 using sigret = return_of_t<signature>; 3671 using ret = decltype(std::declval<H>()(std::declval<params_type>())); 3672 // don't know why MS VS 2015 RC doesn't like std::result_of 3673 3674 constexpr bool is_illegal_type = std::is_same<detail::decay_t<ret>, illegal_argument>::value; 3675 constexpr bool is_first_return = std::is_same<return_type, void>::value; 3676 constexpr bool void_signature = std::is_same<sigret, void>::value; 3677 constexpr bool is_pointer_sigret = std::is_pointer<sigret>::value; 3678 constexpr bool is_pointer_ret = std::is_pointer<detail::decay_t<ret>>::value; 3679 constexpr bool ptr_const_mismatch = 3680 is_pointer_ret && 3681 is_pointer_sigret && 3682 !std::is_const<detail::remove_pointer_t<sigret>>{} && 3683 std::is_const<detail::remove_pointer_t<detail::decay_t<ret>>>{}; 3684 constexpr bool is_ref_sigret = std::is_reference<sigret>::value; 3685 constexpr bool is_ref_ret = std::is_reference<ret>::value; 3686 constexpr bool ref_const_mismatch= 3687 is_ref_ret && 3688 is_ref_sigret && 3689 !std::is_const<detail::remove_reference_t<sigret>>::value && 3690 std::is_const<detail::remove_reference_t<ret>>::value; 3691 constexpr bool matching_ret_type = std::is_constructible<sigret, ret>::value; 3692 constexpr bool ref_value_mismatch = !is_ref_ret && is_ref_sigret; 3693 3694 static_assert(matching_ret_type || !void_signature, 3695 "RETURN does not make sense for void-function"); 3696 static_assert(!is_illegal_type, 3697 "RETURN illegal argument"); 3698 static_assert(!ptr_const_mismatch, 3699 "RETURN const* from function returning pointer to non-const"); 3700 static_assert(!ref_value_mismatch || matching_ret_type, 3701 "RETURN non-reference from function returning reference"); 3702 static_assert(ref_value_mismatch || !ref_const_mismatch, 3703 "RETURN const& from function returning non-const reference"); 3704 3705 static_assert(ptr_const_mismatch || ref_const_mismatch || is_illegal_type || matching_ret_type || void_signature, 3706 "RETURN value is not convertible to the return type of the function"); 3707 static_assert(is_first_return, 3708 "Multiple RETURN does not make sense"); 3709 static_assert(!throws || upper_call_limit == 0, 3710 "THROW and RETURN does not make sense"); 3711 static_assert(upper_call_limit > 0, 3712 "RETURN for forbidden call does not make sense"); 3713 3714 constexpr bool valid = !is_illegal_type && matching_ret_type && is_first_return && !throws && upper_call_limit > 0; 3715 using tag = std::integral_constant<bool, valid>; 3716 matcher->set_return(tag{}, std::forward<H>(h)); 3717 return {matcher}; 3718 } 3719 3720 call_modifier&& 3721 null_modifier() 3722 { 3723 return std::move(*this); 3724 } 3725 3726 private: 3727 template <typename H> 3728 struct throw_handler_t 3729 { 3730 using R = decltype(default_return<return_of_t<signature>>()); 3731 3732 throw_handler_t(H&& h_) 3733 : h(std::forward<H>(h_)) 3734 {} 3735 3736 template <typename T> 3737 R operator()(T& p) 3738 { 3739 /* Work around VS 2017 15.7.x C4702 warning by 3740 * enclosing the operation in an otherwise 3741 * unnecessary try/catch block. 3742 */ 3743 try 3744 { 3745 h(p); 3746 abort(); 3747 } 3748 catch (...) 3749 { 3750 throw; 3751 } 3752 return default_return<R>(); // unreachable code 3753 } 3754 3755 private: 3756 H h; 3757 }; 3758 3759 public: 3760 template <typename H> 3761 call_modifier<Matcher, modifier_tag, throw_injector<Parent>> 3762 handle_throw( 3763 H&& h) 3764 { 3765 static_assert(!throws, 3766 "Multiple THROW does not make sense"); 3767 constexpr bool has_return = !std::is_same<return_type, void>::value; 3768 static_assert(!has_return, 3769 "THROW and RETURN does not make sense"); 3770 3771 constexpr bool forbidden = upper_call_limit == 0U; 3772 3773 static_assert(!forbidden, 3774 "THROW for forbidden call does not make sense"); 3775 3776 constexpr bool valid = !throws && !has_return;// && !forbidden; 3777 using tag = std::integral_constant<bool, valid>; 3778 auto handler = throw_handler_t<H>(std::forward<H>(h)); 3779 matcher->set_return(tag{}, std::move(handler)); 3780 return {matcher}; 3781 } 3782 3783 template <size_t L, 3784 size_t H, 3785 bool times_set = call_limit_set> 3786 call_modifier<Matcher, modifier_tag, call_limit_injector<Parent, H>> 3787 times( 3788 multiplicity<L, H>) 3789 { 3790 static_assert(!times_set, 3791 "Only one TIMES call limit is allowed, but it can express an interval"); 3792 3793 static_assert(H >= L, 3794 "In TIMES the first value must not exceed the second"); 3795 3796 static_assert(H > 0 || !throws, 3797 "THROW and TIMES(0) does not make sense"); 3798 3799 static_assert(H > 0 || std::is_same<return_type, void>::value, 3800 "RETURN and TIMES(0) does not make sense"); 3801 3802 static_assert(H > 0 || !side_effects, 3803 "SIDE_EFFECT and TIMES(0) does not make sense"); 3804 3805 static_assert(H > 0 || !sequence_set, 3806 "IN_SEQUENCE and TIMES(0) does not make sense"); 3807 3808 matcher->sequences->set_limits(L, H); 3809 return {matcher}; 3810 } 3811 3812 template <typename ... T, 3813 bool b = sequence_set> 3814 call_modifier<Matcher, modifier_tag, sequence_injector<Parent>> 3815 in_sequence( 3816 T&& ... t) 3817 { 3818 static_assert(!b, 3819 "Multiple IN_SEQUENCE does not make sense." 3820 " You can list several sequence objects at once"); 3821 3822 static_assert(upper_call_limit > 0, 3823 "IN_SEQUENCE for forbidden call does not make sense"); 3824 3825 matcher->set_sequence(std::forward<T>(t)...); 3826 return {matcher}; 3827 } 3828 Matcher* matcher; 3829 }; 3830 3831 inline 3832 void 3833 report_unfulfilled( 3834 const char* reason, 3835 char const *name, 3836 std::string const &values, 3837 size_t min_calls, 3838 size_t call_count, 3839 location loc) 3840 { 3841 std::ostringstream os; 3842 os << reason 3843 << ":\nExpected " << name << " to be called "; 3844 if (min_calls == 1) 3845 os << "once"; 3846 else 3847 os << min_calls << " times"; 3848 os << ", actually "; 3849 switch (call_count) 3850 { 3851 case 0: 3852 os << "never called\n"; break; 3853 case 1: 3854 os << "called once\n"; break; 3855 default: 3856 os << "called " << call_count << " times\n"; 3857 } 3858 os << values; 3859 send_report<specialized>(severity::nonfatal, loc, os.str()); 3860 } 3861 3862 inline 3863 void 3864 report_forbidden_call( 3865 char const *name, 3866 location loc, 3867 std::string const& values) 3868 { 3869 std::ostringstream os; 3870 os << "Match of forbidden call of " << name 3871 << " at " << loc << '\n' << values; 3872 send_report<specialized>(severity::fatal, loc, os.str()); 3873 } 3874 3875 template <typename Sig> 3876 struct matcher_info 3877 { 3878 using signature = Sig; 3879 using return_type = void; 3880 static size_t const upper_call_limit = 1; 3881 static bool const throws = false; 3882 static bool const call_limit_set = false; 3883 static bool const sequence_set = false; 3884 static bool const side_effects = false; 3885 }; 3886 3887 3888 template <typename Sig, typename Value> 3889 struct call_matcher : public call_matcher_base<Sig>, expectation 3890 { 3891 using call_matcher_base<Sig>::name; 3892 using call_matcher_base<Sig>::loc; 3893 3894 template <typename ... U> 3895 call_matcher( 3896 char const *file, 3897 unsigned long line, 3898 char const *call_string, 3899 U &&... u) 3900 : call_matcher_base<Sig>(location{file, line}, call_string) 3901 , val(std::forward<U>(u)...) 3902 {} 3903 3904 call_matcher(call_matcher &&r) = delete; 3905 3906 ~call_matcher() override 3907 { 3908 auto lock = get_lock(); 3909 if (is_unfulfilled()) 3910 { 3911 report_missed("Unfulfilled expectation"); 3912 } 3913 this->unlink(); 3914 } 3915 3916 bool 3917 is_satisfied() 3918 const 3919 noexcept 3920 override 3921 { 3922 auto lock = get_lock(); 3923 return sequences->is_satisfied(); 3924 } 3925 3926 bool 3927 is_saturated() 3928 const 3929 noexcept 3930 override 3931 { 3932 auto lock = get_lock(); 3933 return sequences->is_saturated(); 3934 } 3935 bool 3936 is_unfulfilled() 3937 const 3938 noexcept 3939 { 3940 return !reported && this->is_linked() && !sequences->is_satisfied(); 3941 } 3942 3943 void 3944 mock_destroyed() 3945 override 3946 { 3947 if (is_unfulfilled()) 3948 { 3949 report_missed("Pending expectation on destroyed mock object"); 3950 } 3951 } 3952 3953 call_matcher* 3954 hook_last( 3955 call_matcher_list<Sig> &list) 3956 noexcept 3957 { 3958 list.push_front(this); 3959 return this; 3960 } 3961 3962 bool 3963 matches( 3964 call_params_type_t<Sig> const& params) 3965 const 3966 override 3967 { 3968 return match_parameters(val, params) && match_conditions(params); 3969 } 3970 3971 bool 3972 match_conditions( 3973 call_params_type_t<Sig> const & params) 3974 const 3975 { 3976 // std::all_of() is almost always preferable. The only reason 3977 // for using a hand rolled loop is because it cuts compilation 3978 // times quite noticeably (almost 10% with g++5.1) 3979 for (auto& c : conditions) 3980 { 3981 if (!c.check(params)) return false; 3982 } 3983 return true; 3984 } 3985 3986 unsigned 3987 sequence_cost() 3988 const 3989 noexcept 3990 override 3991 { 3992 return sequences->order(); 3993 } 3994 3995 return_of_t<Sig> 3996 return_value( 3997 trace_agent& agent, 3998 call_params_type_t<Sig>& params) 3999 override 4000 { 4001 if (!return_handler_obj) return default_return<return_of_t<Sig>>(); 4002 return return_handler_obj->call(agent, params); 4003 } 4004 4005 void 4006 run_actions( 4007 call_params_type_t<Sig>& params, 4008 call_matcher_list<Sig> &saturated_list) 4009 override 4010 { 4011 if (sequences->is_forbidden()) 4012 { 4013 reported = true; 4014 report_forbidden_call(name, loc, params_string(params)); 4015 } 4016 auto lock = get_lock(); 4017 { 4018 if (!sequences->can_be_called()) 4019 { 4020 sequences->validate(severity::fatal, name, loc); 4021 } 4022 sequences->increment_call(); 4023 if (sequences->is_satisfied()) 4024 { 4025 sequences->retire_predecessors(); 4026 } 4027 if (sequences->is_saturated()) 4028 { 4029 sequences->retire(); 4030 this->unlink(); 4031 saturated_list.push_back(this); 4032 } 4033 } 4034 for (auto& a : actions) a.action(params); 4035 } 4036 4037 std::ostream& 4038 report_signature( 4039 std::ostream& os) 4040 const override 4041 { 4042 return os << name << " at " << loc; 4043 } 4044 4045 std::ostream& 4046 report_mismatch( 4047 std::ostream& os, 4048 call_params_type_t<Sig> const & params) 4049 override 4050 { 4051 reported = true; 4052 report_signature(os); 4053 if (match_parameters(val, params)) 4054 { 4055 for (auto& cond : conditions) 4056 { 4057 if (!cond.check(params)) 4058 { 4059 os << "\n Failed WITH(" << cond.name() << ')'; 4060 } 4061 } 4062 } 4063 else 4064 { 4065 os << '\n'; 4066 ::trompeloeil::print_mismatch(os, val, params); 4067 } 4068 return os; 4069 } 4070 4071 void 4072 report_missed( 4073 char const *reason) 4074 noexcept 4075 { 4076 reported = true; 4077 report_unfulfilled( 4078 reason, 4079 name, 4080 params_string(val), 4081 sequences->get_min_calls(), 4082 sequences->get_calls(), 4083 loc); 4084 } 4085 4086 template <typename C> 4087 void 4088 add_condition( 4089 char const *str, 4090 C&& c) 4091 { 4092 auto cond = new condition<Sig, C>(str, std::forward<C>(c)); 4093 conditions.push_back(cond); 4094 } 4095 4096 template <typename S> 4097 void 4098 add_side_effect( 4099 S&& s) 4100 { 4101 auto effect = new side_effect<Sig, S>(std::forward<S>(s)); 4102 actions.push_back(effect); 4103 } 4104 4105 template <typename ... T> 4106 void 4107 set_sequence( 4108 T&& ... t) 4109 { 4110 using handler = sequence_handler<sizeof...(T)>; 4111 auto seq = detail::make_unique<handler>(*sequences, 4112 name, 4113 loc, 4114 std::forward<T>(t)...); 4115 sequences = std::move(seq); 4116 } 4117 4118 template <typename T> 4119 inline 4120 void 4121 set_return( 4122 std::true_type, 4123 T&& h) 4124 { 4125 using basic_t = typename std::remove_reference<T>::type; 4126 using handler = return_handler_t<Sig, basic_t>; 4127 return_handler_obj.reset(new handler(std::forward<T>(h))); 4128 } 4129 4130 template <typename T> 4131 inline // Never called. Used to limit errmsg 4132 static // with RETURN of wrong type and after: 4133 void // FORBIDDEN_CALL 4134 set_return(std::false_type, T&&t)// RETURN 4135 noexcept; // THROW 4136 4137 condition_list<Sig> conditions; 4138 side_effect_list<Sig> actions; 4139 std::unique_ptr<return_handler<Sig>> return_handler_obj; 4140 std::unique_ptr<sequence_handler_base> sequences = detail::make_unique<sequence_handler<0>>(); 4141 Value val; 4142 bool reported = false; 4143 }; 4144 4145 /* Clang (all versions) does not like computing the return type R 4146 * before determining if the function overload is the best match. 4147 */ 4148 template < 4149 int N, 4150 typename T, 4151 typename = detail::enable_if_t<N <= std::tuple_size<T>::value>, 4152 typename R = decltype(std::get<N-1>(std::declval<T>())) 4153 > 4154 constexpr 4155 TROMPELOEIL_DECLTYPE_AUTO 4156 arg( 4157 T* t, 4158 std::true_type) 4159 TROMPELOEIL_TRAILING_RETURN_TYPE(R) 4160 { 4161 return std::get<N-1>(*t); 4162 } 4163 4164 template <int N> 4165 inline 4166 constexpr 4167 illegal_argument const 4168 arg( 4169 void const*, 4170 std::false_type) 4171 noexcept 4172 { 4173 return {}; 4174 } 4175 4176 template < 4177 int N, 4178 typename T, 4179 typename R = decltype(arg<N>(std::declval<T*>(), 4180 std::integral_constant<bool, (N <= std::tuple_size<T>::value)>{})) 4181 > 4182 TROMPELOEIL_DECLTYPE_AUTO 4183 mkarg( 4184 T& t) 4185 noexcept 4186 TROMPELOEIL_TRAILING_RETURN_TYPE(R) 4187 { 4188 return arg<N>(&t, std::integral_constant<bool, (N <= std::tuple_size<T>::value)>{}); 4189 } 4190 4191 template <typename Mock> 4192 struct call_validator_t 4193 { 4194 template <typename M, typename Tag, typename Info> 4195 auto 4196 make_expectation( 4197 std::true_type, 4198 call_modifier<M, Tag, Info>&& m) 4199 const 4200 noexcept 4201 TROMPELOEIL_TRAILING_RETURN_TYPE(std::unique_ptr<expectation>) 4202 { 4203 auto lock = get_lock(); 4204 m.matcher->hook_last(obj.trompeloeil_matcher_list(static_cast<Tag*>(nullptr))); 4205 4206 return std::unique_ptr<expectation>(m.matcher); 4207 } 4208 4209 template <typename T> 4210 static // Never called. Used to 4211 std::unique_ptr<expectation> // limit errmsg when RETURN 4212 make_expectation(std::false_type, T&&) noexcept; // is missing in non-void 4213 // function 4214 4215 template <typename M, typename Tag, typename Info> 4216 inline 4217 auto 4218 operator+( 4219 call_modifier<M, Tag, Info>&& t) 4220 const 4221 TROMPELOEIL_TRAILING_RETURN_TYPE(std::unique_ptr<expectation>) 4222 { 4223 using call = call_modifier<M, Tag, Info>; 4224 using sigret = return_of_t<typename call::signature>; 4225 using ret = typename call::return_type; 4226 constexpr bool retmatch = std::is_same<ret, sigret>::value; 4227 constexpr bool forbidden = call::upper_call_limit == 0; 4228 constexpr bool valid_return_type = call::throws || retmatch || forbidden; 4229 static_assert(valid_return_type, "RETURN missing for non-void function"); 4230 auto tag = std::integral_constant<bool, valid_return_type>{}; 4231 return make_expectation(tag, std::move(t)); 4232 } 4233 Mock& obj; 4234 }; 4235 4236 template <typename T, 4237 typename = detail::enable_if_t<std::is_lvalue_reference<T&&>::value>> 4238 inline 4239 T&& 4240 decay_return_type( 4241 T&& t) 4242 { 4243 return std::forward<T>(t); 4244 } 4245 4246 template <typename T, 4247 typename = detail::enable_if_t<std::is_rvalue_reference<T&&>::value>> 4248 inline 4249 T 4250 decay_return_type( 4251 T&& t) 4252 { 4253 return std::forward<T>(t); 4254 } 4255 4256 template <typename T, size_t N> 4257 inline 4258 T* 4259 decay_return_type( 4260 T (&t)[N]) 4261 { 4262 return t; 4263 } 4264 4265 template <bool sequence_set> 4266 struct lifetime_monitor_modifier 4267 { 4268 operator std::unique_ptr<lifetime_monitor>() { return std::move(monitor);} 4269 template <typename ... T, bool b = sequence_set> 4270 lifetime_monitor_modifier<true> 4271 in_sequence(T&& ... t) 4272 { 4273 static_assert(!b, 4274 "Multiple IN_SEQUENCE does not make sense." 4275 " You can list several sequence objects at once"); 4276 monitor->set_sequence(std::forward<T>(t)...); 4277 return { std::move(monitor) }; 4278 } 4279 std::unique_ptr<lifetime_monitor> monitor; 4280 }; 4281 4282 struct lifetime_monitor_releaser 4283 { 4284 template <bool b> 4285 std::unique_ptr<trompeloeil::lifetime_monitor> 4286 operator+( 4287 lifetime_monitor_modifier<b>&& m) 4288 const 4289 { 4290 return m; 4291 } 4292 }; 4293 4294 template <bool movable, typename Sig> 4295 struct expectations 4296 { 4297 expectations() = default; 4298 expectations(expectations&&) = default; 4299 ~expectations() { 4300 active.decommission(); 4301 saturated.decommission(); 4302 } 4303 call_matcher_list<Sig> active{}; 4304 call_matcher_list<Sig> saturated{}; 4305 }; 4306 4307 template <typename Sig> 4308 struct expectations<false, Sig> 4309 { 4310 expectations() = default; 4311 expectations(expectations&&) 4312 { 4313 static_assert(std::is_same<Sig,void>::value, 4314 "By default, mock objects are not movable. " 4315 "To make a mock object movable, see: " 4316 "https://github.com/rollbear/trompeloeil/blob/master/docs/reference.md#movable_mock"); 4317 } 4318 ~expectations() { 4319 active.decommission(); 4320 saturated.decommission(); 4321 } 4322 call_matcher_list<Sig> active{}; 4323 call_matcher_list<Sig> saturated{}; 4324 }; 4325 4326 template <typename Sig, typename ... P> 4327 return_of_t<Sig> mock_func(std::false_type, P&& ...); 4328 4329 4330 template <bool movable, typename Sig, typename ... P> 4331 return_of_t<Sig> 4332 mock_func(std::true_type, 4333 expectations<movable, Sig>& e, 4334 char const *func_name, 4335 char const *sig_name, 4336 P&& ... p) 4337 { 4338 auto lock = get_lock(); 4339 4340 call_params_type_t<void(P...)> param_value(std::forward<P>(p)...); 4341 4342 auto i = find(e.active, param_value); 4343 if (!i) 4344 { 4345 report_mismatch(e.active, 4346 e.saturated, 4347 func_name + std::string(" with signature ") + sig_name, 4348 param_value); 4349 } 4350 else{ 4351 report_match(e.active); 4352 } 4353 trace_agent ta{i->loc, i->name, tracer_obj()}; 4354 try 4355 { 4356 ta.trace_params(param_value); 4357 i->run_actions(param_value, e.saturated); 4358 return i->return_value(ta, param_value); 4359 } 4360 catch (...) 4361 { 4362 ta.trace_exception(); 4363 throw; 4364 } 4365 } 4366 4367 template <typename ... U> 4368 struct param_helper { 4369 using type = decltype(detail::make_tuple(std::declval<U>()...)); 4370 }; 4371 4372 template <typename ... U> 4373 using param_t = typename param_helper<U...>::type; 4374 4375 template <typename sig, typename tag, typename... U> 4376 using modifier_t = call_modifier<call_matcher<sig, param_t<U...>>, 4377 tag, 4378 matcher_info<sig>>; 4379 4380 template <typename M, 4381 typename = detail::enable_if_t<::trompeloeil::is_matcher<M>::value>> 4382 inline 4383 ::trompeloeil::ptr_deref<detail::decay_t<M>> 4384 operator*( 4385 M&& m) 4386 { 4387 return ::trompeloeil::ptr_deref<detail::decay_t<M>>{std::forward<M>(m)}; 4388 } 4389 4390 template <typename M, 4391 typename = detail::enable_if_t<::trompeloeil::is_matcher<M>::value>> 4392 inline 4393 ::trompeloeil::neg_matcher<detail::decay_t<M>> 4394 operator!( 4395 M&& m) 4396 { 4397 return ::trompeloeil::neg_matcher<detail::decay_t<M>>{std::forward<M>(m)}; 4398 } 4399 4400 /* 4401 * Convert the signature S of a mock function to the signature of 4402 * a member function of class T that takes the same parameters P 4403 * but returns R. 4404 * 4405 * The member function has the same constness as the mock function. 4406 */ 4407 template <typename T, typename R, typename S> 4408 struct signature_to_member_function; 4409 4410 template <typename T, typename R, typename R_of_S, typename... P> 4411 struct signature_to_member_function<T, R, R_of_S(P...)> 4412 { 4413 using type = detail::conditional_t< 4414 std::is_const<T>::value, 4415 R (T::*)(P...) const, 4416 R (T::*)(P...)>; 4417 }; 4418 4419 template <typename T> 4420 struct mock_interface : public T 4421 { 4422 using trompeloeil_interface_name = T; 4423 using T::T; 4424 }; 4425 4426 #if defined(TROMPELOEIL_USER_DEFINED_COMPILE_TIME_REPORTER) 4427 extern template struct reporter<specialized>; 4428 #endif // TROMPELOEIL_USER_DEFINED_COMPILE_TIME_REPORTER 4429 } 4430 4431 #define TROMPELOEIL_LINE_ID(name) \ 4432 TROMPELOEIL_CONCAT(trompeloeil_l_ ## name ## _, __LINE__) 4433 4434 #define TROMPELOEIL_COUNT_ID(name) \ 4435 TROMPELOEIL_CONCAT(trompeloeil_c_ ## name ## _, __COUNTER__) 4436 4437 #ifdef _MSC_VER 4438 #define TROMPELOEIL_MAKE_MOCK0(name, sig, ...) \ 4439 TROMPELOEIL_MAKE_MOCK_(name,,0, sig, __VA_ARGS__,,) 4440 #define TROMPELOEIL_MAKE_MOCK1(name, sig, ...) \ 4441 TROMPELOEIL_MAKE_MOCK_(name,,1, sig, __VA_ARGS__,,) 4442 #define TROMPELOEIL_MAKE_MOCK2(name, sig, ...) \ 4443 TROMPELOEIL_MAKE_MOCK_(name,,2, sig, __VA_ARGS__,,) 4444 #define TROMPELOEIL_MAKE_MOCK3(name, sig, ...) \ 4445 TROMPELOEIL_MAKE_MOCK_(name,,3, sig, __VA_ARGS__,,) 4446 #define TROMPELOEIL_MAKE_MOCK4(name, sig, ...) \ 4447 TROMPELOEIL_MAKE_MOCK_(name,,4, sig, __VA_ARGS__,,) 4448 #define TROMPELOEIL_MAKE_MOCK5(name, sig, ...) \ 4449 TROMPELOEIL_MAKE_MOCK_(name,,5, sig, __VA_ARGS__,,) 4450 #define TROMPELOEIL_MAKE_MOCK6(name, sig, ...) \ 4451 TROMPELOEIL_MAKE_MOCK_(name,,6, sig, __VA_ARGS__,,) 4452 #define TROMPELOEIL_MAKE_MOCK7(name, sig, ...) \ 4453 TROMPELOEIL_MAKE_MOCK_(name,,7, sig, __VA_ARGS__,,) 4454 #define TROMPELOEIL_MAKE_MOCK8(name, sig, ...) \ 4455 TROMPELOEIL_MAKE_MOCK_(name,,8, sig, __VA_ARGS__,,) 4456 #define TROMPELOEIL_MAKE_MOCK9(name, sig, ...) \ 4457 TROMPELOEIL_MAKE_MOCK_(name,,9, sig, __VA_ARGS__,,) 4458 #define TROMPELOEIL_MAKE_MOCK10(name, sig, ...) \ 4459 TROMPELOEIL_MAKE_MOCK_(name,,10, sig, __VA_ARGS__,,) 4460 #define TROMPELOEIL_MAKE_MOCK11(name, sig, ...) \ 4461 TROMPELOEIL_MAKE_MOCK_(name,,11, sig, __VA_ARGS__,,) 4462 #define TROMPELOEIL_MAKE_MOCK12(name, sig, ...) \ 4463 TROMPELOEIL_MAKE_MOCK_(name,,12, sig, __VA_ARGS__,,) 4464 #define TROMPELOEIL_MAKE_MOCK13(name, sig, ...) \ 4465 TROMPELOEIL_MAKE_MOCK_(name,,13, sig, __VA_ARGS__,,) 4466 #define TROMPELOEIL_MAKE_MOCK14(name, sig, ...) \ 4467 TROMPELOEIL_MAKE_MOCK_(name,,14, sig, __VA_ARGS__,,) 4468 #define TROMPELOEIL_MAKE_MOCK15(name, sig, ...) \ 4469 TROMPELOEIL_MAKE_MOCK_(name,,15, sig, __VA_ARGS__,,) 4470 4471 #define TROMPELOEIL_MAKE_CONST_MOCK0(name, sig, ...) \ 4472 TROMPELOEIL_MAKE_MOCK_(name,const,0, sig, __VA_ARGS__,,) 4473 #define TROMPELOEIL_MAKE_CONST_MOCK1(name, sig, ...) \ 4474 TROMPELOEIL_MAKE_MOCK_(name,const,1, sig, __VA_ARGS__,,) 4475 #define TROMPELOEIL_MAKE_CONST_MOCK2(name, sig, ...) \ 4476 TROMPELOEIL_MAKE_MOCK_(name,const,2, sig, __VA_ARGS__,,) 4477 #define TROMPELOEIL_MAKE_CONST_MOCK3(name, sig, ...) \ 4478 TROMPELOEIL_MAKE_MOCK_(name,const,3, sig, __VA_ARGS__,,) 4479 #define TROMPELOEIL_MAKE_CONST_MOCK4(name, sig, ...) \ 4480 TROMPELOEIL_MAKE_MOCK_(name,const,4, sig, __VA_ARGS__,,) 4481 #define TROMPELOEIL_MAKE_CONST_MOCK5(name, sig, ...) \ 4482 TROMPELOEIL_MAKE_MOCK_(name,const,5, sig, __VA_ARGS__,,) 4483 #define TROMPELOEIL_MAKE_CONST_MOCK6(name, sig, ...) \ 4484 TROMPELOEIL_MAKE_MOCK_(name,const,6, sig, __VA_ARGS__,,) 4485 #define TROMPELOEIL_MAKE_CONST_MOCK7(name, sig, ...) \ 4486 TROMPELOEIL_MAKE_MOCK_(name,const,7, sig, __VA_ARGS__,,) 4487 #define TROMPELOEIL_MAKE_CONST_MOCK8(name, sig, ...) \ 4488 TROMPELOEIL_MAKE_MOCK_(name,const,8, sig, __VA_ARGS__,,) 4489 #define TROMPELOEIL_MAKE_CONST_MOCK9(name, sig, ...) \ 4490 TROMPELOEIL_MAKE_MOCK_(name,const,9, sig, __VA_ARGS__,,) 4491 #define TROMPELOEIL_MAKE_CONST_MOCK10(name, sig, ...) \ 4492 TROMPELOEIL_MAKE_MOCK_(name,const,10, sig, __VA_ARGS__,,) 4493 #define TROMPELOEIL_MAKE_CONST_MOCK11(name, sig, ...) \ 4494 TROMPELOEIL_MAKE_MOCK_(name,const,11, sig, __VA_ARGS__,,) 4495 #define TROMPELOEIL_MAKE_CONST_MOCK12(name, sig, ...) \ 4496 TROMPELOEIL_MAKE_MOCK_(name,const,12, sig, __VA_ARGS__,,) 4497 #define TROMPELOEIL_MAKE_CONST_MOCK13(name, sig, ...) \ 4498 TROMPELOEIL_MAKE_MOCK_(name,const,13, sig, __VA_ARGS__,,) 4499 #define TROMPELOEIL_MAKE_CONST_MOCK14(name, sig, ...) \ 4500 TROMPELOEIL_MAKE_MOCK_(name,const,14, sig, __VA_ARGS__,,) 4501 #define TROMPELOEIL_MAKE_CONST_MOCK15(name, sig, ...) \ 4502 TROMPELOEIL_MAKE_MOCK_(name,const,15, sig, __VA_ARGS__,,) 4503 4504 4505 #else 4506 // sane standards compliant preprocessor 4507 4508 #define TROMPELOEIL_MAKE_MOCK0(name, ...) \ 4509 TROMPELOEIL_MAKE_MOCK_(name,,0, __VA_ARGS__,,) 4510 #define TROMPELOEIL_MAKE_MOCK1(name, ...) \ 4511 TROMPELOEIL_MAKE_MOCK_(name,,1, __VA_ARGS__,,) 4512 #define TROMPELOEIL_MAKE_MOCK2(name, ...) \ 4513 TROMPELOEIL_MAKE_MOCK_(name,,2, __VA_ARGS__,,) 4514 #define TROMPELOEIL_MAKE_MOCK3(name, ...) \ 4515 TROMPELOEIL_MAKE_MOCK_(name,,3, __VA_ARGS__,,) 4516 #define TROMPELOEIL_MAKE_MOCK4(name, ...) \ 4517 TROMPELOEIL_MAKE_MOCK_(name,,4, __VA_ARGS__,,) 4518 #define TROMPELOEIL_MAKE_MOCK5(name, ...) \ 4519 TROMPELOEIL_MAKE_MOCK_(name,,5, __VA_ARGS__,,) 4520 #define TROMPELOEIL_MAKE_MOCK6(name, ...) \ 4521 TROMPELOEIL_MAKE_MOCK_(name,,6, __VA_ARGS__,,) 4522 #define TROMPELOEIL_MAKE_MOCK7(name, ...) \ 4523 TROMPELOEIL_MAKE_MOCK_(name,,7, __VA_ARGS__,,) 4524 #define TROMPELOEIL_MAKE_MOCK8(name, ...) \ 4525 TROMPELOEIL_MAKE_MOCK_(name,,8, __VA_ARGS__,,) 4526 #define TROMPELOEIL_MAKE_MOCK9(name, ...) \ 4527 TROMPELOEIL_MAKE_MOCK_(name,,9, __VA_ARGS__,,) 4528 #define TROMPELOEIL_MAKE_MOCK10(name, ...) \ 4529 TROMPELOEIL_MAKE_MOCK_(name,,10, __VA_ARGS__,,) 4530 #define TROMPELOEIL_MAKE_MOCK11(name, ...) \ 4531 TROMPELOEIL_MAKE_MOCK_(name,,11, __VA_ARGS__,,) 4532 #define TROMPELOEIL_MAKE_MOCK12(name, ...) \ 4533 TROMPELOEIL_MAKE_MOCK_(name,,12, __VA_ARGS__,,) 4534 #define TROMPELOEIL_MAKE_MOCK13(name, ...) \ 4535 TROMPELOEIL_MAKE_MOCK_(name,,13, __VA_ARGS__,,) 4536 #define TROMPELOEIL_MAKE_MOCK14(name, ...) \ 4537 TROMPELOEIL_MAKE_MOCK_(name,,14,__VA_ARGS__,,) 4538 #define TROMPELOEIL_MAKE_MOCK15(name, ...) \ 4539 TROMPELOEIL_MAKE_MOCK_(name,,15, __VA_ARGS__,,) 4540 4541 #define TROMPELOEIL_MAKE_CONST_MOCK0(name, ...) \ 4542 TROMPELOEIL_MAKE_MOCK_(name,const,0, __VA_ARGS__,,) 4543 #define TROMPELOEIL_MAKE_CONST_MOCK1(name, ...) \ 4544 TROMPELOEIL_MAKE_MOCK_(name,const,1, __VA_ARGS__,,) 4545 #define TROMPELOEIL_MAKE_CONST_MOCK2(name, ...) \ 4546 TROMPELOEIL_MAKE_MOCK_(name,const,2, __VA_ARGS__,,) 4547 #define TROMPELOEIL_MAKE_CONST_MOCK3(name, ...) \ 4548 TROMPELOEIL_MAKE_MOCK_(name,const,3, __VA_ARGS__,,) 4549 #define TROMPELOEIL_MAKE_CONST_MOCK4(name, ...) \ 4550 TROMPELOEIL_MAKE_MOCK_(name,const,4, __VA_ARGS__,,) 4551 #define TROMPELOEIL_MAKE_CONST_MOCK5(name, ...) \ 4552 TROMPELOEIL_MAKE_MOCK_(name,const,5, __VA_ARGS__,,) 4553 #define TROMPELOEIL_MAKE_CONST_MOCK6(name, ...) \ 4554 TROMPELOEIL_MAKE_MOCK_(name,const,6, __VA_ARGS__,,) 4555 #define TROMPELOEIL_MAKE_CONST_MOCK7(name, ...) \ 4556 TROMPELOEIL_MAKE_MOCK_(name,const,7, __VA_ARGS__,,) 4557 #define TROMPELOEIL_MAKE_CONST_MOCK8(name, ...) \ 4558 TROMPELOEIL_MAKE_MOCK_(name,const,8, __VA_ARGS__,,) 4559 #define TROMPELOEIL_MAKE_CONST_MOCK9(name, ...) \ 4560 TROMPELOEIL_MAKE_MOCK_(name,const,9, __VA_ARGS__,,) 4561 #define TROMPELOEIL_MAKE_CONST_MOCK10(name, ...) \ 4562 TROMPELOEIL_MAKE_MOCK_(name,const,10, __VA_ARGS__,,) 4563 #define TROMPELOEIL_MAKE_CONST_MOCK11(name, ...) \ 4564 TROMPELOEIL_MAKE_MOCK_(name,const,11, __VA_ARGS__,,) 4565 #define TROMPELOEIL_MAKE_CONST_MOCK12(name, ...) \ 4566 TROMPELOEIL_MAKE_MOCK_(name,const,12, __VA_ARGS__,,) 4567 #define TROMPELOEIL_MAKE_CONST_MOCK13(name, ...) \ 4568 TROMPELOEIL_MAKE_MOCK_(name,const,13, __VA_ARGS__,,) 4569 #define TROMPELOEIL_MAKE_CONST_MOCK14(name, ...) \ 4570 TROMPELOEIL_MAKE_MOCK_(name,const,14, __VA_ARGS__,,) 4571 #define TROMPELOEIL_MAKE_CONST_MOCK15(name, ...) \ 4572 TROMPELOEIL_MAKE_MOCK_(name,const,15, __VA_ARGS__,,) 4573 4574 #endif 4575 4576 #define TROMPELOEIL_IMPLEMENT_MOCK0(...) \ 4577 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_MOCK_(0, __VA_ARGS__,override)) 4578 #define TROMPELOEIL_IMPLEMENT_MOCK1(...) \ 4579 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_MOCK_(1, __VA_ARGS__,override)) 4580 #define TROMPELOEIL_IMPLEMENT_MOCK2(...) \ 4581 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_MOCK_(2, __VA_ARGS__,override)) 4582 #define TROMPELOEIL_IMPLEMENT_MOCK3(...) \ 4583 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_MOCK_(3, __VA_ARGS__,override)) 4584 #define TROMPELOEIL_IMPLEMENT_MOCK4(...) \ 4585 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_MOCK_(4, __VA_ARGS__,override)) 4586 #define TROMPELOEIL_IMPLEMENT_MOCK5(...) \ 4587 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_MOCK_(5, __VA_ARGS__,override)) 4588 #define TROMPELOEIL_IMPLEMENT_MOCK6(...) \ 4589 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_MOCK_(6, __VA_ARGS__,override)) 4590 #define TROMPELOEIL_IMPLEMENT_MOCK7(...) \ 4591 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_MOCK_(7, __VA_ARGS__,override)) 4592 #define TROMPELOEIL_IMPLEMENT_MOCK8(...) \ 4593 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_MOCK_(8, __VA_ARGS__,override)) 4594 #define TROMPELOEIL_IMPLEMENT_MOCK9(...) \ 4595 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_MOCK_(9, __VA_ARGS__,override)) 4596 #define TROMPELOEIL_IMPLEMENT_MOCK10(...) \ 4597 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_MOCK_(10, __VA_ARGS__,override)) 4598 #define TROMPELOEIL_IMPLEMENT_MOCK11(...) \ 4599 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_MOCK_(11, __VA_ARGS__,override)) 4600 #define TROMPELOEIL_IMPLEMENT_MOCK12(...) \ 4601 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_MOCK_(12, __VA_ARGS__,override)) 4602 #define TROMPELOEIL_IMPLEMENT_MOCK13(...) \ 4603 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_MOCK_(13, __VA_ARGS__,override)) 4604 #define TROMPELOEIL_IMPLEMENT_MOCK14(...) \ 4605 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_MOCK_(14, __VA_ARGS__,override)) 4606 #define TROMPELOEIL_IMPLEMENT_MOCK15(...) \ 4607 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_MOCK_(15, __VA_ARGS__,override)) 4608 4609 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK0(...) \ 4610 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_CONST_MOCK_(0, __VA_ARGS__,override)) 4611 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK1(...) \ 4612 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_CONST_MOCK_(1, __VA_ARGS__,override)) 4613 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK2(...) \ 4614 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_CONST_MOCK_(2, __VA_ARGS__,override)) 4615 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK3(...) \ 4616 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_CONST_MOCK_(3, __VA_ARGS__,override)) 4617 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK4(...) \ 4618 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_CONST_MOCK_(4, __VA_ARGS__,override)) 4619 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK5(...) \ 4620 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_CONST_MOCK_(5, __VA_ARGS__,override)) 4621 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK6(...) \ 4622 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_CONST_MOCK_(6, __VA_ARGS__,override)) 4623 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK7(...) \ 4624 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_CONST_MOCK_(7, __VA_ARGS__,override)) 4625 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK8(...) \ 4626 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_CONST_MOCK_(8, __VA_ARGS__,override)) 4627 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK9(...) \ 4628 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_CONST_MOCK_(9, __VA_ARGS__,override)) 4629 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK10(...) \ 4630 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_CONST_MOCK_(10, __VA_ARGS__,override)) 4631 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK11(...) \ 4632 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_CONST_MOCK_(11, __VA_ARGS__,override)) 4633 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK12(...) \ 4634 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_CONST_MOCK_(12, __VA_ARGS__,override)) 4635 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK13(...) \ 4636 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_CONST_MOCK_(13, __VA_ARGS__,override)) 4637 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK14(...) \ 4638 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_CONST_MOCK_(14, __VA_ARGS__,override)) 4639 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK15(...) \ 4640 TROMPELOEIL_IDENTITY(TROMPELOEIL_IMPLEMENT_CONST_MOCK_(15, __VA_ARGS__,override)) 4641 4642 4643 #define TROMPELOEIL_IMPLEMENT_MOCK_(num, name, ...) \ 4644 TROMPELOEIL_MAKE_MOCK_(name,\ 4645 ,\ 4646 num,\ 4647 decltype(::trompeloeil::nonconst_member_signature(&trompeloeil_interface_name::name))::type,\ 4648 TROMPELOEIL_SEPARATE(__VA_ARGS__),) 4649 #define TROMPELOEIL_IMPLEMENT_CONST_MOCK_(num, name, ...) \ 4650 TROMPELOEIL_MAKE_MOCK_(name,\ 4651 const,\ 4652 num,\ 4653 decltype(::trompeloeil::const_member_signature(&trompeloeil_interface_name::name))::type,\ 4654 TROMPELOEIL_SEPARATE(__VA_ARGS__),) 4655 4656 #define TROMPELOEIL_MAKE_MOCK_(name, constness, num, sig, spec, ...) \ 4657 private: \ 4658 using TROMPELOEIL_LINE_ID(cardinality_match) = \ 4659 std::integral_constant<bool, num == \ 4660 ::trompeloeil::param_list<TROMPELOEIL_REMOVE_PAREN(sig)>::size>; \ 4661 static_assert(TROMPELOEIL_LINE_ID(cardinality_match)::value, \ 4662 "Function signature does not have " #num " parameters"); \ 4663 using TROMPELOEIL_LINE_ID(matcher_list_t) = \ 4664 ::trompeloeil::call_matcher_list<TROMPELOEIL_REMOVE_PAREN(sig)>; \ 4665 using TROMPELOEIL_LINE_ID(expectation_list_t) = \ 4666 ::trompeloeil::expectations<trompeloeil_movable_mock, \ 4667 TROMPELOEIL_REMOVE_PAREN(sig)>; \ 4668 \ 4669 struct TROMPELOEIL_LINE_ID(tag_type_trompeloeil) \ 4670 { \ 4671 const char* trompeloeil_expectation_file; \ 4672 unsigned long trompeloeil_expectation_line; \ 4673 const char *trompeloeil_expectation_string; \ 4674 \ 4675 /* Work around parsing bug in VS 2015 when a "complex" */ \ 4676 /* decltype() appears in a trailing return type. */ \ 4677 /* Further, work around C2066 defect in VS 2017 15.7.1. */ \ 4678 using trompeloeil_sig_t = typename \ 4679 ::trompeloeil::identity_type<TROMPELOEIL_REMOVE_PAREN(sig)>::type; \ 4680 \ 4681 using trompeloeil_call_params_type_t = \ 4682 ::trompeloeil::call_params_type_t<TROMPELOEIL_REMOVE_PAREN(sig)>; \ 4683 \ 4684 using trompeloeil_return_of_t = \ 4685 ::trompeloeil::return_of_t<TROMPELOEIL_REMOVE_PAREN(sig)>; \ 4686 \ 4687 template <typename ... trompeloeil_param_type> \ 4688 auto name( \ 4689 trompeloeil_param_type&& ... trompeloeil_param) \ 4690 -> ::trompeloeil::modifier_t<trompeloeil_sig_t, \ 4691 TROMPELOEIL_LINE_ID(tag_type_trompeloeil), \ 4692 trompeloeil_param_type...> \ 4693 { \ 4694 using matcher = ::trompeloeil::call_matcher< \ 4695 TROMPELOEIL_REMOVE_PAREN(sig), \ 4696 ::trompeloeil::param_t<trompeloeil_param_type...>>; \ 4697 return { \ 4698 new matcher { \ 4699 trompeloeil_expectation_file, \ 4700 trompeloeil_expectation_line, \ 4701 trompeloeil_expectation_string, \ 4702 std::forward<trompeloeil_param_type>(trompeloeil_param)... \ 4703 } \ 4704 }; \ 4705 } \ 4706 }; \ 4707 \ 4708 public: \ 4709 TROMPELOEIL_LINE_ID(matcher_list_t)& \ 4710 trompeloeil_matcher_list( \ 4711 TROMPELOEIL_LINE_ID(tag_type_trompeloeil)*) \ 4712 constness \ 4713 noexcept \ 4714 { \ 4715 return TROMPELOEIL_LINE_ID(expectations).active; \ 4716 } \ 4717 \ 4718 ::trompeloeil::return_of_t<TROMPELOEIL_REMOVE_PAREN(sig)> \ 4719 name(TROMPELOEIL_PARAM_LIST(num, sig)) \ 4720 constness \ 4721 spec \ 4722 { \ 4723 return ::trompeloeil::mock_func<trompeloeil_movable_mock, TROMPELOEIL_REMOVE_PAREN(sig)>( \ 4724 TROMPELOEIL_LINE_ID(cardinality_match){}, \ 4725 TROMPELOEIL_LINE_ID(expectations), \ 4726 #name, \ 4727 #sig \ 4728 TROMPELOEIL_PARAMS(num)); \ 4729 } \ 4730 \ 4731 TROMPELOEIL_NOT_IMPLEMENTED( \ 4732 auto \ 4733 trompeloeil_self_ ## name(TROMPELOEIL_PARAM_LIST(num, sig)) constness \ 4734 -> decltype(*this)); \ 4735 \ 4736 TROMPELOEIL_NOT_IMPLEMENTED(TROMPELOEIL_LINE_ID(tag_type_trompeloeil) \ 4737 trompeloeil_tag_ ## name(TROMPELOEIL_PARAM_LIST(num, sig)) constness); \ 4738 \ 4739 private: \ 4740 mutable \ 4741 TROMPELOEIL_LINE_ID(expectation_list_t) TROMPELOEIL_LINE_ID(expectations){}; \ 4742 \ 4743 public: \ 4744 /* An unused alias declaration to make trailing semicolon acceptable. */ \ 4745 using TROMPELOEIL_LINE_ID(unused_alias) = void 4746 4747 4748 #define TROMPELOEIL_LPAREN ( 4749 4750 #define TROMPELOEIL_MORE_THAN_TWO_ARGS(...) \ 4751 TROMPELOEIL_IDENTITY( \ 4752 TROMPELOEIL_ARG16(__VA_ARGS__, \ 4753 T, T, T, T, T, T, T, T, T, T, T, T, T, F, F, F)) 4754 4755 4756 #define TROMPELOEIL_REQUIRE_CALL_V(...) \ 4757 TROMPELOEIL_IDENTITY(TROMPELOEIL_REQUIRE_CALL_IMPL TROMPELOEIL_LPAREN \ 4758 TROMPELOEIL_MORE_THAN_TWO_ARGS(__VA_ARGS__), __VA_ARGS__)) 4759 4760 // Dispatch to _F (0, 1, or 2 arguments) or _T (> 2 arguments) macro 4761 #define TROMPELOEIL_REQUIRE_CALL_IMPL(N, ...) \ 4762 TROMPELOEIL_IDENTITY( \ 4763 TROMPELOEIL_REQUIRE_CALL_ ## N TROMPELOEIL_LPAREN __VA_ARGS__)) 4764 4765 // Accept only two arguments 4766 #define TROMPELOEIL_REQUIRE_CALL_F(obj, func) \ 4767 auto TROMPELOEIL_COUNT_ID(call_obj) = \ 4768 TROMPELOEIL_REQUIRE_CALL_V_LAMBDA(obj, func, #obj, #func, .null_modifier()) 4769 4770 // Accept three or more arguments. 4771 #define TROMPELOEIL_REQUIRE_CALL_T(obj, func, ...) \ 4772 auto TROMPELOEIL_COUNT_ID(call_obj) = \ 4773 TROMPELOEIL_REQUIRE_CALL_V_LAMBDA(obj, func, #obj, #func, __VA_ARGS__) 4774 4775 4776 #define TROMPELOEIL_REQUIRE_CALL_V_LAMBDA(obj, func, obj_s, func_s, ...) \ 4777 [&] \ 4778 { \ 4779 using trompeloeil_s_t = decltype((obj) \ 4780 .TROMPELOEIL_CONCAT(trompeloeil_self_, func)); \ 4781 using trompeloeil_e_t = decltype((obj) \ 4782 .TROMPELOEIL_CONCAT(trompeloeil_tag_,func)); \ 4783 \ 4784 return TROMPELOEIL_REQUIRE_CALL_LAMBDA_OBJ(obj, func, obj_s, func_s) \ 4785 __VA_ARGS__ \ 4786 ; \ 4787 }() 4788 4789 4790 #define TROMPELOEIL_REQUIRE_CALL_LAMBDA_OBJ(obj, func, obj_s, func_s) \ 4791 ::trompeloeil::call_validator_t<trompeloeil_s_t>{(obj)} + \ 4792 ::trompeloeil::detail::conditional_t<false, \ 4793 decltype((obj).func), \ 4794 trompeloeil_e_t> \ 4795 {__FILE__, static_cast<unsigned long>(__LINE__), obj_s "." func_s}.func 4796 4797 4798 #define TROMPELOEIL_NAMED_REQUIRE_CALL_V(...) \ 4799 TROMPELOEIL_IDENTITY(TROMPELOEIL_NAMED_REQUIRE_CALL_IMPL TROMPELOEIL_LPAREN \ 4800 TROMPELOEIL_MORE_THAN_TWO_ARGS(__VA_ARGS__), __VA_ARGS__)) 4801 4802 // Dispatch to _F (0, 1, or 2 arguments) or _T (> 2 arguments) macro 4803 #define TROMPELOEIL_NAMED_REQUIRE_CALL_IMPL(N, ...) \ 4804 TROMPELOEIL_IDENTITY( \ 4805 TROMPELOEIL_NAMED_REQUIRE_CALL_ ## N TROMPELOEIL_LPAREN __VA_ARGS__)) 4806 4807 // Accept only two arguments 4808 #define TROMPELOEIL_NAMED_REQUIRE_CALL_F(obj, func) \ 4809 TROMPELOEIL_REQUIRE_CALL_V_LAMBDA(obj, func, #obj, #func, .null_modifier()) 4810 4811 // Accept three or more arguments. 4812 #define TROMPELOEIL_NAMED_REQUIRE_CALL_T(obj, func, ...) \ 4813 TROMPELOEIL_REQUIRE_CALL_V_LAMBDA(obj, func, #obj, #func, __VA_ARGS__) 4814 4815 4816 #define TROMPELOEIL_ALLOW_CALL_V(...) \ 4817 TROMPELOEIL_IDENTITY(TROMPELOEIL_ALLOW_CALL_IMPL TROMPELOEIL_LPAREN \ 4818 TROMPELOEIL_MORE_THAN_TWO_ARGS(__VA_ARGS__), __VA_ARGS__)) 4819 4820 // Dispatch to _F (0, 1, or 2 arguments) or _T (> 2 arguments) macro 4821 #define TROMPELOEIL_ALLOW_CALL_IMPL(N, ...) \ 4822 TROMPELOEIL_IDENTITY( \ 4823 TROMPELOEIL_ALLOW_CALL_ ## N TROMPELOEIL_LPAREN __VA_ARGS__)) 4824 4825 // Accept only two arguments 4826 #define TROMPELOEIL_ALLOW_CALL_F(obj, func) \ 4827 TROMPELOEIL_REQUIRE_CALL_T(obj, func, .TROMPELOEIL_INFINITY_TIMES()) 4828 4829 // Accept three or more arguments. 4830 #define TROMPELOEIL_ALLOW_CALL_T(obj, func, ...) \ 4831 TROMPELOEIL_REQUIRE_CALL_T(obj, \ 4832 func, \ 4833 .TROMPELOEIL_INFINITY_TIMES() __VA_ARGS__) 4834 4835 4836 #define TROMPELOEIL_NAMED_ALLOW_CALL_V(...) \ 4837 TROMPELOEIL_IDENTITY(TROMPELOEIL_NAMED_ALLOW_CALL_IMPL TROMPELOEIL_LPAREN \ 4838 TROMPELOEIL_MORE_THAN_TWO_ARGS(__VA_ARGS__), __VA_ARGS__)) 4839 4840 // Dispatch to _F (0, 1, or 2 arguments) or _T (> 2 arguments) macro 4841 #define TROMPELOEIL_NAMED_ALLOW_CALL_IMPL(N, ...) \ 4842 TROMPELOEIL_IDENTITY( \ 4843 TROMPELOEIL_NAMED_ALLOW_CALL_ ## N TROMPELOEIL_LPAREN __VA_ARGS__)) 4844 4845 // Accept only two arguments 4846 #define TROMPELOEIL_NAMED_ALLOW_CALL_F(obj, func) \ 4847 TROMPELOEIL_NAMED_REQUIRE_CALL_T(obj, func, .TROMPELOEIL_INFINITY_TIMES()) 4848 4849 // Accept three or more arguments. 4850 #define TROMPELOEIL_NAMED_ALLOW_CALL_T(obj, func, ...) \ 4851 TROMPELOEIL_NAMED_REQUIRE_CALL_T(obj, \ 4852 func, \ 4853 .TROMPELOEIL_INFINITY_TIMES() \ 4854 __VA_ARGS__) 4855 4856 4857 #define TROMPELOEIL_FORBID_CALL_V(...) \ 4858 TROMPELOEIL_IDENTITY(TROMPELOEIL_FORBID_CALL_IMPL TROMPELOEIL_LPAREN \ 4859 TROMPELOEIL_MORE_THAN_TWO_ARGS(__VA_ARGS__), __VA_ARGS__)) 4860 4861 // Dispatch to _F (0, 1, or 2 arguments) or _T (> 2 arguments) macro 4862 #define TROMPELOEIL_FORBID_CALL_IMPL(N, ...) \ 4863 TROMPELOEIL_IDENTITY( \ 4864 TROMPELOEIL_FORBID_CALL_ ## N TROMPELOEIL_LPAREN __VA_ARGS__)) 4865 4866 // Accept only two arguments 4867 #define TROMPELOEIL_FORBID_CALL_F(obj, func) \ 4868 TROMPELOEIL_REQUIRE_CALL_T(obj, func, .TROMPELOEIL_TIMES(0)) 4869 4870 // Accept three or more arguments. 4871 #define TROMPELOEIL_FORBID_CALL_T(obj, func, ...) \ 4872 TROMPELOEIL_REQUIRE_CALL_T(obj, \ 4873 func, \ 4874 .TROMPELOEIL_TIMES(0) __VA_ARGS__) 4875 4876 4877 #define TROMPELOEIL_NAMED_FORBID_CALL_V(...) \ 4878 TROMPELOEIL_IDENTITY(TROMPELOEIL_NAMED_FORBID_CALL_IMPL TROMPELOEIL_LPAREN \ 4879 TROMPELOEIL_MORE_THAN_TWO_ARGS(__VA_ARGS__), __VA_ARGS__)) 4880 4881 // Dispatch to _F (0, 1, or 2 arguments) or _T (> 2 arguments) macro 4882 #define TROMPELOEIL_NAMED_FORBID_CALL_IMPL(N, ...) \ 4883 TROMPELOEIL_IDENTITY( \ 4884 TROMPELOEIL_NAMED_FORBID_CALL_ ## N TROMPELOEIL_LPAREN __VA_ARGS__)) 4885 4886 // Accept only two arguments 4887 #define TROMPELOEIL_NAMED_FORBID_CALL_F(obj, func) \ 4888 TROMPELOEIL_NAMED_REQUIRE_CALL_T(obj, func, .TROMPELOEIL_TIMES(0)) 4889 4890 // Accept three or more arguments. 4891 #define TROMPELOEIL_NAMED_FORBID_CALL_T(obj, func, ...) \ 4892 TROMPELOEIL_NAMED_REQUIRE_CALL_T(obj, \ 4893 func, \ 4894 .TROMPELOEIL_TIMES(0) __VA_ARGS__) 4895 4896 4897 #if (TROMPELOEIL_CPLUSPLUS > 201103L) 4898 4899 #define TROMPELOEIL_REQUIRE_CALL(obj, func) \ 4900 TROMPELOEIL_REQUIRE_CALL_(obj, func, #obj, #func) 4901 4902 #define TROMPELOEIL_REQUIRE_CALL_(obj, func, obj_s, func_s) \ 4903 auto TROMPELOEIL_COUNT_ID(call_obj) = TROMPELOEIL_REQUIRE_CALL_OBJ(obj, func,\ 4904 obj_s, func_s) 4905 4906 #define TROMPELOEIL_NAMED_REQUIRE_CALL(obj, func) \ 4907 TROMPELOEIL_NAMED_REQUIRE_CALL_(obj, func, #obj, #func) 4908 4909 #define TROMPELOEIL_NAMED_REQUIRE_CALL_(obj, func, obj_s, func_s) \ 4910 TROMPELOEIL_REQUIRE_CALL_OBJ(obj, func, obj_s, func_s) 4911 4912 4913 #define TROMPELOEIL_REQUIRE_CALL_OBJ(obj, func, obj_s, func_s) \ 4914 ::trompeloeil::call_validator_t<decltype((obj).TROMPELOEIL_CONCAT(trompeloeil_self_, func))>{(obj)} + \ 4915 ::trompeloeil::detail::conditional_t<false, \ 4916 decltype((obj).func), \ 4917 decltype((obj).TROMPELOEIL_CONCAT(trompeloeil_tag_,func))>\ 4918 {__FILE__, static_cast<unsigned long>(__LINE__), obj_s "." func_s}.func 4919 4920 4921 #define TROMPELOEIL_ALLOW_CALL(obj, func) \ 4922 TROMPELOEIL_ALLOW_CALL_(obj, func, #obj, #func) 4923 4924 #define TROMPELOEIL_ALLOW_CALL_(obj, func, obj_s, func_s) \ 4925 TROMPELOEIL_REQUIRE_CALL_(obj, func, obj_s, func_s) \ 4926 .TROMPELOEIL_INFINITY_TIMES() 4927 4928 4929 #define TROMPELOEIL_NAMED_ALLOW_CALL(obj, func) \ 4930 TROMPELOEIL_NAMED_ALLOW_CALL_(obj, func, #obj, #func) 4931 4932 #define TROMPELOEIL_NAMED_ALLOW_CALL_(obj, func, obj_s, func_s) \ 4933 TROMPELOEIL_NAMED_REQUIRE_CALL_(obj, func, obj_s, func_s) \ 4934 .TROMPELOEIL_INFINITY_TIMES() 4935 4936 4937 #define TROMPELOEIL_FORBID_CALL(obj, func) \ 4938 TROMPELOEIL_FORBID_CALL_(obj, func, #obj, #func) 4939 4940 #define TROMPELOEIL_FORBID_CALL_(obj, func, obj_s, func_s) \ 4941 TROMPELOEIL_REQUIRE_CALL_(obj, func, obj_s, func_s) \ 4942 .TROMPELOEIL_TIMES(0) 4943 4944 4945 #define TROMPELOEIL_NAMED_FORBID_CALL(obj, func) \ 4946 TROMPELOEIL_NAMED_FORBID_CALL_(obj, func, #obj, #func) 4947 4948 #define TROMPELOEIL_NAMED_FORBID_CALL_(obj, func, obj_s, func_s) \ 4949 TROMPELOEIL_NAMED_REQUIRE_CALL_(obj, func, obj_s, func_s) \ 4950 .TROMPELOEIL_TIMES(0) 4951 4952 #endif /* (TROMPELOEIL_CPLUSPLUS > 201103L) */ 4953 4954 4955 #define TROMPELOEIL_WITH(...) TROMPELOEIL_WITH_(=,#__VA_ARGS__, __VA_ARGS__) 4956 #define TROMPELOEIL_LR_WITH(...) TROMPELOEIL_WITH_(&,#__VA_ARGS__, __VA_ARGS__) 4957 4958 4959 #if (TROMPELOEIL_CPLUSPLUS == 201103L) 4960 4961 #define TROMPELOEIL_WITH_(capture, arg_s, ...) \ 4962 with( \ 4963 arg_s, \ 4964 [capture] \ 4965 (typename trompeloeil_e_t::trompeloeil_call_params_type_t const& trompeloeil_x)\ 4966 { \ 4967 auto& _1 = ::trompeloeil::mkarg<1>(trompeloeil_x); \ 4968 auto& _2 = ::trompeloeil::mkarg<2>(trompeloeil_x); \ 4969 auto& _3 = ::trompeloeil::mkarg<3>(trompeloeil_x); \ 4970 auto& _4 = ::trompeloeil::mkarg<4>(trompeloeil_x); \ 4971 auto& _5 = ::trompeloeil::mkarg<5>(trompeloeil_x); \ 4972 auto& _6 = ::trompeloeil::mkarg<6>(trompeloeil_x); \ 4973 auto& _7 = ::trompeloeil::mkarg<7>(trompeloeil_x); \ 4974 auto& _8 = ::trompeloeil::mkarg<8>(trompeloeil_x); \ 4975 auto& _9 = ::trompeloeil::mkarg<9>(trompeloeil_x); \ 4976 auto&_10 = ::trompeloeil::mkarg<10>(trompeloeil_x); \ 4977 auto&_11 = ::trompeloeil::mkarg<11>(trompeloeil_x); \ 4978 auto&_12 = ::trompeloeil::mkarg<12>(trompeloeil_x); \ 4979 auto&_13 = ::trompeloeil::mkarg<13>(trompeloeil_x); \ 4980 auto&_14 = ::trompeloeil::mkarg<14>(trompeloeil_x); \ 4981 auto&_15 = ::trompeloeil::mkarg<15>(trompeloeil_x); \ 4982 ::trompeloeil::ignore( \ 4983 _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15); \ 4984 return __VA_ARGS__; \ 4985 }) 4986 4987 #else /* (TROMPELOEIL_CPLUSPLUS == 201103L) */ 4988 4989 #define TROMPELOEIL_WITH_(capture, arg_s, ...) \ 4990 with(arg_s, [capture](auto const& trompeloeil_x) { \ 4991 auto& _1 = ::trompeloeil::mkarg<1>(trompeloeil_x); \ 4992 auto& _2 = ::trompeloeil::mkarg<2>(trompeloeil_x); \ 4993 auto& _3 = ::trompeloeil::mkarg<3>(trompeloeil_x); \ 4994 auto& _4 = ::trompeloeil::mkarg<4>(trompeloeil_x); \ 4995 auto& _5 = ::trompeloeil::mkarg<5>(trompeloeil_x); \ 4996 auto& _6 = ::trompeloeil::mkarg<6>(trompeloeil_x); \ 4997 auto& _7 = ::trompeloeil::mkarg<7>(trompeloeil_x); \ 4998 auto& _8 = ::trompeloeil::mkarg<8>(trompeloeil_x); \ 4999 auto& _9 = ::trompeloeil::mkarg<9>(trompeloeil_x); \ 5000 auto&_10 = ::trompeloeil::mkarg<10>(trompeloeil_x); \ 5001 auto&_11 = ::trompeloeil::mkarg<11>(trompeloeil_x); \ 5002 auto&_12 = ::trompeloeil::mkarg<12>(trompeloeil_x); \ 5003 auto&_13 = ::trompeloeil::mkarg<13>(trompeloeil_x); \ 5004 auto&_14 = ::trompeloeil::mkarg<14>(trompeloeil_x); \ 5005 auto&_15 = ::trompeloeil::mkarg<15>(trompeloeil_x); \ 5006 ::trompeloeil::ignore(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15); \ 5007 return __VA_ARGS__; \ 5008 }) 5009 5010 #endif /* !(TROMPELOEIL_CPLUSPLUS == 201103L) */ 5011 5012 5013 #define TROMPELOEIL_SIDE_EFFECT(...) TROMPELOEIL_SIDE_EFFECT_(=, __VA_ARGS__) 5014 #define TROMPELOEIL_LR_SIDE_EFFECT(...) TROMPELOEIL_SIDE_EFFECT_(&, __VA_ARGS__) 5015 5016 5017 #if (TROMPELOEIL_CPLUSPLUS == 201103L) 5018 5019 #define TROMPELOEIL_SIDE_EFFECT_(capture, ...) \ 5020 sideeffect( \ 5021 [capture] \ 5022 (typename trompeloeil_e_t::trompeloeil_call_params_type_t& trompeloeil_x) \ 5023 { \ 5024 auto& _1 = ::trompeloeil::mkarg<1>(trompeloeil_x); \ 5025 auto& _2 = ::trompeloeil::mkarg<2>(trompeloeil_x); \ 5026 auto& _3 = ::trompeloeil::mkarg<3>(trompeloeil_x); \ 5027 auto& _4 = ::trompeloeil::mkarg<4>(trompeloeil_x); \ 5028 auto& _5 = ::trompeloeil::mkarg<5>(trompeloeil_x); \ 5029 auto& _6 = ::trompeloeil::mkarg<6>(trompeloeil_x); \ 5030 auto& _7 = ::trompeloeil::mkarg<7>(trompeloeil_x); \ 5031 auto& _8 = ::trompeloeil::mkarg<8>(trompeloeil_x); \ 5032 auto& _9 = ::trompeloeil::mkarg<9>(trompeloeil_x); \ 5033 auto&_10 = ::trompeloeil::mkarg<10>(trompeloeil_x); \ 5034 auto&_11 = ::trompeloeil::mkarg<11>(trompeloeil_x); \ 5035 auto&_12 = ::trompeloeil::mkarg<12>(trompeloeil_x); \ 5036 auto&_13 = ::trompeloeil::mkarg<13>(trompeloeil_x); \ 5037 auto&_14 = ::trompeloeil::mkarg<14>(trompeloeil_x); \ 5038 auto&_15 = ::trompeloeil::mkarg<15>(trompeloeil_x); \ 5039 ::trompeloeil::ignore( \ 5040 _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15); \ 5041 __VA_ARGS__; \ 5042 }) 5043 5044 #else /* (TROMPELOEIL_CPLUSPLUS == 201103L) */ 5045 5046 #define TROMPELOEIL_SIDE_EFFECT_(capture, ...) \ 5047 sideeffect([capture](auto& trompeloeil_x) { \ 5048 auto& _1 = ::trompeloeil::mkarg<1>(trompeloeil_x); \ 5049 auto& _2 = ::trompeloeil::mkarg<2>(trompeloeil_x); \ 5050 auto& _3 = ::trompeloeil::mkarg<3>(trompeloeil_x); \ 5051 auto& _4 = ::trompeloeil::mkarg<4>(trompeloeil_x); \ 5052 auto& _5 = ::trompeloeil::mkarg<5>(trompeloeil_x); \ 5053 auto& _6 = ::trompeloeil::mkarg<6>(trompeloeil_x); \ 5054 auto& _7 = ::trompeloeil::mkarg<7>(trompeloeil_x); \ 5055 auto& _8 = ::trompeloeil::mkarg<8>(trompeloeil_x); \ 5056 auto& _9 = ::trompeloeil::mkarg<9>(trompeloeil_x); \ 5057 auto&_10 = ::trompeloeil::mkarg<10>(trompeloeil_x); \ 5058 auto&_11 = ::trompeloeil::mkarg<11>(trompeloeil_x); \ 5059 auto&_12 = ::trompeloeil::mkarg<12>(trompeloeil_x); \ 5060 auto&_13 = ::trompeloeil::mkarg<13>(trompeloeil_x); \ 5061 auto&_14 = ::trompeloeil::mkarg<14>(trompeloeil_x); \ 5062 auto&_15 = ::trompeloeil::mkarg<15>(trompeloeil_x); \ 5063 ::trompeloeil::ignore(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15); \ 5064 __VA_ARGS__; \ 5065 }) 5066 5067 #endif /* !(TROMPELOEIL_CPLUSPLUS == 201103L) */ 5068 5069 5070 #define TROMPELOEIL_RETURN(...) TROMPELOEIL_RETURN_(=, __VA_ARGS__) 5071 #define TROMPELOEIL_LR_RETURN(...) TROMPELOEIL_RETURN_(&, __VA_ARGS__) 5072 5073 5074 #if (TROMPELOEIL_CPLUSPLUS == 201103L) 5075 5076 #define TROMPELOEIL_RETURN_(capture, ...) \ 5077 handle_return( \ 5078 [capture] \ 5079 (typename trompeloeil_e_t::trompeloeil_call_params_type_t& trompeloeil_x) \ 5080 -> typename trompeloeil_e_t::trompeloeil_return_of_t \ 5081 { \ 5082 auto& _1 = ::trompeloeil::mkarg<1>(trompeloeil_x); \ 5083 auto& _2 = ::trompeloeil::mkarg<2>(trompeloeil_x); \ 5084 auto& _3 = ::trompeloeil::mkarg<3>(trompeloeil_x); \ 5085 auto& _4 = ::trompeloeil::mkarg<4>(trompeloeil_x); \ 5086 auto& _5 = ::trompeloeil::mkarg<5>(trompeloeil_x); \ 5087 auto& _6 = ::trompeloeil::mkarg<6>(trompeloeil_x); \ 5088 auto& _7 = ::trompeloeil::mkarg<7>(trompeloeil_x); \ 5089 auto& _8 = ::trompeloeil::mkarg<8>(trompeloeil_x); \ 5090 auto& _9 = ::trompeloeil::mkarg<9>(trompeloeil_x); \ 5091 auto&_10 = ::trompeloeil::mkarg<10>(trompeloeil_x); \ 5092 auto&_11 = ::trompeloeil::mkarg<11>(trompeloeil_x); \ 5093 auto&_12 = ::trompeloeil::mkarg<12>(trompeloeil_x); \ 5094 auto&_13 = ::trompeloeil::mkarg<13>(trompeloeil_x); \ 5095 auto&_14 = ::trompeloeil::mkarg<14>(trompeloeil_x); \ 5096 auto&_15 = ::trompeloeil::mkarg<15>(trompeloeil_x); \ 5097 ::trompeloeil::ignore( \ 5098 _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15); \ 5099 return ::trompeloeil::decay_return_type(__VA_ARGS__); \ 5100 }) 5101 5102 #else /* (TROMPELOEIL_CPLUSPLUS == 201103L) */ 5103 5104 #define TROMPELOEIL_RETURN_(capture, ...) \ 5105 handle_return([capture](auto& trompeloeil_x) -> decltype(auto) { \ 5106 auto& _1 = ::trompeloeil::mkarg<1>(trompeloeil_x); \ 5107 auto& _2 = ::trompeloeil::mkarg<2>(trompeloeil_x); \ 5108 auto& _3 = ::trompeloeil::mkarg<3>(trompeloeil_x); \ 5109 auto& _4 = ::trompeloeil::mkarg<4>(trompeloeil_x); \ 5110 auto& _5 = ::trompeloeil::mkarg<5>(trompeloeil_x); \ 5111 auto& _6 = ::trompeloeil::mkarg<6>(trompeloeil_x); \ 5112 auto& _7 = ::trompeloeil::mkarg<7>(trompeloeil_x); \ 5113 auto& _8 = ::trompeloeil::mkarg<8>(trompeloeil_x); \ 5114 auto& _9 = ::trompeloeil::mkarg<9>(trompeloeil_x); \ 5115 auto&_10 = ::trompeloeil::mkarg<10>(trompeloeil_x); \ 5116 auto&_11 = ::trompeloeil::mkarg<11>(trompeloeil_x); \ 5117 auto&_12 = ::trompeloeil::mkarg<12>(trompeloeil_x); \ 5118 auto&_13 = ::trompeloeil::mkarg<13>(trompeloeil_x); \ 5119 auto&_14 = ::trompeloeil::mkarg<14>(trompeloeil_x); \ 5120 auto&_15 = ::trompeloeil::mkarg<15>(trompeloeil_x); \ 5121 ::trompeloeil::ignore(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15); \ 5122 return ::trompeloeil::decay_return_type(__VA_ARGS__); \ 5123 }) 5124 5125 #endif /* !(TROMPELOEIL_CPLUSPLUS == 201103L) */ 5126 5127 5128 #define TROMPELOEIL_THROW(...) TROMPELOEIL_THROW_(=, __VA_ARGS__) 5129 #define TROMPELOEIL_LR_THROW(...) TROMPELOEIL_THROW_(&, __VA_ARGS__) 5130 5131 5132 #if (TROMPELOEIL_CPLUSPLUS == 201103L) 5133 5134 #define TROMPELOEIL_THROW_(capture, ...) \ 5135 handle_throw( \ 5136 [capture] \ 5137 (typename trompeloeil_e_t::trompeloeil_call_params_type_t& trompeloeil_x) \ 5138 { \ 5139 auto& _1 = ::trompeloeil::mkarg<1>(trompeloeil_x); \ 5140 auto& _2 = ::trompeloeil::mkarg<2>(trompeloeil_x); \ 5141 auto& _3 = ::trompeloeil::mkarg<3>(trompeloeil_x); \ 5142 auto& _4 = ::trompeloeil::mkarg<4>(trompeloeil_x); \ 5143 auto& _5 = ::trompeloeil::mkarg<5>(trompeloeil_x); \ 5144 auto& _6 = ::trompeloeil::mkarg<6>(trompeloeil_x); \ 5145 auto& _7 = ::trompeloeil::mkarg<7>(trompeloeil_x); \ 5146 auto& _8 = ::trompeloeil::mkarg<8>(trompeloeil_x); \ 5147 auto& _9 = ::trompeloeil::mkarg<9>(trompeloeil_x); \ 5148 auto&_10 = ::trompeloeil::mkarg<10>(trompeloeil_x); \ 5149 auto&_11 = ::trompeloeil::mkarg<11>(trompeloeil_x); \ 5150 auto&_12 = ::trompeloeil::mkarg<12>(trompeloeil_x); \ 5151 auto&_13 = ::trompeloeil::mkarg<13>(trompeloeil_x); \ 5152 auto&_14 = ::trompeloeil::mkarg<14>(trompeloeil_x); \ 5153 auto&_15 = ::trompeloeil::mkarg<15>(trompeloeil_x); \ 5154 ::trompeloeil::ignore( \ 5155 _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15); \ 5156 throw __VA_ARGS__; \ 5157 }) 5158 5159 #else /* (TROMPELOEIL_CPLUSPLUS == 201103L) */ 5160 5161 #define TROMPELOEIL_THROW_(capture, ...) \ 5162 handle_throw([capture](auto& trompeloeil_x) { \ 5163 auto& _1 = ::trompeloeil::mkarg<1>(trompeloeil_x); \ 5164 auto& _2 = ::trompeloeil::mkarg<2>(trompeloeil_x); \ 5165 auto& _3 = ::trompeloeil::mkarg<3>(trompeloeil_x); \ 5166 auto& _4 = ::trompeloeil::mkarg<4>(trompeloeil_x); \ 5167 auto& _5 = ::trompeloeil::mkarg<5>(trompeloeil_x); \ 5168 auto& _6 = ::trompeloeil::mkarg<6>(trompeloeil_x); \ 5169 auto& _7 = ::trompeloeil::mkarg<7>(trompeloeil_x); \ 5170 auto& _8 = ::trompeloeil::mkarg<8>(trompeloeil_x); \ 5171 auto& _9 = ::trompeloeil::mkarg<9>(trompeloeil_x); \ 5172 auto&_10 = ::trompeloeil::mkarg<10>(trompeloeil_x); \ 5173 auto&_11 = ::trompeloeil::mkarg<11>(trompeloeil_x); \ 5174 auto&_12 = ::trompeloeil::mkarg<12>(trompeloeil_x); \ 5175 auto&_13 = ::trompeloeil::mkarg<13>(trompeloeil_x); \ 5176 auto&_14 = ::trompeloeil::mkarg<14>(trompeloeil_x); \ 5177 auto&_15 = ::trompeloeil::mkarg<15>(trompeloeil_x); \ 5178 ::trompeloeil::ignore(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15); \ 5179 throw __VA_ARGS__; \ 5180 }) 5181 5182 #endif /* !(TROMPELOEIL_CPLUSPLUS == 201103L) */ 5183 5184 5185 #define TROMPELOEIL_TIMES(...) times(::trompeloeil::multiplicity<__VA_ARGS__>{}) 5186 #define TROMPELOEIL_INFINITY_TIMES() TROMPELOEIL_TIMES(0, ~static_cast<size_t>(0)) 5187 5188 #define TROMPELOEIL_IN_SEQUENCE(...) \ 5189 in_sequence(TROMPELOEIL_INIT_WITH_STR(::trompeloeil::sequence_matcher::init_type, __VA_ARGS__)) 5190 5191 #define TROMPELOEIL_ANY(type) ::trompeloeil::any_matcher<type>(#type) 5192 5193 #define TROMPELOEIL_AT_LEAST(num) num, ~static_cast<size_t>(0) 5194 #define TROMPELOEIL_AT_MOST(num) 0, num 5195 5196 #define TROMPELOEIL_REQUIRE_DESTRUCTION(obj) \ 5197 TROMPELOEIL_REQUIRE_DESTRUCTION_(obj, #obj) 5198 5199 #define TROMPELOEIL_REQUIRE_DESTRUCTION_(obj, obj_s) \ 5200 std::unique_ptr<trompeloeil::expectation> \ 5201 TROMPELOEIL_CONCAT(trompeloeil_death_monitor_, __LINE__) \ 5202 = TROMPELOEIL_NAMED_REQUIRE_DESTRUCTION_(,obj, obj_s) 5203 5204 #define TROMPELOEIL_NAMED_REQUIRE_DESTRUCTION(obj) \ 5205 TROMPELOEIL_NAMED_REQUIRE_DESTRUCTION_("NAMED_", obj, #obj) 5206 5207 #define TROMPELOEIL_NAMED_REQUIRE_DESTRUCTION_(prefix, obj, obj_s) \ 5208 trompeloeil::lifetime_monitor_releaser{} + \ 5209 trompeloeil::lifetime_monitor_modifier<false>{ \ 5210 ::trompeloeil::detail::make_unique<trompeloeil::lifetime_monitor>( \ 5211 obj, \ 5212 obj_s, \ 5213 prefix "REQUIRE_DESTRUCTION(" obj_s ")", \ 5214 "destructor for " obj_s, \ 5215 ::trompeloeil::location{__FILE__, \ 5216 static_cast<unsigned long>(__LINE__)}) \ 5217 } 5218 5219 #ifndef TROMPELOEIL_LONG_MACROS 5220 #define MAKE_MOCK0 TROMPELOEIL_MAKE_MOCK0 5221 #define MAKE_MOCK1 TROMPELOEIL_MAKE_MOCK1 5222 #define MAKE_MOCK2 TROMPELOEIL_MAKE_MOCK2 5223 #define MAKE_MOCK3 TROMPELOEIL_MAKE_MOCK3 5224 #define MAKE_MOCK4 TROMPELOEIL_MAKE_MOCK4 5225 #define MAKE_MOCK5 TROMPELOEIL_MAKE_MOCK5 5226 #define MAKE_MOCK6 TROMPELOEIL_MAKE_MOCK6 5227 #define MAKE_MOCK7 TROMPELOEIL_MAKE_MOCK7 5228 #define MAKE_MOCK8 TROMPELOEIL_MAKE_MOCK8 5229 #define MAKE_MOCK9 TROMPELOEIL_MAKE_MOCK9 5230 #define MAKE_MOCK10 TROMPELOEIL_MAKE_MOCK10 5231 #define MAKE_MOCK11 TROMPELOEIL_MAKE_MOCK11 5232 #define MAKE_MOCK12 TROMPELOEIL_MAKE_MOCK12 5233 #define MAKE_MOCK13 TROMPELOEIL_MAKE_MOCK13 5234 #define MAKE_MOCK14 TROMPELOEIL_MAKE_MOCK14 5235 #define MAKE_MOCK15 TROMPELOEIL_MAKE_MOCK15 5236 5237 #define MAKE_CONST_MOCK0 TROMPELOEIL_MAKE_CONST_MOCK0 5238 #define MAKE_CONST_MOCK1 TROMPELOEIL_MAKE_CONST_MOCK1 5239 #define MAKE_CONST_MOCK2 TROMPELOEIL_MAKE_CONST_MOCK2 5240 #define MAKE_CONST_MOCK3 TROMPELOEIL_MAKE_CONST_MOCK3 5241 #define MAKE_CONST_MOCK4 TROMPELOEIL_MAKE_CONST_MOCK4 5242 #define MAKE_CONST_MOCK5 TROMPELOEIL_MAKE_CONST_MOCK5 5243 #define MAKE_CONST_MOCK6 TROMPELOEIL_MAKE_CONST_MOCK6 5244 #define MAKE_CONST_MOCK7 TROMPELOEIL_MAKE_CONST_MOCK7 5245 #define MAKE_CONST_MOCK8 TROMPELOEIL_MAKE_CONST_MOCK8 5246 #define MAKE_CONST_MOCK9 TROMPELOEIL_MAKE_CONST_MOCK9 5247 #define MAKE_CONST_MOCK10 TROMPELOEIL_MAKE_CONST_MOCK10 5248 #define MAKE_CONST_MOCK11 TROMPELOEIL_MAKE_CONST_MOCK11 5249 #define MAKE_CONST_MOCK12 TROMPELOEIL_MAKE_CONST_MOCK12 5250 #define MAKE_CONST_MOCK13 TROMPELOEIL_MAKE_CONST_MOCK13 5251 #define MAKE_CONST_MOCK14 TROMPELOEIL_MAKE_CONST_MOCK14 5252 #define MAKE_CONST_MOCK15 TROMPELOEIL_MAKE_CONST_MOCK15 5253 5254 #define IMPLEMENT_MOCK0 TROMPELOEIL_IMPLEMENT_MOCK0 5255 #define IMPLEMENT_MOCK1 TROMPELOEIL_IMPLEMENT_MOCK1 5256 #define IMPLEMENT_MOCK2 TROMPELOEIL_IMPLEMENT_MOCK2 5257 #define IMPLEMENT_MOCK3 TROMPELOEIL_IMPLEMENT_MOCK3 5258 #define IMPLEMENT_MOCK4 TROMPELOEIL_IMPLEMENT_MOCK4 5259 #define IMPLEMENT_MOCK5 TROMPELOEIL_IMPLEMENT_MOCK5 5260 #define IMPLEMENT_MOCK6 TROMPELOEIL_IMPLEMENT_MOCK6 5261 #define IMPLEMENT_MOCK7 TROMPELOEIL_IMPLEMENT_MOCK7 5262 #define IMPLEMENT_MOCK8 TROMPELOEIL_IMPLEMENT_MOCK8 5263 #define IMPLEMENT_MOCK9 TROMPELOEIL_IMPLEMENT_MOCK9 5264 #define IMPLEMENT_MOCK10 TROMPELOEIL_IMPLEMENT_MOCK10 5265 #define IMPLEMENT_MOCK11 TROMPELOEIL_IMPLEMENT_MOCK11 5266 #define IMPLEMENT_MOCK12 TROMPELOEIL_IMPLEMENT_MOCK12 5267 #define IMPLEMENT_MOCK13 TROMPELOEIL_IMPLEMENT_MOCK13 5268 #define IMPLEMENT_MOCK14 TROMPELOEIL_IMPLEMENT_MOCK14 5269 #define IMPLEMENT_MOCK15 TROMPELOEIL_IMPLEMENT_MOCK15 5270 5271 #define IMPLEMENT_CONST_MOCK0 TROMPELOEIL_IMPLEMENT_CONST_MOCK0 5272 #define IMPLEMENT_CONST_MOCK1 TROMPELOEIL_IMPLEMENT_CONST_MOCK1 5273 #define IMPLEMENT_CONST_MOCK2 TROMPELOEIL_IMPLEMENT_CONST_MOCK2 5274 #define IMPLEMENT_CONST_MOCK3 TROMPELOEIL_IMPLEMENT_CONST_MOCK3 5275 #define IMPLEMENT_CONST_MOCK4 TROMPELOEIL_IMPLEMENT_CONST_MOCK4 5276 #define IMPLEMENT_CONST_MOCK5 TROMPELOEIL_IMPLEMENT_CONST_MOCK5 5277 #define IMPLEMENT_CONST_MOCK6 TROMPELOEIL_IMPLEMENT_CONST_MOCK6 5278 #define IMPLEMENT_CONST_MOCK7 TROMPELOEIL_IMPLEMENT_CONST_MOCK7 5279 #define IMPLEMENT_CONST_MOCK8 TROMPELOEIL_IMPLEMENT_CONST_MOCK8 5280 #define IMPLEMENT_CONST_MOCK9 TROMPELOEIL_IMPLEMENT_CONST_MOCK9 5281 #define IMPLEMENT_CONST_MOCK10 TROMPELOEIL_IMPLEMENT_CONST_MOCK10 5282 #define IMPLEMENT_CONST_MOCK11 TROMPELOEIL_IMPLEMENT_CONST_MOCK11 5283 #define IMPLEMENT_CONST_MOCK12 TROMPELOEIL_IMPLEMENT_CONST_MOCK12 5284 #define IMPLEMENT_CONST_MOCK13 TROMPELOEIL_IMPLEMENT_CONST_MOCK13 5285 #define IMPLEMENT_CONST_MOCK14 TROMPELOEIL_IMPLEMENT_CONST_MOCK14 5286 #define IMPLEMENT_CONST_MOCK15 TROMPELOEIL_IMPLEMENT_CONST_MOCK15 5287 5288 #define REQUIRE_CALL_V TROMPELOEIL_REQUIRE_CALL_V 5289 #define NAMED_REQUIRE_CALL_V TROMPELOEIL_NAMED_REQUIRE_CALL_V 5290 #define ALLOW_CALL_V TROMPELOEIL_ALLOW_CALL_V 5291 #define NAMED_ALLOW_CALL_V TROMPELOEIL_NAMED_ALLOW_CALL_V 5292 #define FORBID_CALL_V TROMPELOEIL_FORBID_CALL_V 5293 #define NAMED_FORBID_CALL_V TROMPELOEIL_NAMED_FORBID_CALL_V 5294 5295 #if (TROMPELOEIL_CPLUSPLUS > 201103L) 5296 5297 #define REQUIRE_CALL TROMPELOEIL_REQUIRE_CALL 5298 #define NAMED_REQUIRE_CALL TROMPELOEIL_NAMED_REQUIRE_CALL 5299 #define ALLOW_CALL TROMPELOEIL_ALLOW_CALL 5300 #define NAMED_ALLOW_CALL TROMPELOEIL_NAMED_ALLOW_CALL 5301 #define FORBID_CALL TROMPELOEIL_FORBID_CALL 5302 #define NAMED_FORBID_CALL TROMPELOEIL_NAMED_FORBID_CALL 5303 5304 #endif /* (TROMPELOEIL_CPLUSPLUS > 201103L) */ 5305 5306 #define WITH TROMPELOEIL_WITH 5307 #define LR_WITH TROMPELOEIL_LR_WITH 5308 #define SIDE_EFFECT TROMPELOEIL_SIDE_EFFECT 5309 #define LR_SIDE_EFFECT TROMPELOEIL_LR_SIDE_EFFECT 5310 #define RETURN TROMPELOEIL_RETURN 5311 #define LR_RETURN TROMPELOEIL_LR_RETURN 5312 #define THROW TROMPELOEIL_THROW 5313 #define LR_THROW TROMPELOEIL_LR_THROW 5314 5315 #define TIMES TROMPELOEIL_TIMES 5316 #define IN_SEQUENCE TROMPELOEIL_IN_SEQUENCE 5317 #define ANY TROMPELOEIL_ANY 5318 #define AT_LEAST TROMPELOEIL_AT_LEAST 5319 #define AT_MOST TROMPELOEIL_AT_MOST 5320 #define REQUIRE_DESTRUCTION TROMPELOEIL_REQUIRE_DESTRUCTION 5321 #define NAMED_REQUIRE_DESTRUCTION TROMPELOEIL_NAMED_REQUIRE_DESTRUCTION 5322 5323 #endif // TROMPELOEIL_LONG_MACROS 5324 5325 #endif // include guard