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__