trompeloeil

FORK: Header only C++14 mocking framework
git clone https://git.neptards.moe/u3shit/trompeloeil.git
Log | Files | Refs | README

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