File indexing completed on 2024-09-22 04:53:11

0001 /*
0002  * SPDX-FileCopyrightText: 2008 Trevor Pounds
0003  * SPDX-License-Identifier: MIT
0004  */
0005 
0006 #ifndef __MOCKITOPP_DYNAMIC_VFUNCTION_HPP__
0007 #define __MOCKITOPP_DYNAMIC_VFUNCTION_HPP__
0008 
0009 #include <algorithm>
0010 #include <list>
0011 
0012 #include <mockitopp/exceptions.hpp>
0013 #include <mockitopp/detail/stubbing/action.hpp>
0014 #include <mockitopp/detail/util/pointers.hpp>
0015 #include <mockitopp/detail/util/tr1_tuple.hpp>
0016 #include <mockitopp/matchers/Matcher.hpp>
0017 
0018 // TODO: add documentation
0019 namespace mockitopp
0020 {
0021    namespace detail
0022    {
0023       struct dynamic_vfunction_base
0024       {
0025          int calls;
0026 
0027          // allow polymorphic desctruction with unknown subtype
0028          virtual ~dynamic_vfunction_base() {}
0029 
0030          /**
0031           * verify method is called within a specified range
0032           *
0033           * @param min minimum times method should be called
0034           * @param max maximum times method should be called
0035           */
0036          bool between(int min, int max) const
0037          {
0038             if(calls >= min && calls <= max)
0039                { return true; }
0040             return false;
0041          }
0042 
0043          /**
0044           * verify method is called at least (n) times
0045           *
0046           * @param times minimum number of times method should be called
0047           */
0048          bool atLeast(int times) const
0049             { return calls >= times; }
0050 
0051          /**
0052           * verify method is called at most (n) times
0053           *
0054           * @param times maximum number of times method should be called
0055           */
0056          bool atMost(int times) const
0057             { return calls <= times; }
0058 
0059          /**
0060           * verify method is called exactly (n) times
0061           *
0062           * @param times exact number of times method should be called
0063           */
0064          bool exactly(int times) const
0065             { return calls == times; }
0066 
0067          /**
0068           * verify method is never called
0069           */
0070          bool never() const
0071             { return calls == 0; }
0072       };
0073 
0074       template <typename R>
0075       struct dynamic_vfunction_progress : dynamic_vfunction_base
0076       {
0077          typedef shared_ptr<action<R> > action_type;
0078          typedef std::list<action_type> action_queue_type;
0079 
0080          action_queue_type* stubbing_progress;
0081 
0082          dynamic_vfunction_progress& thenReturn(R value)
0083          {
0084             stubbing_progress->push_back(action_type(new returnable_action<R>(value)));
0085             return *this;
0086          }
0087 
0088          template <typename T>
0089          dynamic_vfunction_progress& thenThrow(T throwable)
0090          {
0091             stubbing_progress->push_back(action_type(new throwable_action<R, T>(throwable)));
0092             return *this;
0093          }
0094       };
0095 
0096       template <>
0097       struct dynamic_vfunction_progress<void> : dynamic_vfunction_base
0098       {
0099          typedef shared_ptr<action<void> > action_type;
0100          typedef std::list<action_type>    action_queue_type;
0101 
0102          action_queue_type* stubbing_progress;
0103 
0104          dynamic_vfunction_progress& thenReturn()
0105          {
0106             stubbing_progress->push_back(action_type(new returnable_action<void>()));
0107             return *this;
0108          }
0109 
0110          template <typename T>
0111          dynamic_vfunction_progress& thenThrow(T throwable)
0112          {
0113             stubbing_progress->push_back(action_type(new throwable_action<void, T>(throwable)));
0114             return *this;
0115          }
0116       };
0117 
0118       template <typename K, typename V>
0119       struct map_entry
0120       {
0121          K key;
0122          V val;
0123 
0124          map_entry(const K& k, const V& v) : key(k), val(v) {}
0125 
0126          template <typename K2, typename V2>
0127             bool operator== (const map_entry<K2, V2>& rhs) const
0128             { return key == rhs.key; }
0129 
0130          template <typename T>
0131             bool operator== (const T& rhs) const
0132             { return key == rhs; }
0133       };
0134 
0135       template <typename T>
0136       struct matcher_element
0137       {
0138          matcher::Matcher<T>* matcher;
0139   
0140          matcher_element(const matcher::Matcher<T>& _matcher)
0141             : matcher(_matcher.clone())
0142             {}
0143 
0144          matcher_element(const matcher_element& rhs)
0145             : matcher(rhs.matcher->clone())
0146             {}
0147 
0148          ~matcher_element()
0149             { delete matcher; }
0150 
0151          matcher_element &operator= (const matcher_element& rhs) const
0152             { matcher_element tmp(rhs); std::swap(*this, tmp); return *this; }
0153 
0154          bool operator== (typename tr1::add_reference<typename tr1::add_const<T>::type>::type rhs) const
0155             { return (*matcher == rhs); }
0156 
0157          bool operator== (const matcher_element& rhs) const
0158             { return (matcher == rhs.matcher); }
0159       };
0160 
0161       template <typename T> struct dynamic_vfunction;
0162 
0163       // TODO: clean up impl
0164       // TODO: add sequence matcher
0165 
0166       // TODO: clean up typedef nomenclature
0167  
0168       // 0 arity template
0169       template <typename R, typename C>
0170       struct dynamic_vfunction<R (C::*)()> : private dynamic_vfunction_progress<R>
0171       {
0172          typedef tr1::tuple<> exact_tuple_type;
0173          typedef tr1::tuple< > fuzzy_tuple_type;
0174 
0175          typedef typename dynamic_vfunction_progress<R>::action_type       action_type;
0176          typedef typename dynamic_vfunction_progress<R>::action_queue_type action_queue_type;
0177 
0178          std::list<map_entry<exact_tuple_type, action_queue_type> > exact_matches;
0179          std::list<map_entry<fuzzy_tuple_type, action_queue_type> > fuzzy_matches;
0180          std::list<map_entry<exact_tuple_type, int> >               args_to_calls;
0181 
0182          dynamic_vfunction()
0183             : dynamic_vfunction_progress<R>()
0184             , exact_matches()
0185             , fuzzy_matches()
0186             {}
0187 
0188          template <typename T>
0189          int calculate_calls_for_arguments(const T args) {
0190             int calls = 0;
0191             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0192                = args_to_calls.begin();
0193             for(; calls_it != args_to_calls.end(); calls_it++) {
0194                if(args == calls_it->key) {
0195                   calls += calls_it->val;
0196                }
0197             }
0198             return calls;
0199          }
0200 
0201          
0202 
0203          dynamic_vfunction_progress<R>& when()
0204          {
0205             const exact_tuple_type args = exact_tuple_type();
0206             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator match
0207                = std::find(exact_matches.begin(), exact_matches.end(), args);
0208             if(match == exact_matches.end())
0209             {
0210                exact_matches.push_back(map_entry<exact_tuple_type, action_queue_type>(args, action_queue_type()));
0211                match = --exact_matches.end();
0212             }
0213             this->calls = calculate_calls_for_arguments(args);
0214             this->stubbing_progress = &(match->val);
0215             return *this;
0216          }
0217 
0218          R invoke()
0219          {
0220             const exact_tuple_type args = exact_tuple_type();
0221 
0222             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0223                = std::find(args_to_calls.begin(), args_to_calls.end(), args);
0224             if(calls_it == args_to_calls.end()) {
0225                args_to_calls.push_back(map_entry<exact_tuple_type, int>(args, 1));
0226             } else {
0227                (calls_it->val)++;
0228             }
0229 
0230             action_queue_type* actions = 0;
0231             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator exact_match
0232                = std::find(exact_matches.begin(), exact_matches.end(), args);
0233             if(exact_match != exact_matches.end())
0234                { actions = &(exact_match->val); }
0235             if(!actions)
0236             {
0237                typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator fuzzy_match
0238                   = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0239                if(fuzzy_match == fuzzy_matches.end())
0240                    { throw partial_implementation_exception(); }
0241                actions = &(fuzzy_match->val);
0242             }
0243             action_type action = actions->front();
0244             if(actions->size() > 1)
0245                { actions->pop_front(); }
0246             return action->invoke();
0247          }
0248       };
0249  
0250       // 1 arity template
0251       template <typename R, typename C, typename A0>
0252       struct dynamic_vfunction<R (C::*)(A0)> : private dynamic_vfunction_progress<R>
0253       {
0254          typedef tr1::tuple<A0> exact_tuple_type;
0255          typedef tr1::tuple<matcher_element<A0 > > fuzzy_tuple_type;
0256 
0257          typedef typename dynamic_vfunction_progress<R>::action_type       action_type;
0258          typedef typename dynamic_vfunction_progress<R>::action_queue_type action_queue_type;
0259 
0260          std::list<map_entry<exact_tuple_type, action_queue_type> > exact_matches;
0261          std::list<map_entry<fuzzy_tuple_type, action_queue_type> > fuzzy_matches;
0262          std::list<map_entry<exact_tuple_type, int> >               args_to_calls;
0263 
0264          dynamic_vfunction()
0265             : dynamic_vfunction_progress<R>()
0266             , exact_matches()
0267             , fuzzy_matches()
0268             {}
0269 
0270          template <typename T>
0271          int calculate_calls_for_arguments(const T args) {
0272             int calls = 0;
0273             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0274                = args_to_calls.begin();
0275             for(; calls_it != args_to_calls.end(); calls_it++) {
0276                if(args == calls_it->key) {
0277                   calls += calls_it->val;
0278                }
0279             }
0280             return calls;
0281          }
0282 
0283          dynamic_vfunction_progress<R>& when(const matcher::Matcher<A0 >& a0)
0284          {
0285             const fuzzy_tuple_type args = fuzzy_tuple_type(a0);
0286             typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator match
0287                = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0288             if(match == fuzzy_matches.end())
0289             {
0290                fuzzy_matches.push_back(map_entry<fuzzy_tuple_type, action_queue_type>(args, action_queue_type()));
0291                match = --fuzzy_matches.end();
0292             }
0293             this->calls = calculate_calls_for_arguments(args);
0294             this->stubbing_progress = &(match->val);
0295             return *this;
0296          }
0297 
0298          dynamic_vfunction_progress<R>& when(A0 a0)
0299          {
0300             const exact_tuple_type args = exact_tuple_type(a0);
0301             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator match
0302                = std::find(exact_matches.begin(), exact_matches.end(), args);
0303             if(match == exact_matches.end())
0304             {
0305                exact_matches.push_back(map_entry<exact_tuple_type, action_queue_type>(args, action_queue_type()));
0306                match = --exact_matches.end();
0307             }
0308             this->calls = calculate_calls_for_arguments(args);
0309             this->stubbing_progress = &(match->val);
0310             return *this;
0311          }
0312 
0313          R invoke(A0 a0)
0314          {
0315             const exact_tuple_type args = exact_tuple_type(a0);
0316 
0317             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0318                = std::find(args_to_calls.begin(), args_to_calls.end(), args);
0319             if(calls_it == args_to_calls.end()) {
0320                args_to_calls.push_back(map_entry<exact_tuple_type, int>(args, 1));
0321             } else {
0322                (calls_it->val)++;
0323             }
0324 
0325             action_queue_type* actions = 0;
0326             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator exact_match
0327                = std::find(exact_matches.begin(), exact_matches.end(), args);
0328             if(exact_match != exact_matches.end())
0329                { actions = &(exact_match->val); }
0330             if(!actions)
0331             {
0332                typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator fuzzy_match
0333                   = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0334                if(fuzzy_match == fuzzy_matches.end())
0335                    { throw partial_implementation_exception(); }
0336                actions = &(fuzzy_match->val);
0337             }
0338             action_type action = actions->front();
0339             if(actions->size() > 1)
0340                { actions->pop_front(); }
0341             return action->invoke();
0342          }
0343       };
0344  
0345       // 2 arity template
0346       template <typename R, typename C, typename A0, typename A1>
0347       struct dynamic_vfunction<R (C::*)(A0, A1)> : private dynamic_vfunction_progress<R>
0348       {
0349          typedef tr1::tuple<A0, A1> exact_tuple_type;
0350          typedef tr1::tuple<matcher_element<A0 >, matcher_element<A1 > > fuzzy_tuple_type;
0351 
0352          typedef typename dynamic_vfunction_progress<R>::action_type       action_type;
0353          typedef typename dynamic_vfunction_progress<R>::action_queue_type action_queue_type;
0354 
0355          std::list<map_entry<exact_tuple_type, action_queue_type> > exact_matches;
0356          std::list<map_entry<fuzzy_tuple_type, action_queue_type> > fuzzy_matches;
0357          std::list<map_entry<exact_tuple_type, int> >               args_to_calls;
0358 
0359          dynamic_vfunction()
0360             : dynamic_vfunction_progress<R>()
0361             , exact_matches()
0362             , fuzzy_matches()
0363             {}
0364 
0365          template <typename T>
0366          int calculate_calls_for_arguments(const T args) {
0367             int calls = 0;
0368             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0369                = args_to_calls.begin();
0370             for(; calls_it != args_to_calls.end(); calls_it++) {
0371                if(args == calls_it->key) {
0372                   calls += calls_it->val;
0373                }
0374             }
0375             return calls;
0376          }
0377 
0378          dynamic_vfunction_progress<R>& when(const matcher::Matcher<A0 >& a0, const matcher::Matcher<A1 >& a1)
0379          {
0380             const fuzzy_tuple_type args = fuzzy_tuple_type(a0, a1);
0381             typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator match
0382                = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0383             if(match == fuzzy_matches.end())
0384             {
0385                fuzzy_matches.push_back(map_entry<fuzzy_tuple_type, action_queue_type>(args, action_queue_type()));
0386                match = --fuzzy_matches.end();
0387             }
0388             this->calls = calculate_calls_for_arguments(args);
0389             this->stubbing_progress = &(match->val);
0390             return *this;
0391          }
0392 
0393          dynamic_vfunction_progress<R>& when(A0 a0, A1 a1)
0394          {
0395             const exact_tuple_type args = exact_tuple_type(a0, a1);
0396             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator match
0397                = std::find(exact_matches.begin(), exact_matches.end(), args);
0398             if(match == exact_matches.end())
0399             {
0400                exact_matches.push_back(map_entry<exact_tuple_type, action_queue_type>(args, action_queue_type()));
0401                match = --exact_matches.end();
0402             }
0403             this->calls = calculate_calls_for_arguments(args);
0404             this->stubbing_progress = &(match->val);
0405             return *this;
0406          }
0407 
0408          R invoke(A0 a0, A1 a1)
0409          {
0410             const exact_tuple_type args = exact_tuple_type(a0, a1);
0411 
0412             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0413                = std::find(args_to_calls.begin(), args_to_calls.end(), args);
0414             if(calls_it == args_to_calls.end()) {
0415                args_to_calls.push_back(map_entry<exact_tuple_type, int>(args, 1));
0416             } else {
0417                (calls_it->val)++;
0418             }
0419 
0420             action_queue_type* actions = 0;
0421             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator exact_match
0422                = std::find(exact_matches.begin(), exact_matches.end(), args);
0423             if(exact_match != exact_matches.end())
0424                { actions = &(exact_match->val); }
0425             if(!actions)
0426             {
0427                typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator fuzzy_match
0428                   = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0429                if(fuzzy_match == fuzzy_matches.end())
0430                    { throw partial_implementation_exception(); }
0431                actions = &(fuzzy_match->val);
0432             }
0433             action_type action = actions->front();
0434             if(actions->size() > 1)
0435                { actions->pop_front(); }
0436             return action->invoke();
0437          }
0438       };
0439  
0440       // 3 arity template
0441       template <typename R, typename C, typename A0, typename A1, typename A2>
0442       struct dynamic_vfunction<R (C::*)(A0, A1, A2)> : private dynamic_vfunction_progress<R>
0443       {
0444          typedef tr1::tuple<A0, A1, A2> exact_tuple_type;
0445          typedef tr1::tuple<matcher_element<A0 >, matcher_element<A1 >, matcher_element<A2 > > fuzzy_tuple_type;
0446 
0447          typedef typename dynamic_vfunction_progress<R>::action_type       action_type;
0448          typedef typename dynamic_vfunction_progress<R>::action_queue_type action_queue_type;
0449 
0450          std::list<map_entry<exact_tuple_type, action_queue_type> > exact_matches;
0451          std::list<map_entry<fuzzy_tuple_type, action_queue_type> > fuzzy_matches;
0452          std::list<map_entry<exact_tuple_type, int> >               args_to_calls;
0453 
0454          dynamic_vfunction()
0455             : dynamic_vfunction_progress<R>()
0456             , exact_matches()
0457             , fuzzy_matches()
0458             {}
0459 
0460          template <typename T>
0461          int calculate_calls_for_arguments(const T args) {
0462             int calls = 0;
0463             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0464                = args_to_calls.begin();
0465             for(; calls_it != args_to_calls.end(); calls_it++) {
0466                if(args == calls_it->key) {
0467                   calls += calls_it->val;
0468                }
0469             }
0470             return calls;
0471          }
0472 
0473          dynamic_vfunction_progress<R>& when(const matcher::Matcher<A0 >& a0, const matcher::Matcher<A1 >& a1, const matcher::Matcher<A2 >& a2)
0474          {
0475             const fuzzy_tuple_type args = fuzzy_tuple_type(a0, a1, a2);
0476             typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator match
0477                = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0478             if(match == fuzzy_matches.end())
0479             {
0480                fuzzy_matches.push_back(map_entry<fuzzy_tuple_type, action_queue_type>(args, action_queue_type()));
0481                match = --fuzzy_matches.end();
0482             }
0483             this->calls = calculate_calls_for_arguments(args);
0484             this->stubbing_progress = &(match->val);
0485             return *this;
0486          }
0487 
0488          dynamic_vfunction_progress<R>& when(A0 a0, A1 a1, A2 a2)
0489          {
0490             const exact_tuple_type args = exact_tuple_type(a0, a1, a2);
0491             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator match
0492                = std::find(exact_matches.begin(), exact_matches.end(), args);
0493             if(match == exact_matches.end())
0494             {
0495                exact_matches.push_back(map_entry<exact_tuple_type, action_queue_type>(args, action_queue_type()));
0496                match = --exact_matches.end();
0497             }
0498             this->calls = calculate_calls_for_arguments(args);
0499             this->stubbing_progress = &(match->val);
0500             return *this;
0501          }
0502 
0503          R invoke(A0 a0, A1 a1, A2 a2)
0504          {
0505             const exact_tuple_type args = exact_tuple_type(a0, a1, a2);
0506 
0507             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0508                = std::find(args_to_calls.begin(), args_to_calls.end(), args);
0509             if(calls_it == args_to_calls.end()) {
0510                args_to_calls.push_back(map_entry<exact_tuple_type, int>(args, 1));
0511             } else {
0512                (calls_it->val)++;
0513             }
0514 
0515             action_queue_type* actions = 0;
0516             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator exact_match
0517                = std::find(exact_matches.begin(), exact_matches.end(), args);
0518             if(exact_match != exact_matches.end())
0519                { actions = &(exact_match->val); }
0520             if(!actions)
0521             {
0522                typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator fuzzy_match
0523                   = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0524                if(fuzzy_match == fuzzy_matches.end())
0525                    { throw partial_implementation_exception(); }
0526                actions = &(fuzzy_match->val);
0527             }
0528             action_type action = actions->front();
0529             if(actions->size() > 1)
0530                { actions->pop_front(); }
0531             return action->invoke();
0532          }
0533       };
0534  
0535       // 4 arity template
0536       template <typename R, typename C, typename A0, typename A1, typename A2, typename A3>
0537       struct dynamic_vfunction<R (C::*)(A0, A1, A2, A3)> : private dynamic_vfunction_progress<R>
0538       {
0539          typedef tr1::tuple<A0, A1, A2, A3> exact_tuple_type;
0540          typedef tr1::tuple<matcher_element<A0 >, matcher_element<A1 >, matcher_element<A2 >, matcher_element<A3 > > fuzzy_tuple_type;
0541 
0542          typedef typename dynamic_vfunction_progress<R>::action_type       action_type;
0543          typedef typename dynamic_vfunction_progress<R>::action_queue_type action_queue_type;
0544 
0545          std::list<map_entry<exact_tuple_type, action_queue_type> > exact_matches;
0546          std::list<map_entry<fuzzy_tuple_type, action_queue_type> > fuzzy_matches;
0547          std::list<map_entry<exact_tuple_type, int> >               args_to_calls;
0548 
0549          dynamic_vfunction()
0550             : dynamic_vfunction_progress<R>()
0551             , exact_matches()
0552             , fuzzy_matches()
0553             {}
0554 
0555          template <typename T>
0556          int calculate_calls_for_arguments(const T args) {
0557             int calls = 0;
0558             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0559                = args_to_calls.begin();
0560             for(; calls_it != args_to_calls.end(); calls_it++) {
0561                if(args == calls_it->key) {
0562                   calls += calls_it->val;
0563                }
0564             }
0565             return calls;
0566          }
0567 
0568          dynamic_vfunction_progress<R>& when(const matcher::Matcher<A0 >& a0, const matcher::Matcher<A1 >& a1, const matcher::Matcher<A2 >& a2, const matcher::Matcher<A3 >& a3)
0569          {
0570             const fuzzy_tuple_type args = fuzzy_tuple_type(a0, a1, a2, a3);
0571             typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator match
0572                = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0573             if(match == fuzzy_matches.end())
0574             {
0575                fuzzy_matches.push_back(map_entry<fuzzy_tuple_type, action_queue_type>(args, action_queue_type()));
0576                match = --fuzzy_matches.end();
0577             }
0578             this->calls = calculate_calls_for_arguments(args);
0579             this->stubbing_progress = &(match->val);
0580             return *this;
0581          }
0582 
0583          dynamic_vfunction_progress<R>& when(A0 a0, A1 a1, A2 a2, A3 a3)
0584          {
0585             const exact_tuple_type args = exact_tuple_type(a0, a1, a2, a3);
0586             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator match
0587                = std::find(exact_matches.begin(), exact_matches.end(), args);
0588             if(match == exact_matches.end())
0589             {
0590                exact_matches.push_back(map_entry<exact_tuple_type, action_queue_type>(args, action_queue_type()));
0591                match = --exact_matches.end();
0592             }
0593             this->calls = calculate_calls_for_arguments(args);
0594             this->stubbing_progress = &(match->val);
0595             return *this;
0596          }
0597 
0598          R invoke(A0 a0, A1 a1, A2 a2, A3 a3)
0599          {
0600             const exact_tuple_type args = exact_tuple_type(a0, a1, a2, a3);
0601 
0602             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0603                = std::find(args_to_calls.begin(), args_to_calls.end(), args);
0604             if(calls_it == args_to_calls.end()) {
0605                args_to_calls.push_back(map_entry<exact_tuple_type, int>(args, 1));
0606             } else {
0607                (calls_it->val)++;
0608             }
0609 
0610             action_queue_type* actions = 0;
0611             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator exact_match
0612                = std::find(exact_matches.begin(), exact_matches.end(), args);
0613             if(exact_match != exact_matches.end())
0614                { actions = &(exact_match->val); }
0615             if(!actions)
0616             {
0617                typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator fuzzy_match
0618                   = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0619                if(fuzzy_match == fuzzy_matches.end())
0620                    { throw partial_implementation_exception(); }
0621                actions = &(fuzzy_match->val);
0622             }
0623             action_type action = actions->front();
0624             if(actions->size() > 1)
0625                { actions->pop_front(); }
0626             return action->invoke();
0627          }
0628       };
0629  
0630       // 5 arity template
0631       template <typename R, typename C, typename A0, typename A1, typename A2, typename A3, typename A4>
0632       struct dynamic_vfunction<R (C::*)(A0, A1, A2, A3, A4)> : private dynamic_vfunction_progress<R>
0633       {
0634          typedef tr1::tuple<A0, A1, A2, A3, A4> exact_tuple_type;
0635          typedef tr1::tuple<matcher_element<A0 >, matcher_element<A1 >, matcher_element<A2 >, matcher_element<A3 >, matcher_element<A4 > > fuzzy_tuple_type;
0636 
0637          typedef typename dynamic_vfunction_progress<R>::action_type       action_type;
0638          typedef typename dynamic_vfunction_progress<R>::action_queue_type action_queue_type;
0639 
0640          std::list<map_entry<exact_tuple_type, action_queue_type> > exact_matches;
0641          std::list<map_entry<fuzzy_tuple_type, action_queue_type> > fuzzy_matches;
0642          std::list<map_entry<exact_tuple_type, int> >               args_to_calls;
0643 
0644          dynamic_vfunction()
0645             : dynamic_vfunction_progress<R>()
0646             , exact_matches()
0647             , fuzzy_matches()
0648             {}
0649 
0650          template <typename T>
0651          int calculate_calls_for_arguments(const T args) {
0652             int calls = 0;
0653             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0654                = args_to_calls.begin();
0655             for(; calls_it != args_to_calls.end(); calls_it++) {
0656                if(args == calls_it->key) {
0657                   calls += calls_it->val;
0658                }
0659             }
0660             return calls;
0661          }
0662 
0663          dynamic_vfunction_progress<R>& when(const matcher::Matcher<A0 >& a0, const matcher::Matcher<A1 >& a1, const matcher::Matcher<A2 >& a2, const matcher::Matcher<A3 >& a3, const matcher::Matcher<A4 >& a4)
0664          {
0665             const fuzzy_tuple_type args = fuzzy_tuple_type(a0, a1, a2, a3, a4);
0666             typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator match
0667                = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0668             if(match == fuzzy_matches.end())
0669             {
0670                fuzzy_matches.push_back(map_entry<fuzzy_tuple_type, action_queue_type>(args, action_queue_type()));
0671                match = --fuzzy_matches.end();
0672             }
0673             this->calls = calculate_calls_for_arguments(args);
0674             this->stubbing_progress = &(match->val);
0675             return *this;
0676          }
0677 
0678          dynamic_vfunction_progress<R>& when(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4)
0679          {
0680             const exact_tuple_type args = exact_tuple_type(a0, a1, a2, a3, a4);
0681             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator match
0682                = std::find(exact_matches.begin(), exact_matches.end(), args);
0683             if(match == exact_matches.end())
0684             {
0685                exact_matches.push_back(map_entry<exact_tuple_type, action_queue_type>(args, action_queue_type()));
0686                match = --exact_matches.end();
0687             }
0688             this->calls = calculate_calls_for_arguments(args);
0689             this->stubbing_progress = &(match->val);
0690             return *this;
0691          }
0692 
0693          R invoke(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4)
0694          {
0695             const exact_tuple_type args = exact_tuple_type(a0, a1, a2, a3, a4);
0696 
0697             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0698                = std::find(args_to_calls.begin(), args_to_calls.end(), args);
0699             if(calls_it == args_to_calls.end()) {
0700                args_to_calls.push_back(map_entry<exact_tuple_type, int>(args, 1));
0701             } else {
0702                (calls_it->val)++;
0703             }
0704 
0705             action_queue_type* actions = 0;
0706             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator exact_match
0707                = std::find(exact_matches.begin(), exact_matches.end(), args);
0708             if(exact_match != exact_matches.end())
0709                { actions = &(exact_match->val); }
0710             if(!actions)
0711             {
0712                typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator fuzzy_match
0713                   = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0714                if(fuzzy_match == fuzzy_matches.end())
0715                    { throw partial_implementation_exception(); }
0716                actions = &(fuzzy_match->val);
0717             }
0718             action_type action = actions->front();
0719             if(actions->size() > 1)
0720                { actions->pop_front(); }
0721             return action->invoke();
0722          }
0723       };
0724  
0725       // 6 arity template
0726       template <typename R, typename C, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
0727       struct dynamic_vfunction<R (C::*)(A0, A1, A2, A3, A4, A5)> : private dynamic_vfunction_progress<R>
0728       {
0729          typedef tr1::tuple<A0, A1, A2, A3, A4, A5> exact_tuple_type;
0730          typedef tr1::tuple<matcher_element<A0 >, matcher_element<A1 >, matcher_element<A2 >, matcher_element<A3 >, matcher_element<A4 >, matcher_element<A5 > > fuzzy_tuple_type;
0731 
0732          typedef typename dynamic_vfunction_progress<R>::action_type       action_type;
0733          typedef typename dynamic_vfunction_progress<R>::action_queue_type action_queue_type;
0734 
0735          std::list<map_entry<exact_tuple_type, action_queue_type> > exact_matches;
0736          std::list<map_entry<fuzzy_tuple_type, action_queue_type> > fuzzy_matches;
0737          std::list<map_entry<exact_tuple_type, int> >               args_to_calls;
0738 
0739          dynamic_vfunction()
0740             : dynamic_vfunction_progress<R>()
0741             , exact_matches()
0742             , fuzzy_matches()
0743             {}
0744 
0745          template <typename T>
0746          int calculate_calls_for_arguments(const T args) {
0747             int calls = 0;
0748             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0749                = args_to_calls.begin();
0750             for(; calls_it != args_to_calls.end(); calls_it++) {
0751                if(args == calls_it->key) {
0752                   calls += calls_it->val;
0753                }
0754             }
0755             return calls;
0756          }
0757 
0758          dynamic_vfunction_progress<R>& when(const matcher::Matcher<A0 >& a0, const matcher::Matcher<A1 >& a1, const matcher::Matcher<A2 >& a2, const matcher::Matcher<A3 >& a3, const matcher::Matcher<A4 >& a4, const matcher::Matcher<A5 >& a5)
0759          {
0760             const fuzzy_tuple_type args = fuzzy_tuple_type(a0, a1, a2, a3, a4, a5);
0761             typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator match
0762                = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0763             if(match == fuzzy_matches.end())
0764             {
0765                fuzzy_matches.push_back(map_entry<fuzzy_tuple_type, action_queue_type>(args, action_queue_type()));
0766                match = --fuzzy_matches.end();
0767             }
0768             this->calls = calculate_calls_for_arguments(args);
0769             this->stubbing_progress = &(match->val);
0770             return *this;
0771          }
0772 
0773          dynamic_vfunction_progress<R>& when(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
0774          {
0775             const exact_tuple_type args = exact_tuple_type(a0, a1, a2, a3, a4, a5);
0776             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator match
0777                = std::find(exact_matches.begin(), exact_matches.end(), args);
0778             if(match == exact_matches.end())
0779             {
0780                exact_matches.push_back(map_entry<exact_tuple_type, action_queue_type>(args, action_queue_type()));
0781                match = --exact_matches.end();
0782             }
0783             this->calls = calculate_calls_for_arguments(args);
0784             this->stubbing_progress = &(match->val);
0785             return *this;
0786          }
0787 
0788          R invoke(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
0789          {
0790             const exact_tuple_type args = exact_tuple_type(a0, a1, a2, a3, a4, a5);
0791 
0792             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0793                = std::find(args_to_calls.begin(), args_to_calls.end(), args);
0794             if(calls_it == args_to_calls.end()) {
0795                args_to_calls.push_back(map_entry<exact_tuple_type, int>(args, 1));
0796             } else {
0797                (calls_it->val)++;
0798             }
0799 
0800             action_queue_type* actions = 0;
0801             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator exact_match
0802                = std::find(exact_matches.begin(), exact_matches.end(), args);
0803             if(exact_match != exact_matches.end())
0804                { actions = &(exact_match->val); }
0805             if(!actions)
0806             {
0807                typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator fuzzy_match
0808                   = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0809                if(fuzzy_match == fuzzy_matches.end())
0810                    { throw partial_implementation_exception(); }
0811                actions = &(fuzzy_match->val);
0812             }
0813             action_type action = actions->front();
0814             if(actions->size() > 1)
0815                { actions->pop_front(); }
0816             return action->invoke();
0817          }
0818       };
0819  
0820       // 7 arity template
0821       template <typename R, typename C, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
0822       struct dynamic_vfunction<R (C::*)(A0, A1, A2, A3, A4, A5, A6)> : private dynamic_vfunction_progress<R>
0823       {
0824          typedef tr1::tuple<A0, A1, A2, A3, A4, A5, A6> exact_tuple_type;
0825          typedef tr1::tuple<matcher_element<A0 >, matcher_element<A1 >, matcher_element<A2 >, matcher_element<A3 >, matcher_element<A4 >, matcher_element<A5 >, matcher_element<A6 > > fuzzy_tuple_type;
0826 
0827          typedef typename dynamic_vfunction_progress<R>::action_type       action_type;
0828          typedef typename dynamic_vfunction_progress<R>::action_queue_type action_queue_type;
0829 
0830          std::list<map_entry<exact_tuple_type, action_queue_type> > exact_matches;
0831          std::list<map_entry<fuzzy_tuple_type, action_queue_type> > fuzzy_matches;
0832          std::list<map_entry<exact_tuple_type, int> >               args_to_calls;
0833 
0834          dynamic_vfunction()
0835             : dynamic_vfunction_progress<R>()
0836             , exact_matches()
0837             , fuzzy_matches()
0838             {}
0839 
0840          template <typename T>
0841          int calculate_calls_for_arguments(const T args) {
0842             int calls = 0;
0843             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0844                = args_to_calls.begin();
0845             for(; calls_it != args_to_calls.end(); calls_it++) {
0846                if(args == calls_it->key) {
0847                   calls += calls_it->val;
0848                }
0849             }
0850             return calls;
0851          }
0852 
0853          dynamic_vfunction_progress<R>& when(const matcher::Matcher<A0 >& a0, const matcher::Matcher<A1 >& a1, const matcher::Matcher<A2 >& a2, const matcher::Matcher<A3 >& a3, const matcher::Matcher<A4 >& a4, const matcher::Matcher<A5 >& a5, const matcher::Matcher<A6 >& a6)
0854          {
0855             const fuzzy_tuple_type args = fuzzy_tuple_type(a0, a1, a2, a3, a4, a5, a6);
0856             typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator match
0857                = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0858             if(match == fuzzy_matches.end())
0859             {
0860                fuzzy_matches.push_back(map_entry<fuzzy_tuple_type, action_queue_type>(args, action_queue_type()));
0861                match = --fuzzy_matches.end();
0862             }
0863             this->calls = calculate_calls_for_arguments(args);
0864             this->stubbing_progress = &(match->val);
0865             return *this;
0866          }
0867 
0868          dynamic_vfunction_progress<R>& when(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
0869          {
0870             const exact_tuple_type args = exact_tuple_type(a0, a1, a2, a3, a4, a5, a6);
0871             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator match
0872                = std::find(exact_matches.begin(), exact_matches.end(), args);
0873             if(match == exact_matches.end())
0874             {
0875                exact_matches.push_back(map_entry<exact_tuple_type, action_queue_type>(args, action_queue_type()));
0876                match = --exact_matches.end();
0877             }
0878             this->calls = calculate_calls_for_arguments(args);
0879             this->stubbing_progress = &(match->val);
0880             return *this;
0881          }
0882 
0883          R invoke(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
0884          {
0885             const exact_tuple_type args = exact_tuple_type(a0, a1, a2, a3, a4, a5, a6);
0886 
0887             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0888                = std::find(args_to_calls.begin(), args_to_calls.end(), args);
0889             if(calls_it == args_to_calls.end()) {
0890                args_to_calls.push_back(map_entry<exact_tuple_type, int>(args, 1));
0891             } else {
0892                (calls_it->val)++;
0893             }
0894 
0895             action_queue_type* actions = 0;
0896             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator exact_match
0897                = std::find(exact_matches.begin(), exact_matches.end(), args);
0898             if(exact_match != exact_matches.end())
0899                { actions = &(exact_match->val); }
0900             if(!actions)
0901             {
0902                typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator fuzzy_match
0903                   = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0904                if(fuzzy_match == fuzzy_matches.end())
0905                    { throw partial_implementation_exception(); }
0906                actions = &(fuzzy_match->val);
0907             }
0908             action_type action = actions->front();
0909             if(actions->size() > 1)
0910                { actions->pop_front(); }
0911             return action->invoke();
0912          }
0913       };
0914  
0915       // 8 arity template
0916       template <typename R, typename C, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
0917       struct dynamic_vfunction<R (C::*)(A0, A1, A2, A3, A4, A5, A6, A7)> : private dynamic_vfunction_progress<R>
0918       {
0919          typedef tr1::tuple<A0, A1, A2, A3, A4, A5, A6, A7> exact_tuple_type;
0920          typedef tr1::tuple<matcher_element<A0 >, matcher_element<A1 >, matcher_element<A2 >, matcher_element<A3 >, matcher_element<A4 >, matcher_element<A5 >, matcher_element<A6 >, matcher_element<A7 > > fuzzy_tuple_type;
0921 
0922          typedef typename dynamic_vfunction_progress<R>::action_type       action_type;
0923          typedef typename dynamic_vfunction_progress<R>::action_queue_type action_queue_type;
0924 
0925          std::list<map_entry<exact_tuple_type, action_queue_type> > exact_matches;
0926          std::list<map_entry<fuzzy_tuple_type, action_queue_type> > fuzzy_matches;
0927          std::list<map_entry<exact_tuple_type, int> >               args_to_calls;
0928 
0929          dynamic_vfunction()
0930             : dynamic_vfunction_progress<R>()
0931             , exact_matches()
0932             , fuzzy_matches()
0933             {}
0934 
0935          template <typename T>
0936          int calculate_calls_for_arguments(const T args) {
0937             int calls = 0;
0938             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0939                = args_to_calls.begin();
0940             for(; calls_it != args_to_calls.end(); calls_it++) {
0941                if(args == calls_it->key) {
0942                   calls += calls_it->val;
0943                }
0944             }
0945             return calls;
0946          }
0947 
0948          dynamic_vfunction_progress<R>& when(const matcher::Matcher<A0 >& a0, const matcher::Matcher<A1 >& a1, const matcher::Matcher<A2 >& a2, const matcher::Matcher<A3 >& a3, const matcher::Matcher<A4 >& a4, const matcher::Matcher<A5 >& a5, const matcher::Matcher<A6 >& a6, const matcher::Matcher<A7 >& a7)
0949          {
0950             const fuzzy_tuple_type args = fuzzy_tuple_type(a0, a1, a2, a3, a4, a5, a6, a7);
0951             typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator match
0952                = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0953             if(match == fuzzy_matches.end())
0954             {
0955                fuzzy_matches.push_back(map_entry<fuzzy_tuple_type, action_queue_type>(args, action_queue_type()));
0956                match = --fuzzy_matches.end();
0957             }
0958             this->calls = calculate_calls_for_arguments(args);
0959             this->stubbing_progress = &(match->val);
0960             return *this;
0961          }
0962 
0963          dynamic_vfunction_progress<R>& when(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
0964          {
0965             const exact_tuple_type args = exact_tuple_type(a0, a1, a2, a3, a4, a5, a6, a7);
0966             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator match
0967                = std::find(exact_matches.begin(), exact_matches.end(), args);
0968             if(match == exact_matches.end())
0969             {
0970                exact_matches.push_back(map_entry<exact_tuple_type, action_queue_type>(args, action_queue_type()));
0971                match = --exact_matches.end();
0972             }
0973             this->calls = calculate_calls_for_arguments(args);
0974             this->stubbing_progress = &(match->val);
0975             return *this;
0976          }
0977 
0978          R invoke(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
0979          {
0980             const exact_tuple_type args = exact_tuple_type(a0, a1, a2, a3, a4, a5, a6, a7);
0981 
0982             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
0983                = std::find(args_to_calls.begin(), args_to_calls.end(), args);
0984             if(calls_it == args_to_calls.end()) {
0985                args_to_calls.push_back(map_entry<exact_tuple_type, int>(args, 1));
0986             } else {
0987                (calls_it->val)++;
0988             }
0989 
0990             action_queue_type* actions = 0;
0991             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator exact_match
0992                = std::find(exact_matches.begin(), exact_matches.end(), args);
0993             if(exact_match != exact_matches.end())
0994                { actions = &(exact_match->val); }
0995             if(!actions)
0996             {
0997                typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator fuzzy_match
0998                   = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
0999                if(fuzzy_match == fuzzy_matches.end())
1000                    { throw partial_implementation_exception(); }
1001                actions = &(fuzzy_match->val);
1002             }
1003             action_type action = actions->front();
1004             if(actions->size() > 1)
1005                { actions->pop_front(); }
1006             return action->invoke();
1007          }
1008       };
1009  
1010       // 9 arity template
1011       template <typename R, typename C, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
1012       struct dynamic_vfunction<R (C::*)(A0, A1, A2, A3, A4, A5, A6, A7, A8)> : private dynamic_vfunction_progress<R>
1013       {
1014          typedef tr1::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8> exact_tuple_type;
1015          typedef tr1::tuple<matcher_element<A0 >, matcher_element<A1 >, matcher_element<A2 >, matcher_element<A3 >, matcher_element<A4 >, matcher_element<A5 >, matcher_element<A6 >, matcher_element<A7 >, matcher_element<A8 > > fuzzy_tuple_type;
1016 
1017          typedef typename dynamic_vfunction_progress<R>::action_type       action_type;
1018          typedef typename dynamic_vfunction_progress<R>::action_queue_type action_queue_type;
1019 
1020          std::list<map_entry<exact_tuple_type, action_queue_type> > exact_matches;
1021          std::list<map_entry<fuzzy_tuple_type, action_queue_type> > fuzzy_matches;
1022          std::list<map_entry<exact_tuple_type, int> >               args_to_calls;
1023 
1024          dynamic_vfunction()
1025             : dynamic_vfunction_progress<R>()
1026             , exact_matches()
1027             , fuzzy_matches()
1028             {}
1029 
1030          template <typename T>
1031          int calculate_calls_for_arguments(const T args) {
1032             int calls = 0;
1033             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
1034                = args_to_calls.begin();
1035             for(; calls_it != args_to_calls.end(); calls_it++) {
1036                if(args == calls_it->key) {
1037                   calls += calls_it->val;
1038                }
1039             }
1040             return calls;
1041          }
1042 
1043          dynamic_vfunction_progress<R>& when(const matcher::Matcher<A0 >& a0, const matcher::Matcher<A1 >& a1, const matcher::Matcher<A2 >& a2, const matcher::Matcher<A3 >& a3, const matcher::Matcher<A4 >& a4, const matcher::Matcher<A5 >& a5, const matcher::Matcher<A6 >& a6, const matcher::Matcher<A7 >& a7, const matcher::Matcher<A8 >& a8)
1044          {
1045             const fuzzy_tuple_type args = fuzzy_tuple_type(a0, a1, a2, a3, a4, a5, a6, a7, a8);
1046             typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator match
1047                = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
1048             if(match == fuzzy_matches.end())
1049             {
1050                fuzzy_matches.push_back(map_entry<fuzzy_tuple_type, action_queue_type>(args, action_queue_type()));
1051                match = --fuzzy_matches.end();
1052             }
1053             this->calls = calculate_calls_for_arguments(args);
1054             this->stubbing_progress = &(match->val);
1055             return *this;
1056          }
1057 
1058          dynamic_vfunction_progress<R>& when(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
1059          {
1060             const exact_tuple_type args = exact_tuple_type(a0, a1, a2, a3, a4, a5, a6, a7, a8);
1061             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator match
1062                = std::find(exact_matches.begin(), exact_matches.end(), args);
1063             if(match == exact_matches.end())
1064             {
1065                exact_matches.push_back(map_entry<exact_tuple_type, action_queue_type>(args, action_queue_type()));
1066                match = --exact_matches.end();
1067             }
1068             this->calls = calculate_calls_for_arguments(args);
1069             this->stubbing_progress = &(match->val);
1070             return *this;
1071          }
1072 
1073          R invoke(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
1074          {
1075             const exact_tuple_type args = exact_tuple_type(a0, a1, a2, a3, a4, a5, a6, a7, a8);
1076 
1077             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
1078                = std::find(args_to_calls.begin(), args_to_calls.end(), args);
1079             if(calls_it == args_to_calls.end()) {
1080                args_to_calls.push_back(map_entry<exact_tuple_type, int>(args, 1));
1081             } else {
1082                (calls_it->val)++;
1083             }
1084 
1085             action_queue_type* actions = 0;
1086             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator exact_match
1087                = std::find(exact_matches.begin(), exact_matches.end(), args);
1088             if(exact_match != exact_matches.end())
1089                { actions = &(exact_match->val); }
1090             if(!actions)
1091             {
1092                typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator fuzzy_match
1093                   = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
1094                if(fuzzy_match == fuzzy_matches.end())
1095                    { throw partial_implementation_exception(); }
1096                actions = &(fuzzy_match->val);
1097             }
1098             action_type action = actions->front();
1099             if(actions->size() > 1)
1100                { actions->pop_front(); }
1101             return action->invoke();
1102          }
1103       };
1104  
1105       // 10 arity template
1106       template <typename R, typename C, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
1107       struct dynamic_vfunction<R (C::*)(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)> : private dynamic_vfunction_progress<R>
1108       {
1109          typedef tr1::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8, A9> exact_tuple_type;
1110          typedef tr1::tuple<matcher_element<A0 >, matcher_element<A1 >, matcher_element<A2 >, matcher_element<A3 >, matcher_element<A4 >, matcher_element<A5 >, matcher_element<A6 >, matcher_element<A7 >, matcher_element<A8 >, matcher_element<A9 > > fuzzy_tuple_type;
1111 
1112          typedef typename dynamic_vfunction_progress<R>::action_type       action_type;
1113          typedef typename dynamic_vfunction_progress<R>::action_queue_type action_queue_type;
1114 
1115          std::list<map_entry<exact_tuple_type, action_queue_type> > exact_matches;
1116          std::list<map_entry<fuzzy_tuple_type, action_queue_type> > fuzzy_matches;
1117          std::list<map_entry<exact_tuple_type, int> >               args_to_calls;
1118 
1119          dynamic_vfunction()
1120             : dynamic_vfunction_progress<R>()
1121             , exact_matches()
1122             , fuzzy_matches()
1123             {}
1124 
1125          template <typename T>
1126          int calculate_calls_for_arguments(const T args) {
1127             int calls = 0;
1128             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
1129                = args_to_calls.begin();
1130             for(; calls_it != args_to_calls.end(); calls_it++) {
1131                if(args == calls_it->key) {
1132                   calls += calls_it->val;
1133                }
1134             }
1135             return calls;
1136          }
1137 
1138          dynamic_vfunction_progress<R>& when(const matcher::Matcher<A0 >& a0, const matcher::Matcher<A1 >& a1, const matcher::Matcher<A2 >& a2, const matcher::Matcher<A3 >& a3, const matcher::Matcher<A4 >& a4, const matcher::Matcher<A5 >& a5, const matcher::Matcher<A6 >& a6, const matcher::Matcher<A7 >& a7, const matcher::Matcher<A8 >& a8, const matcher::Matcher<A9 >& a9)
1139          {
1140             const fuzzy_tuple_type args = fuzzy_tuple_type(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
1141             typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator match
1142                = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
1143             if(match == fuzzy_matches.end())
1144             {
1145                fuzzy_matches.push_back(map_entry<fuzzy_tuple_type, action_queue_type>(args, action_queue_type()));
1146                match = --fuzzy_matches.end();
1147             }
1148             this->calls = calculate_calls_for_arguments(args);
1149             this->stubbing_progress = &(match->val);
1150             return *this;
1151          }
1152 
1153          dynamic_vfunction_progress<R>& when(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
1154          {
1155             const exact_tuple_type args = exact_tuple_type(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
1156             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator match
1157                = std::find(exact_matches.begin(), exact_matches.end(), args);
1158             if(match == exact_matches.end())
1159             {
1160                exact_matches.push_back(map_entry<exact_tuple_type, action_queue_type>(args, action_queue_type()));
1161                match = --exact_matches.end();
1162             }
1163             this->calls = calculate_calls_for_arguments(args);
1164             this->stubbing_progress = &(match->val);
1165             return *this;
1166          }
1167 
1168          R invoke(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
1169          {
1170             const exact_tuple_type args = exact_tuple_type(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
1171 
1172             typename std::list<map_entry<exact_tuple_type, int> >::iterator calls_it
1173                = std::find(args_to_calls.begin(), args_to_calls.end(), args);
1174             if(calls_it == args_to_calls.end()) {
1175                args_to_calls.push_back(map_entry<exact_tuple_type, int>(args, 1));
1176             } else {
1177                (calls_it->val)++;
1178             }
1179 
1180             action_queue_type* actions = 0;
1181             typename std::list<map_entry<exact_tuple_type, action_queue_type> >::iterator exact_match
1182                = std::find(exact_matches.begin(), exact_matches.end(), args);
1183             if(exact_match != exact_matches.end())
1184                { actions = &(exact_match->val); }
1185             if(!actions)
1186             {
1187                typename std::list<map_entry<fuzzy_tuple_type, action_queue_type> >::iterator fuzzy_match
1188                   = std::find(fuzzy_matches.begin(), fuzzy_matches.end(), args);
1189                if(fuzzy_match == fuzzy_matches.end())
1190                    { throw partial_implementation_exception(); }
1191                actions = &(fuzzy_match->val);
1192             }
1193             action_type action = actions->front();
1194             if(actions->size() > 1)
1195                { actions->pop_front(); }
1196             return action->invoke();
1197          }
1198       };
1199    } // namespace detail
1200 } // namespace mockitopp
1201 
1202 #endif //__MOCKITOPP_DYNAMIC_VFUNCTION_HPP__