MeyersãšAlexandrescuã¯é·ãéããã«ãã¡ãœãããšã©ã€ãã©ãªå®è£ ã®ããã€ãã®ã¢ãããŒãã«ã€ããŠæžããŠããŸããã ã»ãŒ20幎éããããã®ã¢ã€ãã¢ã¯C ++ã«é¢ããããŸããŸãªæç®ã§è°è«ãããŠããŸãããããããŸã§ã®ãšãããå®éã®ãããžã§ã¯ãã§äŸ¿å©ã«äœ¿çšã§ããå®å šãªãœãªã¥ãŒã·ã§ã³ãŸã§éçºãããŠããŸãã...
ç§ã¯éã詊ãããããŠãã®åé¡ã«å¯Ÿããç§ã®ããžã§ã³ãšããã解決ããæ¹æ³ãæäŸããããšã«ããŸããã ãã®çµæãããããŒã®ã¿ã®ãã³ãã¬ãŒãã©ã€ãã©ãªãäœæãããŸããã
ããã¯ãçŽç²ãªC ++ã§ã®C ++ 03æšæºã®äžã§ã®å®è£ ã§ããã³ãŒããžã§ãã¬ãŒã¿ãŒã远å ã¯ãããŸããã ç®æšã¯ãå®è¡æã«ã¿ã€ãïŒããã³å€ã«ãã£ãŠãïŒã§é¢æ°ããªãŒããŒããŒãããæ©èœãå®çŸããããã®ã·ã³ãã«ã§çŽæçãªã€ã³ã¿ãŒãã§ã€ã¹ãåããã©ã€ãã©ãªã§ãïŒæå°éã®ããã°ã©ã ã§ããã
ãã¹ããã©ã€ãã®å Žåã¯ã ãœãŒã¹ãããŠã³ããŒãããïŒincludeãããã€ãäœæããå¿ èŠããããŸãã
ãã¬ãŒã³ããŒã·ã§ã³ã¯åçŽãªãã®ããè€éãªãã®ãŸã§éžæããŸããã ãããã£ãŠããã®èšäºã§ã¯ãã©ã€ãã©ãªã䜿çšããæãç°¡åãªæ¹æ³ã«ã€ããŠèª¬æããŸããããããŸã§ã®ãšãããå®è£ ææ³ã«ã€ããŠã¯èª¬æããŸããã
ãã«ãã¡ãœãããšã¯äœã§ããïŒ
å矩èªãããã€ããããŸãïŒè€æ°ã®ãã£ã¹ããããã¿ã€ãã«ããè€æ°ã®åãæ¿ããå®è¡æã®é¢æ°ã®ãªãŒããŒããŒãã ãã®ãããã¯ã«é¢ããå€ãã®æ å ±ãã€ã³ã¿ãŒããããšæç®ã«ãããŸãããããã£ãŠãç§ã¯åãããšãã¯ãã¹ãã¹ãããŸããããããã€ãã®ãªã³ã¯ãæäŸããŸããè±èªãšãã·ã¢èªã®ãŠã£ãããã£ã¢ã
C ++ã§ãã«ãã¡ãœããã䜿çšããçç±
ãã®åé¡ãé瀺ããŸãããç§ã¯ããã«ãç®æšããã«ãã¡ãœãããå®è£ ãã詊ã¿ã§ãããC ++ã§å¿ èŠãã©ãããæ£åœåããæœè±¡çãªæšè«ã§ã¯ãªãããšããç¥ããããŸãã 誰ããå¿ èŠãšããŸããã誰ãã¯å¿ èŠãšããŸããã ã€ãã£ãªã ãããå Žåã誰ããããã奜ããã©ããã«é¢ä¿ãªããå®è£ ã«ã¯ååšããæš©å©ããããŸãã ä»ã®èšèªã«ã¯ãã®ãããªå®è£ ããããããèšèªãŸãã¯ã©ã€ãã©ãªã®äžéšã§ããªãC ++ãæªãã®ã§ããïŒ
ãšããã§ãC ++ã¯ãã€ãèšèªåŽããã®ãã«ãã¡ãœããããµããŒããããããããŸããã BjörnStraustrupã®ãªãã¡ãŒã§ã ã 以åã¯ã誰ããC ++ 0xãšãã£ã·ã§ã³ã«ç»å ŽããããšãæåŸ ããŠããŸãããããããŸã§ã®ãšããããã®ææ¡ã¯é©åã«è§£æ±ºãããŠããŸããã
èªåãã远å ã§ããŸãã Straustrupã¯ãå¯èœã§ããã°ãå éšã¡ã³ããŒã¡ãœããã®ä»£ããã«ããã®ãããªé¢æ°ãã¯ã©ã¹ã®ãããªãã¯ã€ã³ã¿ãŒãã§ã€ã¹ã«ååãªå Žåããã®é¢æ°ãåªå ããããšããå§ãããŸãã ãããã颿°ãå€çžåŒæ°ãåŠçããå¿ èŠãããå Žåã¯ã©ãã§ããããïŒ éå±€å šäœïŒãŸãã¯ãã®äžéšïŒã«æµžéããæ°ããä»®æ³ã¡ãœããã远å ããå¿ èŠããããã³ã ããã¯ãããŒã¿ãšã¡ãœããã®ç·å¯ãªæ¥ç¶ã®æ©èœã§ãã ãã«ãã¡ãœããã䜿çšãããšããã®äŸåé¢ä¿ãåé¿ã§ããã¯ã©ã¹éå±€ã«å¹²æžããããšãªãæ©èœãæ¡åŒµã§ããŸãã ã€ãŸããå éšä»®æ³ã¡ãœããã䜿çšããã«ãå€éšä»®æ³ã¡ãœãããäœæã§ããŸãã1ã€ããã§ã¯ãªããè€æ°ã®å€æ çãªåŒæ°ããäœæã§ããŸãã äžè¬çã«ãã¢ããªã±ãŒã·ã§ã³éšåã¯éåžžã«åºãã§ãã
ã¡ãã£ãšããæŽå²
2009幎ã«ãC ++ãšèšèšææ³ãç ç©¶ããéçšã§ããGangs of Fourãã ãMethods of Object-Oriented Design ããšããæ¬ããåããŠãã«ãã¡ãœããã«ã€ããŠåŠã³ãŸããã ãã¶ã€ã³ãã¿ãŒã³ãã蚪åè ãã»ã¯ã·ã§ã³ã ãã®ãšããC ++ã®ãã«ãã¡ãœããã®å®è£ ã䜿çšããããšã«é¢ããŠå¥å šã§åçŽãªãã®ã¯ãªããšããã®ã¯ãç§ã«ãšã£ãŠå¥åŠã«æããŸããã ãããã¿ã€ããã¹ã±ããããè¶£å³ãšããŠèªç±æéã«éçºããŸããïŒã»ãŒå®å šã«æ°åæžãçŽããŸããïŒã Alexandrescuãèªããšã圌ã¯è€æ°ã®æ¹æ³ã§ãã«ãã¡ãœãããå®è£ ããŠããããšãããããŸããã ãããããããã¯éåžžã«éå®çã§äœ¿çšãå°é£ã§ããããšã倿ããå Žåã«ãã£ãŠã¯ãŸã£ããæ©èœããŸãããããã¯åœŒã®æ¬ã®ã¡ã¿ããã°ã©ãã³ã°ã®äŸã«ãããŸããã ãŸããæ¥é èŸãmultiãã¯ç¡æå³ã§ãããã®å®è£ ã¯ã2ã€ã®åŒæ°ã®é¢æ°ã«å¯ŸããŠã®ã¿æ©èœããŸãã ããã«ããã€ãã®ã¿ã€ãã®å®è£ ãèŠã€ããŸããããã¹ã±ãžã¥ãŒãªã³ã°ããµããŒãããããã«ã³ãŒããžã§ãã¬ãŒã¿ãŒãŸãã¯æåã³ãŒãã®äœæãšéå±€ã®å€§å¹ ãªå€æŽãå¿ èŠã§ããã ããã¯ãã¹ãŠéåžžã«è€éã§ãããããC ++ã§ãã«ãã¡ãœããã䜿çšããå¿ èŠã¯ãããŸããã ã€ã³ã¿ãŒãã§ã€ã¹ãéåžžã«åçŽãªåœ¢åŒã§æç€ºããããã©ãŒãã³ã¹ã蚱容ã§ããå®è£ ãæäŸããããšã§ããããã®åé¡ãåãé€ãæ¹æ³ãèŠã€ããããšãã§ããŸããã ä»åŸããã«ãã¡ãœãããäœæããæãç°¡åãªæ¹æ³ã®1ã€ïŒããã³ã©ã€ãã©ãªã«ã¯ãã¢ã«ãŽãªãºã ã®åäœã«é¢ããæ¢è£œã®ããªã·ãŒãŸãã¯ç¬èªã®ããªã·ãŒã䜿çšããŠãåçŽãªãã®ããæåã§åŸ®èª¿æŽããæ¹æ³ãŸã§ãå€ãã®æ¹æ³ãçšæãããŠããŸãïŒïŒmml::make_multimethod(f1, f2,..., fn)
f1ãf2ã...ãfnã¯ãåçã«ãªããŒãããïŒã€ãŸããããããããã«ãã¡ãœãããã¢ã»ã³ãã«ããïŒå¿ èŠããã颿°ãŸãã¯åŒã³åºãå¯èœãªããžã§ã¯ãã®ååã§ãã åŒæ°ã«è¿œå ã®èŠä»¶ã¯ãããŸãããmake_multimethodã¯ãããã©ã«ããã©ã¡ãŒã¿ã§èšå®ããããã«ãã¡ãœããïŒåçã«ãªãŒããŒããŒãããã颿°ïŒã衚ã颿°ãªããžã§ã¯ããè¿ããŸãã ããã¯ãã©ã€ãã©ãªãŠãŒã¶ãŒãå ¥åããããã®äœããããå€ã§ããã远å ã®ç¥èã¯å¿ èŠãããŸããã
çµæãšããŠããããããŸãšããªã©ã€ãã©ãªãŒã圢æãããŸãããç§ã¯ãããtriteïŒ MML-MultiMethod LibraryãšåŒã³ãŸããã 圌女ãå ãèŠãæãæ¥ãŸãããããããã圌女ã¯èª°ãã«åœ¹ç«ã€ã§ãããã ã»ãŒ3幎éã«ããã£ãŠãC ++ã§ã®ãã«ãã¡ãœããã®ç¶æ³ã¯ã©ãã«ãç§»åããŠããŸããïŒç§èŠãç§ã¯äœããç¥ããªãã ããããããŸããïŒã
åé¡ã®å£°æ
ãã«ãã¡ãœããããã¹ãããšã¯çè§£ã§ããŸãã ãããã圌ã¯ãããã©ã®ããã«è¡ãå¿ èŠãããããããŠéèŠãªããšã«ãããã¯ã©ã®ããã«èŠããã®ã§ããããïŒ äž»ãªç®çãã€ãŸãå®è¡æã®ãªãŒããŒããŒããåºã«æ§ç¯ããŸã ã ãªããžã§ã¯ãæåã®ãªãŒããŒããŒããšã¯äœã§ããïŒ äžè¬çã«ãC ++ã§ã®ã³ã³ãã€ã«äžã®é¢æ°ã®ãªãŒããŒããŒãã¯ã©ã®ããã«èŠããŸããïŒ åæããŸãããããªãŒããŒããŒãã«ãŒã«ã®è©³çްïŒç¶æ¿ã䜿çšå®£èšãKoenigã®æ€çŽ¢ãªã©ïŒããã¹ãŠèª¬æããããšãªããç°¡åãªäŸãèããŠã¿ãŸãããã
void f(int){} void f(double){} void f(char, void*){}
颿°åfã¯ãåŒæ°ã®ã¿ã€ããšãã®æ°ã«ãã£ãŠ3åãªãŒããŒããŒããããããšãããããŸãã 颿°ã®ãªãŒããŒããŒãã¯O ++ã®å©ç¹ãšããŠC ++ã«ç»å Žãããšããäºå®ïŒCã«ã¯ãªãŒããŒããŒãã¯ãããŸããïŒã«ããããããããã®åœ¢åŒã¯ãªããžã§ã¯ãæåã®ãããªåãã¯ããŸããã ããã3ã€ã®é¢æ°ã¯æé»çã«æ¥ç¶ãããŠããŸããããã«ãååã®äžèŽã«ãããããªãŒããŒããŒãããã颿°ããšããçšèªã¯å šäœãšããŠãã®äŸã«ã¯åœãŠã¯ãŸããŸããã ããšãã°ããã®ã»ããã倿°ã«å®å šã«ä¿åããããäœããã®é¢æ°ã«æž¡ããŠãåŸã§ãªãŒããŒããŒãã䜿çšããŠåŒã³åºããè¡ããŸãã
auto of = f; // f
ãã®èšèªã«ã¯ããªãŒããŒããŒãããã颿°ã®ã»ãããåäžã®ãªããžã§ã¯ãã«çµåããææ®µããããŸããã ãã®åœ¢åŒã®ãªãŒããŒããŒãã¯ã«ãã»ã«åãæåŠããŸãã
ãªããžã§ã¯ãæåã®ä»£æ¿æ¡ãæ€èšããŠãã ããã
struct f { void operator()(int) const {} void operator()(double) const {} void operator()(char, void*) const {} }; auto of = f(); // , of ,
ãã¹ãŠã®é¢æ°ããã¡ã³ã¯ã¿ãŒïŒé¢æ°ãªããžã§ã¯ãïŒãšããŠããè¯ãèšèšããããšæããããããŸããã ããã¯ãããšãã°ããã¹ãŠã®ã¿ã¹ã¯ã«å¯ŸããŠã§ã¯ãªããæšæºã¢ã«ãŽãªãºã ãªã©ã«è¿°èªãæž¡ããšãã«ã€ã³ã©ã€ã³åã®å©ç¹ãåŸãããã«æ£åœåãããå Žåã®åžžèã§ãã éåžžã®å€ãè¯ã颿°ã§ã¯ãªãããã¡ã³ã¯ã¿ãŒã®äžåœãªã¹ãã«ã¯ãäžäŸ¿ã§æéãããããäžéšã®ã¿ã¹ã¯ã§ã¯åãå ¥ããããªã解決çã«ããªããŸãã
ãã®ããããªããžã§ã¯ãæåã®ã¹ã¿ã€ã«ã§ã¯ããªãŒããŒããŒãããã颿°ã¯ãæŒç®åïŒïŒããªãŒããŒããŒãããããã¡ã³ã¯ã¿ãŒïŒé¢æ°åãªããžã§ã¯ãïŒã§ãã MMLã©ã€ãã©ãªã«ã¯ãå€ãã®åå¥ã®åŒã³åºãå¯èœãšã³ãã£ãã£ïŒãããã¯ãã¡ã³ã¯ã¿ãã©ã ããããã³éåžžã®é¢æ°ãžã®ãã€ã³ã¿ïŒãã©ããããããããã«å¯ŸããŠãªãŒããŒããŒããããoperatorïŒïŒãè¡šãæ¢è£œã®äŸ¿å©ãªãã³ãã¬ãŒãããããŸãã ããã¯ãªããžã§ã¯ãoverloaded_function <F1ã... Fn>ãšé¢æ°make_overloaded_functionïŒf1ã...ãfnïŒã§ãããåŒæ°ã®åãä»ããŠãã³ãã¬ãŒãã®ãã©ã¡ãŒã¿ãŒã衚瀺ããŠãªããžã§ã¯ããäœæããŸãã
overloaded_functionã¯ãã³ã³ãã€ã«æã«æŒç®åïŒïŒã䜿çšããŠåŒã³åºãããšãã§ãããªãŒããŒããŒã颿°ã§ãããšã³ãã£ãã£ã§ãã åãçç±ã§ããã«ãã¡ãœããã€ã³ã¿ãŒãã§ã€ã¹ãèšèšãããšãã¯å ã«é²ãå¿ èŠããããŸãã ã€ãŸã å€éšçã«ã¯ãªãŒããŒããŒãããããã¡ã³ã¯ã¿ã®ããã«èŠããåŒã³åºãå¯èœãªãšã³ãã£ãã£ã§ããå¿ èŠããããŸãããã³ã³ãã€ã«æã«äžæãªå®éã®åçãªåã®ãã©ã¡ãŒã¿ã«å¿ããŠå®è¡æã«ãªãŒããŒããŒããå®è¡ããŸãã ãã«ãã¡ãœããã¯ãªããžã§ã¯ãå€ã§ããå¿ èŠããããããèªäœã«å¿ èŠãªãã¹ãŠã®ããŒã¿ãå«ãŸããŠããå¿ èŠããããŸãã Assignableã®æŠå¿µããµããŒãããŸãã ãã®ãããªã€ã³ã¿ãŒãã§ãŒã¹ãšåäœã«ããããã«ãã¡ãœããã¯éåžžã®åŒã³åºããããšã³ãã£ãã£ã®ããã«èŠããSTLãããŒã¹ããããã³ç¹å¥ãªé©å¿ãªãã§å€ãã®STLé¡äŒŒã©ã€ãã©ãªããã³ãŠãŒã¶ãŒã³ãŒããšå¯Ÿè©±ã§ããŸãã
åèš æ¬¡ã®åé¡ã®ã¹ããŒãã¡ã³ããååŸããŸãïŒéçã«ïŒã³ã³ãã€ã«æã«ïŒãªãŒããŒããŒãããã颿°ã®ã»ãããå«ãåŒã³åºãå¯èœãªãšã³ãã£ãã£ãéçºããåŒã³åºãå¯èœãªã€ã³ã¿ãŒãã§ã€ã¹ãæäŸããå®è¡æã«ã»ããããç®çã®éç颿°ã«çä¿¡åŒã³åºãããã£ã¹ãããããŸãã
ææ¡ããããœãªã¥ãŒã·ã§ã³
ãã«ãã¡ãœããèªäœã«å ããŠãåé¡ã«å¯Ÿããæãäžè¬çãªãœãªã¥ãŒã·ã§ã³ã®ããã®ã¯ã©ã¹ãæŠç¥ãç¹æ§ã®ã¯ã©ã¹ããã¡ãµãŒããã¢ããã¿ãŒãããã³ãã®ä»ã®ãŠãŒãã£ãªãã£ã®ã»ãããååŸããããšãã§ããŸããã ãããããªããªã å ¥éèšäºã§ã¯ãä»ã®ãšããããã«ãã¡ãœããã䜿çšããæãç°¡åãªæ¹æ³ãããããäœãããå€ã«ã€ããŠèª¬æããŸãã ãããè¡ãããã«ãã¿ãŒã²ããã®åŒã³åºãå¯èœãšã³ãã£ãã£make_multimethodã®ã»ããã«åºã¥ããŠãã«ãã¡ãœãããã¡ãµãŒããšãããäœæãã颿°ãæºåããŸãã ã ã©ã€ãã©ãªã®ã³ã¢ã¯ãã£ã¹ãããã£ãã³ãã¬ãŒãã¯ã©ã¹ã§ãã詳现ã«ã€ããŠã¯æ¬¡ã®èšäºã§èª¬æããŸããããã¯æå€§éã«äžè¬åãããŠããããã«ãã¡ãœããã®å®è£ ã®ã¿ã«éå®ãããŸããããã«ãã¡ãœããã¯ãã£ã¹ãããã£ã®äœ¿çšãç°¡çŽ åãããã¡ãµãŒãã§ããããããååãªçç±ãããã®ã§ãã³ã¡ã³ãä»ãã®äŸã䜿çšããŠããããããã«åçŽããçè§£ããããšããå§ãããŸãã
ããšãã°ãåçŽãªéå±€ãå¿ èŠã§ãã ç§ã¯å€å žçãªäŸã䜿çšããŸãïŒå®å®è¹ãå°ææãå®å®ã¹ããŒã·ã§ã³ãè¡çªãããã²ãŒã ïŒ
éå±€
struct game_object { virtual ~game_object() { } }; struct space_ship : game_object { }; struct space_station : game_object { }; struct asteroid : game_object { };
䟿å®äžãã²ãŒã ãªããžã§ã¯ããžã®ããªã¢ãŒãã£ãã¯ãã€ã³ã¿ãŒã®é åãè¿ã颿°ïŒ
get_obj_pointersïŒïŒ
vector<game_object*>& get_obj_pointers() { static space_ship ship; static asteroid ast; static space_station station; static vector<game_object*> objs; if (objs.empty()) { objs.push_back(&ship); objs.push_back(&ast); objs.push_back(&station); } return objs; }
ã¿ãŒã²ããã®éçã«ãªãŒããŒããŒãããã颿°ã®ã»ããïŒ
const char* collide_go_go(game_object*, game_object*) { return "Unsupported colliding!"; } const char* collide_sh_sh(space_ship*, space_ship*) { return "Space ship collides with space ship"; } const char* collide_sh_as(space_ship*, asteroid*) { return "Space ship collides with asteroid"; } const char* collide_as_sh(asteroid*, space_ship*) { return "Asteroid collides with space ship"; } const char* collide_as_as(asteroid*, asteroid*) { return "Asteroid collides with asteroid"; }
ãªãŒããŒããŒããããŠãããã®ã¯ãããªããå°ããã圌ãã¯ç°ãªãååãæã£ãŠããŸãã ã¯ããäœæãååŸããããã®äŸ¿å®ã®ããã«ç°ãªããŸãã 誰ããæ¬åœã«å¿ èŠãªå Žåã¯ãåãååãä»ããããšãã§ããŸãã颿°ã®ã¢ãã¬ã¹ãååŸãããšãã«ããããŸããã解決ããå¿ èŠããããŸãã
æåã®éèŠãªãã€ã³ãã ãã«ãã¡ãœãããäœæããŸãïŒããããŒ<mml / generation / make_multimethod.hpp>ãæ¥ç¶ããå¿ èŠããããŸãïŒïŒ
#include <mml/generation/make_multimethod.hpp> auto collide = make_multimethod( collide_go_go , collide_sh_sh , collide_sh_as , collide_as_sh , collide_as_as );
ã§ããïŒ è¡çª-ãã«ãã¡ãœããããããŸãã autoã䜿çšããã«ãããã«çµæããã³ãã¬ãŒã颿°ã«æž¡ããboost :: function <const char *ïŒgame_object *ãgame_object *ïŒ> collide = ...ãå²ãåœãŠãããæç€ºçã«multimethodå<...>ãæå®ããŸãã ã¿ã€ããæç€ºçã«æå®ããããšã¯éåžžã«é£ãããèªåæŒautomaticã䜿çšããã®ãæåã§ãã ïŒboost | std | std :: tr1ïŒ::颿°ã«ã«ãã»ã«åãããšãç¹å®ã®ã±ãŒã¹ã§ã¯æ©èœãšããã©ãŒãã³ã¹ã®äžéšã倱ãããŸãïŒä»¥äžã®èª¬æäŸããããŸãïŒããäžè¬ã«ãã»ãšãã©ã®å Žåãåäœã¯åãã§ãã
2çªç®ã®éèŠãªãã€ã³ãã ãã«ãã¡ãœããã䜿çšããŸãã ç§ãã¡ã¯ãã¹ãŠã®ã²ãŒã ãªããžã§ã¯ãã«å¯Ÿã§çŽé¢ããŠããŸã
auto& objs = get_obj_pointers(); for (size_t i = 0; i < objs.size(); ++i) for (size_t j = 0; j < objs.size(); ++j) cout << '\t' << collide(objs[i], objs[j]) << endl;
ãããã«
Space ship collides with space ship Space ship collides with asteroid Asteroid collides with space ship Asteroid collides with asteroid
ã³ã³ãœãŒã«ãžã®åºåã¯ã誰ãå®éã«èª°ã«ééãããã瀺ããŸãã ã芧ã®ãšãããéå±€ã«ã¯ç¹å¥ãªãã£ã¹ããããµããŒãã¯å¿ èŠãããŸããã Multimethodã¯ããã©ã«ãã§dynamic_castã䜿çšããŠããªããžã§ã¯ãã®å®éã®åçã¿ã€ããèŠã€ããŸãã ãããã£ãŠãRTTIãµããŒããæå¹ã«ããŠã³ãŒããã³ã³ãã€ã«ããå¿ èŠããããŸãã
æå¹æ§ãè©äŸ¡ããããã«ãã³ã³ãã€ã«æã«ãcollideïŒobjs [i]ãobjs [j]ïŒã®åŒã³åºããšåããã·ã³ã³ãŒããäžããæ¬äŒŒã³ãŒããæäŸããŸãã
æ¬äŒŒã³ãŒã
inline const char* collide(game_object* obj1, game_object* obj2) { if (space_ship* sh1 = dynamic_cast<space_ship*>(obj1)) if (space_ship* sh2 = dynamic_cast<space_ship*>(obj2)) return collide_sh_sh(sh1, sh2); else if (asteroid* as2 = dynamic_cast<asteroid*>(obj2)) return collide_sh_as(sh1, as2); else return collide_go_go(sh1, obj2); else if (asteroid* as1 = dynamic_cast<asteroid*>(obj1)) if (space_ship* sh2 = dynamic_cast<space_ship*>(obj2)) return collide_as_sh(as1, sh2); else if (asteroid* as2 = dynamic_cast<asteroid*>(obj2)) return collide_as_as(as1, as2); else return collide_go_go(as1, obj2); else if (space_ship* sh2 = dynamic_cast<space_ship*>(obj2)) return collide_go_go(obj1, sh2); else if (asteroid* as2 = dynamic_cast<asteroid*>(obj2)) return collide_go_go(obj1, as2); else return collide_go_go(obj1, obj2); }
ã芧ã®ãšãããå®è¡æã®ãªãŒããŒãããã¯ãããã2åã®dynamic_castã§è¡šãããææªã®å Žåã¯4ã§ãã
ã©ã€ãã©ãªã¯ãããªã¢ãŒãã£ãã¯ãªããžã§ã¯ããžã®ãã€ã³ã¿ã§åäœããŸãïŒçµã¿èŸŒã¿ãããã³ã¹ããŒãã§ãŠãŒã¶ãŒå®çŸ©ã®ãªããžã§ã¯ãã䜿çšããŸãã ãªã³ã¯ãæäœããããã«ããã¡ãµãŒãref_multimethodãäœæããŸããïŒ<mml / generation / make_ref_multimethod.hpp>ã§å®è£ ïŒïŒ
倿 çãªãªããžã§ã¯ããžã®ãªã³ã¯ã®é åãäœæããããã®äŸ¿å©ãªãŠãŒãã£ãªãã£é¢æ°ïŒ
get_objs_refsïŒïŒ
boost::ptr_vector<game_object>& get_objs_refs() { static boost::ptr_vector<game_object> objs; if (objs.empty()) { objs.push_back(new space_ship); objs.push_back(new asteroid); objs.push_back(new space_station); } return objs; }
ãªã³ã¯ãåãåãã¿ãŒã²ãã颿°ïŒ
ãã€ã³ã¿ãŒãšåãã»ããããªã³ã¯ã®ã¿ãåãå
¥ãã
const char* collide_ref_go_go(game_object&, game_object&) { return "Unsupported colliding!"; } const char* collide_ref_sh_sh(space_ship&, space_ship&) { return "Space ship collides with space ship"; } const char* collide_ref_sh_as(space_ship&, asteroid&) { return "Space ship collides with asteroid"; } const char* collide_ref_as_sh(asteroid&, space_ship&) { return "Asteroid collides with space ship"; } const char* collide_ref_as_as(asteroid&, asteroid&) { return "Asteroid collides with asteroid"; }
ãªããžã§ã¯ãã®è¡çªã®åããµã€ã¯ã«ãç¹°ãè¿ããªãããã«ããã³ãã¬ãŒã颿°ã§ã©ããããŸããïŒ
template <typename F, typename Objs> void collide_tester(F collide, Objs& objs) { for (size_t i = 0; i < 2; ++i) for (size_t j = 0; j < 2; ++j) cout << '\t' << collide(objs[i], objs[j]) << endl; }
åç §ãã«ãã¡ãœãããäœæããŠäœ¿çšããŸãã
#include <mml/generation/make_ref_multimethod.hpp> collide_tester( make_ref_multimethod( collide_ref_go_go , collide_ref_sh_sh , collide_ref_sh_as , collide_ref_as_sh , collide_ref_as_as ) , get_objs_refs() );
ãããã«
Space ship collides with space ship Space ship collides with asteroid Asteroid collides with space ship Asteroid collides with asteroid
æéçã«åçã®æ¬äŒŒã³ãŒãã¯ããã€ã³ã¿ãŒã䜿çšããåã®äŸãšåãã§ãã
æ©èœãªããžã§ã¯ãã¯ãåã蟌ã¿ãç°¡åã§ãããšããç¹ã§ãã€ã³ã©ã€ã³é¢æ°ãžã®ãã€ã³ã¿ãŒãšæ¯èŒããŠæå©ã§ãããšæ¢ã«è¿°ã¹ãŸããã ããã ãã§ãªãããããã®ãªããžã§ã¯ãã®ã»ãšãã©ã«ã¯ããŒã¿ã¡ã³ãããªããããã©ã€ãã©ãªã®è žã§äœ¿çšãããããªãããŒãªç©ºã®ããŒã¹æé©åææ³ã䜿çšããŠãã³ã³ããã®ã¡ã¢ãªã«æ ŒçŽã§ããŸãã ãã¡ã³ã¯ã¿ãŒãšã®ãã«ãã¡ãœããçžäºäœçšã®äŸã次ã«ç€ºããŸãã
struct collider_sh_as { const char* operator()(space_ship*, asteroid*) const { return "Space ship collides with asteroid"; } }; collide_tester( make_multimethod( collide_go_go , collide_sh_sh , collider_sh_as() , collide_as_sh , collide_as_as ) , get_obj_pointers() );
ã芧ã®ãšããããã¡ã³ã¯ã¿ãŒã®äœ¿çšã¯çµã¿èŸŒã¿é¢æ°ã䜿çšããã®ãšåããããç°¡åã§ãã ãã ããåæã«ããã«ãã¡ãœããã®ãµã€ãºã¯å¹ ããã1ãã€ã³ã¿ãŒå°ãªããªããã©ã®ã³ã³ãã€ã©ãŒã§ãcollider_sh_as ::æŒç®åïŒïŒã®æ¬äœãåŒã³åºãå Žæã«ç°¡åã«åã蟌ãããšãã§ããŸãã
ã©ã€ãã©ãªã¯ãBOOST_TYPEOFïŒïŒcollider_sh_as :: operatorïŒïŒïŒãä»ããŠãã©ã¡ãŒã¿ã®ã¿ã€ããšåŒã³åºãæŒç®åã®æ»ãå€ã決å®ããŸãã ã³ã³ãã€ã©ãBOOST_TYPEOFããµããŒãããŠããªãå ŽåããŸãã¯BOOST_TYPEOFããµããŒãããããã«ã«ã¹ã¿ã ã¿ã€ããç»é²ããããªãå ŽåããŸãã¯ãããäœã§ããããç¥ããããªãå Žåã¯ãåæºããªãã§ãã ããã ãã©ã¡ãŒã¿ãŒã®ã¿ã€ããæç€ºçã«æå®ã§ããŸãããããã«ã¯ããã€ãã®äŸ¿å©ãªæ¹æ³ããããŸãã ã©ã€ãã©ãªãŒã¯ããã©ã¡ãŒã¿ãŒã®ã¿ã€ããšãã¡ã³ã¯ã¿ãŒïŒFïŒã®æ»ãå€ãå€å¥ããããã«ã次ã®ãããã³ã«ãå®è£ ããŸãã
- F ::眲åãä»ããŠãã¡ã³ã¯ã¿ãŒåããæ©èœåãååŸããããšããŸãã æ¬¡ã®ããã«å®çŸ©ããå¿
èŠããããŸãã
struct collider_sh_as { typedef const char* signature(space_ship*, asteroid*); ... }
- åã®typedefãæ¬ èœããŠããå ŽåãF :: result_typeãF :: arg1_typeãF :: arg2_typeã...ãF :: arg n _typeãä»ããŠãã¡ã³ã¯ã¿ãŒå
ã®åãèŠã€ããããšããŸãã
struct collider_sh_as { typedef const char* result_type; typedef space_ship* arg1_type; typedef asteroid* arg2_type; ... }
ãããã£ãŠããã®ãããªtypedefããšã¯ã¹ããŒãããboost ::颿°ã¯èªåçã«ãµããŒããããŸãã
- ååšããªãå ŽåãF :: result_typeãF :: argument_typeïŒåé
颿°ã®å ŽåïŒãF :: first_argument_typeãF :: second_argument_typeïŒãã€ããªé¢æ°ã®å ŽåïŒãä»ããŠåãèŠã€ããããšããŸãã
struct collider_sh_as { typedef const char* result_type; typedef space_ship* first_argument_type; typedef asteroid* second_argument_type; ... }
ãŸãã¯ãã¯ããã«äŸ¿å©ã§ãïŒ
struct collider_sh_as : std::binary_function<space_ship*, asteroid*, result_type> { ... }
ãããã£ãŠãstd :: unary_functionãstd :: binary_functionã¯èªåçã«ãµããŒããããŸãã
- åã®3ã€ã®ã¹ããããæ©èœããªãã£ãå ŽåãBOOST_TYPEOFã䜿çšãããŸãã 1ã€ã®éæšæºæŒç®åïŒïŒãæã€ãã¡ã³ã¯ã¿ãŒããµããŒããããŸãã ãããã£ãŠãstd ::颿°ããã³C ++ 11ã©ã ãããµããŒããããŸãã äžéšã®ã³ã³ãã€ã©ã¯ãã«ã¹ã¿ã åãç»é²ããå¿ èŠããããŸãã BOOST_TYPEOFãã©ã®ããã«æ©èœãããã¯ãŸã ããããŸããããŠãŒã¶ãŒã¿ã€ããç»é²ããŸããã§ãããMSVC7.1以éã§ãã©ã¡ãŒã¿ãŒã¿ã€ããå®å šã«è¡šç€ºããŸãã
åã®äŸã§ã¯ããã«ãã¡ãœããã¯åãã¢ãªãã£ã®é¢æ°ããçµã¿ç«ãŠãããŸããã ããã¯ã©ã€ãã©ãªã®å¶éã§ã¯ãããŸããã
äžè¬ã«ãã©ã€ãã©ãªã¯0ãMML_MAX_ARITYã®ã¢ãªãã£ããµããŒãããŸãã MML_MAX_ARITYã®ããã©ã«ãã¯5ã§ããããã©ã«ãå€ã¯å€æŽã§ããŸãã ãããè¡ãã«ã¯ãããããŒãæ¥ç¶ããåã«ããã¯ããå®çŸ©ããå¿ èŠããããŸãã
#define MML_MAX_ARITY n
nã¯æå€§ã¢ãªãã£ã§ãã
ããšãã°ããã«ãåé ãäžé 颿°ã远å ããŸãã
// , , const char* collide_void() { return "Nothing collides?!"; } // , const char* collide_go(game_object*) { return "Unsupported colliding!"; } const char* collide_sh(space_ship*) { return "Space ship collides with what?!"; } const char* collide_as(asteroid*) { return "Asteroid collides with what?!"; } const char* collide_go_go_go(game_object*, game_object*, game_object*) { return "Unsupported colliding!"; } const char* collide_sh_as_as(space_ship*, asteroid*, asteroid*) { return "Space ship collides with two asteroids"; } const char* collide_sh_as_st(space_ship*, asteroid*, space_station*) { return "Space ship collides with asteroid and space_station"; }
ç°ãªãæ°ã®ãªããžã§ã¯ããããã·ã¥ããæ°ãããã¹ã¿ãŒãå¿ èŠã§ãã
template <typename F, typename Objs> void collide_tester_var_arg(F collide, Objs& objs) { // cout << '\t' << collide() << endl; // 1 cout << '\t' << collide(objs[0]) << endl; cout << '\t' << collide(objs[1]) << endl; // 2 cout << '\t' << collide(objs[0], objs[0]) << endl; cout << '\t' << collide(objs[0], objs[1]) << endl; // 3 cout << '\t' << collide(objs[0], objs[1], objs[1]) << endl; cout << '\t' << collide(objs[0], objs[1], objs[2]) << endl; }
ãã«ãã¡ãœãããäœæããŠäœ¿çšããŸãã
collide_tester_var_arg( make_multimethod( collide_go_go , collide_sh_sh , collide_sh_as , collide_void , collide_go , collide_sh , collide_as , collide_go_go_go , collide_sh_as_as , collide_sh_as_st ) , get_obj_pointers() );
ãããã«
Nothing collides Space ship collides with what?! Asteroid collides with what?! Space ship collides with space ship Space ship collides with asteroid Space ship collides with two asteroids Space ship collides with asteroid and space_station
ãããã£ãŠããã«ãã¡ãœããã¯ãåŒæ°ã®æ°ã«é¢ããŠéçã«ãªãŒããŒããŒãããã颿°ã®ããã«åäœããŸãã
æ¬äŒŒã³ãŒãã®ã¬ã³ãçžåœã¯ããã§ããè峿·±ããã®ã«ãªããŸããããã¯åŒæ°ã®æ°ã«åŒ·ãäŸåããŸãïŒ
æ¬äŒŒã³ãŒã
// collide() inline const char* collide() { return collide_void(); } // ! // collide(objs[0]) // collide(objs[1]) inline const char* collide(game_object* obj) { if (space_ship* sh = dynamic_cast<space_ship*>(obj)) return collide_sh(sh); else if (asteroid* as = dynamic_cast<asteroid*>(obj)) return collide_as(as); else return collide_go(obj); } // : // min 1 cast // max 2 casts // collide(objs[0], objs[0]) // collide(objs[0], objs[1]) // , : inline const char* collide(game_object* obj1, game_object* obj2) {...} // collide(objs[0], objs[1], objs[1]) // collide(objs[0], objs[1], objs[2]) inline const char* collide(game_object* obj1, game_object* obj2, game_object* obj3) { if (space_ship* sh1 = dynamic_cast<space_ship*>(obj1)) if (space_ship* sh2 = dynamic_cast<space_ship*>(obj2)) if (asteroid* as3 = dynamic_cast<asteroid*>(obj3)) return collide_go_go_go(sh1, sh2, as3); else if (space_station* st3 = dynamic_cast<space_station*>(obj3)) return collide_go_go_go(sh1, sh2, st3); else return collide_go_go_go(sh1, sh2, obj3); else if (asteroid* as2 = dynamic_cast<asteroid*>(obj2)) if (asteroid* as3 = dynamic_cast<asteroid*>(obj3)) return collide_sh_as_as(sh1, as2, as3); else if (space_station* st3 = dynamic_cast<space_station*>(obj3)) return collide_sh_as_st(sh1, as2, st3); else return collide_go_go_go(sh1, as2, obj3); else if (asteroid* as3 = dynamic_cast<asteroid*>(obj3)) return collide_go_go_go(sh1, obj2, as3); else if (space_station* st3 = dynamic_cast<space_station*>(obj3)) return collide_go_go_go(sh1, obj2, st3); else return collide_go_go_go(sh1, obj2, obj3); else if (asteroid* as1 = dynamic_cast<asteroid*>(obj1)) if (space_ship* sh2 = dynamic_cast<space_ship*>(obj2)) if (asteroid* as3 = dynamic_cast<asteroid*>(obj3)) return collide_go_go_go(as1, sh2, as3); else if (space_station* st3 = dynamic_cast<space_station*>(obj3)) return collide_go_go_go(as1, sh2, st3); else return collide_go_go_go(as1, sh2, obj3); else if (asteroid* as2 = dynamic_cast<asteroid*>(obj2)) if (asteroid* as3 = dynamic_cast<asteroid*>(obj3)) return collide_go_go_go(as1, as2, as3); else if (space_station* st3 = dynamic_cast<space_station*>(obj3)) return collide_go_go_go(as1, as2, st3); else return collide_go_go_go(as1, as2, obj3); else if (asteroid* as3 = dynamic_cast<asteroid*>(obj3)) return collide_go_go_go(as1, obj2, as3); else if (space_station* st3 = dynamic_cast<space_station*>(obj3)) return collide_go_go_go(as1, obj2, st3); else return collide_go_go_go(as1, obj2, obj3); else if (space_ship* sh2 = dynamic_cast<space_ship*>(obj2)) if (asteroid* as3 = dynamic_cast<asteroid*>(obj3)) return collide_go_go_go(obj1, sh2, as3); else if (space_station* st3 = dynamic_cast<space_station*>(obj3)) return collide_go_go_go(obj1, sh2, st3); else return collide_go_go_go(obj1, sh2, obj3); else if (asteroid* as2 = dynamic_cast<asteroid*>(obj2)) if (asteroid* as3 = dynamic_cast<asteroid*>(obj3)) return collide_go_go_go(obj1, as2, as3); else if (space_station* st3 = dynamic_cast<space_station*>(obj3)) return collide_go_go_go(obj1, as2, st3); else return collide_go_go_go(obj1, as2, obj3); else if (asteroid* as3 = dynamic_cast<asteroid*>(obj3)) return collide_go_go_go(obj1, obj2, as3); else if (space_station* st3 = dynamic_cast<space_station*>(obj3)) return collide_go_go_go(obj1, obj2, st3); else return collide_go_go_go(obj1, obj2, obj3); } // : // min 3 casts // max 6 casts
å€çžåãšå€åãæ··åšãããããšãã§ããŸãã å€åã¯ãã®ãŸãŸæž¡ãããŸãã
intåã®3çªç®ã®ãã©ã¡ãŒã¿ãŒãåãåãããšãã§ããããã€ãã®è¿œå ã®ç®ç颿°ã玹ä»ããŸãã
const char* collide_go_go_int(game_object*, game_object*, int) { return "Unsupported colliding with extra int parameter!"; } const char* collide_sh_as_int(space_ship*, asteroid*, int) { return "Space ship collides with asteroid with extra int parameter"; }
æç¢ºã«ããããã«ããã¹ã¿ãŒã¯ãã«ãã¡ãœããã«éä¿¡ããŸãã
2ã€ã®å€çžå;
3ããªã¢ãŒãã£ãã¯ã¿ã€ã;
2ããªã¢ãŒãã£ãã¯ãš1ã€ã®éããªã¢ãŒãã£ãã¯ã¿ã€ãïŒ
template <typename F, typename Objs> void collide_tester_non_polymorphic_arg(F collide, Objs& objs) { cout << '\t' << collide(objs[0], objs[1]) << endl; cout << '\t' << collide(objs[0], objs[1], objs[2]) << endl; cout << '\t' << collide(objs[0], objs[1], 1) << endl; }
以åã®ã¿ãŒã²ãã颿°ãšæ°ããã¿ãŒã²ãã颿°ã«åºã¥ããŠãã«ãã¡ãœãããäœæãã以äžã䜿çšããŸãã
collide_tester_non_polymorphic_arg( make_multimethod( collide_go_go , collide_sh_sh , collide_sh_as , collide_as_sh , collide_as_as , collide_go_go_go , collide_sh_as_st , collide_sh_as_as , collide_go_go_int , collide_sh_as_int ) , get_obj_pointers() );
ãããã«
Space ship collides with asteroid Space ship collides with asteroid and space_station Space ship collides with asteroid with extra int parameter
æåã®åŒã³åºããš2çªç®ã®åŒã³åºãã«çžåœããRanthimeãæå®ããŸããã
æ¬äŒŒã³ãŒã
// collide(objs[0], objs[1], 1) inline const char* collide(game_object* obj1, game_object* obj2, int n) { if (space_ship* sh1 = dynamic_cast<space_ship*>(obj1)) if (space_ship* sh2 = dynamic_cast<space_ship*>(obj2)) return collide_go_go_int(sh1, sh2, n); else if (asteroid* as2 = dynamic_cast<asteroid*>(obj2)) return collide_sh_as_int(sh1, as2, n); else return collide_go_go_int(sh1, obj2, n); else if (asteroid* as1 = dynamic_cast<asteroid*>(obj1)) if (space_ship* sh2 = dynamic_cast<space_ship*>(obj2)) return collide_go_go_int(as1, sh2, n); else if (asteroid* as2 = dynamic_cast<asteroid*>(obj2)) return collide_go_go_int(as1, as2, n); else return collide_go_go_int(as1, obj2, n); else if (space_ship* sh2 = dynamic_cast<space_ship*>(obj2)) return collide_go_go_int(obj1, sh2, n); else if (asteroid* as2 = dynamic_cast<asteroid*>(obj2)) return collide_go_go_int(obj1, as2, n); else return collide_go_go_int(obj1, obj2, n); } // : // min 2 casts // max 4 casts
ã芧ã®ãšãããé倿 çãªåŒæ°ã¯è¿œå ã®ãªãŒããŒãããã«ã€ãªãããŸããã
constããã³volatile修食åã®ãªãŒããŒããŒãããµããŒããããŠããŸãã
const char* collide_go_cvgo(game_object*, const volatile game_object*) { return "Unsupported colliding!"; } const char* collide_sh_cas(space_ship*, const asteroid*) { return "Space ship collides with const asteroid"; } const char* collide_sh_vas(space_ship*, volatile asteroid*) { return "Space ship collides with volatile asteroid"; } const char* collide_sh_cvas(space_ship*, const volatile asteroid*) { return "Space ship collides with const volatile asteroid"; } template <typename F, typename Objs> void collide_tester_cv(F collide, Objs& objs) { game_object* object = objs[1]; const game_object* c_object = objs[1]; const volatile game_object* cv_object = objs[1]; cout << '\t' << collide(objs[0], object) << endl; cout << '\t' << collide(objs[0], c_object) << endl; cout << '\t' << collide(objs[0], cv_object) << endl; } collide_tester_cv( make_multimethod( collide_sh_as , collide_go_cvgo , collide_sh_cas , collide_sh_vas , collide_sh_cvas ) , get_obj_pointers() ); }
ãããã«
Space ship collides with asteroid Space ship collides with const asteroid Space ship collides with const volatile asteroid
ãã«ãã¡ãœããã®éèŠãªæ©èœã¯ãå€çžåŒæ°ã®æ£ç¢ºãªã¿ã€ããã³ã³ãã€ã«æ®µéã§ãã§ã«ããã£ãŠããå Žåã«ã¹ã±ãžã¥ãŒãªã³ã°ãæé©åããæ©èœã§ããã€ãŸããå®éã®ã¿ã€ãã®åŒæ°ã®æ€çŽ¢ã¯ãéå±€ããŒãããå§ãŸããŸããããã¯ãæž¡ãããåŒæ°ã®å®éã®ã¿ã€ãã§ãã説æãç°¡åã«ãªããŸã...äŸãèŠãŠã¿ãŸãããïŒ
template <typename F, typename Objs> void collide_tester_compile_time_optim(F collide, Objs& objs) { space_ship ship; asteroid ast; cout << '\t' << collide(objs[0], &ast) << endl; cout << '\t' << collide(&ship, &ast) << endl; } collide_tester_compile_time_optim( make_multimethod( collide_go_go , collide_sh_sh , collide_sh_as , collide_as_sh , collide_as_as ) , get_obj_pointers() );
ãããã«
Space ship collides with asteroid Space ship collides with asteroid
次ã«ãåçã®ã©ã³ã¿ã€ã ãæ éã«æ€èšããŸãã
// collide(objs[0], &ast) inline const char* collide(game_object* obj1, asteroid* as2) { if (space_ship* sh1 = dynamic_cast<space_ship*>(obj1)) return collide_sh_as(sh1, as2); else if (asteroid* as1 = dynamic_cast<asteroid*>(obj1)) return collide_as_as(as1, as2); else return collide_go_go(obj1, as2); } // : // min 1 cast // max 2 casts // collide(&ship, &ast) inline const char* collide(space_ship* sh1, asteroid* as2) { return collide_sh_as(sh1, as2); } // !
æåã®åŒã³åºãã¯æåã®åŒæ°ã«ãã£ãŠã®ã¿ãã£ã¹ãããããã2çªç®ã®åŒæ°ã¯ãã®ãŸãŸæž¡ãããŸãããã®åã¯ã³ã³ãã€ã«æã«ç¢ºå®ã«æ¢ç¥ã§ãã
éåžžã2çªç®ã®åŒã³åºãã¯åçŽãªè»¢éã§ãããäž¡æ¹ã®åŒæ°ã®åã¯ã³ã³ãã€ã«æã«æ¢ç¥ã§ãã
ãã®ããããã®ãããªæé©åããµããŒãããããã«ãå¯èœã§ããã°ããã«ãã¡ãœãããçŽç²ãªåœ¢åŒã§æ ŒçŽããã³éä¿¡ããboost :: function / * std :: function * /ã®åŸãã«é ããŠã¯ãªããŸãããã¢ãããã£ã¹ãã䌎ãåŒã³åºã-è¡çªïŒïŒgame_object *ïŒïŒshipãïŒgame_object *ïŒïŒastïŒ-ã©ã€ãã©ãªããæé©åã®å¯èœæ§ã奪ããŸãã
ãã«ãã¡ãœããã¯ããã¢ãã€ã³ã¿ãŒã ãã§ãªããboost :: shared_ptrãããã³ãã³ãã¬ãŒãã®ãã¢ãé©åã«ç¹åããã«ã¹ã¿ã ãã€ã³ã¿ãŒåããµããŒãããŠããŸãïŒè©³çްã«ã€ããŠã¯ã次ã®èšäºãåç §ïŒãboost :: shared_ptrããµããŒãããã«ã¯ãããããŒãã¡ã€ã«<mml / casting / sp_dynamic_caster.hpp>ãå«ããå¿ èŠããããŸãã
äŸïŒ
#include <mml/casting/sp_dynamic_caster.hpp> const char* sp_collide_go_go(game_object*, boost::shared_ptr<game_object>) { return "Unsupported colliding!"; } const char* sp_collide_sh_sh(space_ship*, boost::shared_ptr<space_ship>) { return "Space ship collides with smart_ptr space ship"; } struct sp_collider_sh_as { const char* operator()(space_ship*, boost::shared_ptr<asteroid>) const { return "Space ship collides with smart_ptr asteroid"; } }; template <typename F, typename Objs> void sp_collide_tester(F collide, Objs& objs) { boost::shared_ptr<game_object> obj1(new space_ship); boost::shared_ptr<game_object> obj2(new asteroid); cout << '\t' << collide(objs[0], obj1) << endl; cout << '\t' << collide(objs[0], obj2) << endl; } sp_collide_tester( make_multimethod( sp_collide_go_go , sp_collide_sh_sh , sp_collider_sh_as() ) , get_obj_pointers() );
ãããã«
Space ship collides with smart_ptr space ship Space ship collides with smart_ptr asteroid
Ranthimeã®åçç©ïŒ
æ¬äŒŒã³ãŒã
// collide(objs[0], obj1) // collide(objs[0], obj2) inline const char* collide(game_object* obj1, const boost::shared_ptr<game_object>& sp_obj2) { if (space_ship* sh1 = dynamic_cast<space_ship*>(obj1)) if (boost::shared_ptr<space_ship> sp_sh2 = boost::shared_dynamic_cast<space_ship>(sp_obj2)) return sp_collide_sh_sh(sh1, sp_sh2); else if (boost::shared_ptr<asteroid> sp_as2 = boost::shared_dynamic_cast<asteroid>(sp_obj2)) return sp_collider_sh_as()(sh1, sp_as2); else return sp_collide_go_go(obj1, sp_obj2); else if (boost::shared_ptr<space_ship> sp_sh2 = boost::shared_dynamic_cast<space_ship>(sp_obj2)) return sp_collide_go_go(obj1, sp_sh2); else if (boost::shared_ptr<asteroid> sp_as2 = boost::shared_dynamic_cast<asteroid>(sp_obj2)) return sp_collide_go_go(obj1, sp_as2); else return sp_collide_go_go(obj1, sp_obj2); } // : // min 2 casts // max 3 casts
äŸã®ãœãŒã¹ã¯ãã¡ãã§ãã
ã¡ãªãã
. . , , . . . , .( 0).
â compile time, .
çæ
( ). , .. . - . , . , ., .
æ§èœ
â dynamic_cast. dynamic_cast . , - . , «fast_cast», dynamic_cast . , . , ?GUI . (inlining) .
, . Acyclyc Visitor , . dynamic_cast.
, , . ( , ) â .
äŸåé¢ä¿
C++ 03 BOOST (headers only) 1.45.0 .éèŠïŒã³ã³ãã€ã©ã€ã³ã¯ã«ãŒããã£ã¬ã¯ããªå ã«ãboostãããã³ãmmlããã£ã¬ã¯ããªãååšããå¿ èŠããããŸãããboostãããã³ãmmlããã£ã¬ã¯ããªèªäœãincludeãã£ã¬ã¯ããªãšããŠæå®ãããããããå«ããã£ã¬ã¯ããªãæå®ããŸãã
ãµã³ãã«ä»ãã®ã©ã€ãã©ãªã¯ãã³ã³ãã€ã©ã§ãã¹ããããŠããŸãïŒãããŸã§ã¯Windowsã§ã®ã¿ïŒ
ãGCC3.4.2ã
Visual C ++ 7.1ã8.0ã9.0ã10.0
UPDïŒ , , . , . , ( 57 ~190 ). , . , , if-else, .
UPD 2: : , C++ . , . , . mejedi .
. , .