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 .
. , .