-¶äÅ·¥é¥¤¥Ö¥é¥ê¡Ê Ginten C++ Libraries ¡Ë ´Ê°×Èǥɥ¥å¥á¥ó¥È
-written by SubarG, gintensubaru@hotmail.com
-This document is encoded with EUC-JP.
+ このドキュメントは書きかけです
-¡¦Ãí°Õ»ö¹à
-¤³¤Î¥Õ¥¡¥¤¥ë¤Ï¡¢Àµ¼°¤Ê¥É¥¥å¥á¥ó¥È¤¬´°À®¤¹¤ë¤Þ¤Ç¤Î¡Ö¤Ä¤Ê¤®¡×¤È¤·¤ÆÍÑ°Õ¤·¤¿¤â¤Î¤Ç¤¹¡£Àµ¼°¤Ê¥É¥¥å¥á¥ó¥È¤¬´°À®¤·¤¿ºÝ¤Ë¤Ï¡¢¤³¤ÎÆâÍƤÏÂçÉý¤Ëºï¤é¤ì¤ë¤«¡¢¤¢¤ë¤¤¤Ïºï½ü¤µ¤ì¤ëͽÄê¤Ç¤¹¤Î¤Ç¤´Î»¾µ¤¯¤À¤µ¤¤¡£
-Àµ¼°¤Ê¥É¥¥å¥á¥ó¥È¤¬½ÐÍè¤ë¤Þ¤Ç¤Î´Ö¡¢¥é¥¤¥Ö¥é¥ê¤Î»ÈÍÑË¡¤Ï¡¢¤½¤Î¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë( gintenlib/ Æâ)¤ä¥Æ¥¹¥È¥³¡¼¥É( tests/ Æâ)¤Î³Æ¥Õ¥¡¥¤¥ë¤ò»²¾È¤·¤Æ¤¤¤¿¤À¤¯¤è¤¦¤ª´ê¤¤¤·¤Þ¤¹¡£
-
-
-¡¦¤´°§»¢
-
-¤³¤ÎÅ٤϶äÅ·¥é¥¤¥Ö¥é¥ê¤ò¥À¥¦¥ó¥í¡¼¥É夤¢¤ê¤¬¤È¤¦¤´¤¶¤¤¤Þ¤¹¡£
-¶äÅ·¥é¥¤¥Ö¥é¥ê¤È¤Ï¡¢¡Ö¤Ê¤¯¤Æ¤â¤¤¤¤¤¬¤¢¤ë¤È¾¯¤·ÊØÍø¡×¤È¤¤¤¦¥³¥ó¥»¥×¥È¤Î¸µ¡¢¼ç¤Ë¶äÅ·¿ïÉ®½¸ http://d.hatena.ne.jp/gintenlabo/ Æâ¤ÇÀ½ºî¤µ¤ì¤Æ¤¤¤ë¡¢»äŪ C++ ¥é¥¤¥Ö¥é¥ê¤Ç¤¹¡£
-»äŪ¡¢¤È¤¤¤¦Ä̤ꡢËÜÍèŪ¤Ë¤Ï¼«Ê¬¤Î°Ù¤À¤±¤Ëºî¤Ã¤¿¥³¡¼¥ÉÃÇÊÒ½¸¤Ê¤Î¤Ç¤¹¤¬¡¢»È¤Ã¤Æ¤¤¤Æ»×¤Ã¤¿¤è¤ê»È¤¤¾¡¼ê¤¬¤è¤¤¤Î¤Ç¡¢À޳ѤÀ¤«¤é¥é¥¤¥Ö¥é¥ê¤È¤·¤Æ¤Þ¤È¤á¤Æ°ìÈ̸ø³«¤·¤è¤¦¡¢¤È¤¤¤¦¤³¤È¤Ç¡¢£²£°£°£·Ç¯£±£²·îº¢¤«¤é¾¯¤·¤º¤Ä¤Ç¤¹¤¬³«È¯¤ò¿Ê¤á¤Æ¤¤Þ¤·¤¿¡£¤½¤·¤ÆÆóǯ¤¿¤Ã¤¿º£¡¢¤è¤¦¤ä¤¯¤½¤ì¤Ê¤ê¤Îµ¬ÌϤΥ饤¥Ö¥é¥ê¤È»×¤¨¤ë¤è¤¦¤Ë¤Ê¤Ã¤¿¤Î¤Ç¡¢²þ¤á¤Æ version 1.0.0 ¤È¤·¤Æ»×¤¤Àڤ俺ÆÊÔ¤ò¹Ô¤¤¡¢¤è¤¦¤ä¤¯¤³¤¦¤·¤Æ¤Þ¤È¤Þ¤Ã¤¿¥é¥¤¥Ö¥é¥ê¤È¤·¤ÆÀ¤¤Ë½Ð¤¹¤Ë»ê¤Ã¤¿¼¡Âè¤Ç¤¹¡£
-¤½¤¦¤¤¤¦·Ð°Þ¤¬¤¢¤ë¤¿¤á¡¢¼ýÏ¿¤µ¤ì¤Æ¤¤¤ë¥é¥¤¥Ö¥é¥ê¤ÏÈó¾ï¤Ë»¨Â¿¤Ç¡¢Æä˷è¤á¤é¤ì¤¿Êý¸þÀ¤È¤¤¤¦¤â¤Î¤â¸ºß¤·¤Þ¤»¤ó¡£°ì±þ¡¢¥³¥ó¥»¥×¥È¤¬¡Ö¤Ê¤¯¤Æ¤â¤¤¤¤¤¬¤¢¤ë¤È¾¯¤·ÊØÍø¡×¤Ç¤¢¤ë°Ê¾å¡¢¤¢¤¯¤Þ¤Çµ¤·Ú¤Ë»È¤¨¤ë¤³¤È¤Ë½ÅÅÀ¤òÃÖ¤¤¤Æ³«È¯¤·¤Æ¤Ï¤¤¤ë¤Î¤Ç¤¹¤¬¡¢¤½¤ì¤¹¤é¼é¤ì¤Ê¤¤¤³¤È¤â¿¡¹¡£¤³¤ÎÊÕ¤ê¤Ï¥Ð¡¼¥¸¥ç¥ó¥¢¥Ã¥×¤ò½Å¤Í¤ë¾å¤Ç¾¯¤·¤º¤ÄÂåÂؼêÃʤòÁý¤ä¤·¤Æ¤¤¤¯¤³¤È¤ÇÂбþ¤·¤è¤¦¤«¤È¹Í¤¨¤Æ¤¤¤Þ¤¹¡£
-
-¤Ç¤Ï¶ñÂÎŪ¤Ë¡¢¤É¤ó¤Ê¥é¥¤¥Ö¥é¥ê¤¬¤¢¤ë¤«¡¢°ìÉô¤Ç¤¹¤¬¾Ü¤·¤¯¾Ò²ð¤·¤¿¤¤¤È»×¤¤¤Þ¤¹¡£
-¤Þ¤º list_format ¡£¼Â¤ò¸À¤¦¤È¡¢¤³¤ì¤³¤½¤¬¶äÅ·¥é¥¤¥Ö¥é¥ê¤òºî¤í¤¦¤È»×¤Ã¤¿ºÇÂç¤ÎÆ°µ¡¤Ç¤¢¤Ã¤¿¤ê¤·¤Þ¤¹¡£ µ¡Ç½¤Ï¡¢Å¬Åö¤ÊÇÛÎó int a[5]; ¤ä¥³¥ó¥Æ¥Ê std::vector a; ¤ËÂФ·¡¢cout << gintenlib::list_format( a ); ¤È¤«½ñ¤¯¤À¤±¤Ç "( 1, 2, 3, 4, 5 )" ¤Î¤è¤¦¤Ëɽ¼¨¤Ç¤¤ë¡¢¤È¤¤¤¦¤À¤±¤Î¤â¤Î¤Ç¤¹¡£Ê̤ˤʤ¯¤Æ¤â¤É¤¦¤È¤¤¤¦¤³¤È¤Ï¤¢¤ê¤Þ¤»¤ó¤¬¡¢¤¢¤ë¤Ê¤é¤¢¤ë¤Ç¥Ç¥Ð¥Ã¥°¤Î¤È¤¤È¤«¤Ë¾¯¤·ÊØÍø¤Ç¤·¤ç¤¦¡©
-¤â¤Ã¤È¼ÂºÝŪ¤ËÌò¤ËΩ¤Ä¤è¤¦¤Ê¥é¥¤¥Ö¥é¥ê¤â¤¢¤ê¤Þ¤¹¡£ new_ ¤¬¤½¤ÎÂåɽÎã¤Ç¤¹¡£¤³¤ì¤Ï¡¢¡Ö gintenlib::new_<T>(°ú¿ô¥ê¥¹¥È) ¡×¤È½ñ¤¯¤³¤È¤Ë¤è¤ê¡¢¡Ö boost::shared_ptr<T>( new T(°ú¿ô) ) ¡×¤¬¸Æ¤Ð¤ì¤ë¡¢¤È¤¤¤¦¤À¤±¤Î¥é¥¤¥Ö¥é¥ê¤Ç¤¹¤¬¡¢¤¿¤È¤¨¤Ð shared_ptr ¤ò°ú¿ô¤Ë¤È¤ë´Ø¿ô¤Ë¿·¤·¤¯¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤Ã¤ÆÅϤ·¤¿¤¤¡¢¤È¤¤¤¦¤È¤¤Ë¥½¡¼¥¹¤¬¤À¤¤¤Ö´Ê·é¤Ë¤Ê¤ë¡¢¤È¤¤¤¦ÍøÅÀ¤¬¤¢¤ê¤Þ¤¹¡Ê¼ÂºÝ¤Ë¤Ï¤â¤Ã¤È½ÐÍè¤ë¤³¤È¤Ï¿¤¤¤Ç¤¹¡£¾Ü¤·¤¯¤Ï¥Ø¥Ã¥À¤Ë½ñ¤¤¤Æ¤¢¤ë¤Î¤Ç¤½¤Á¤é¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡Ë¡£¤½¤ó¤Ê¤ÎÊ̤ˤʤ¯¤Æ¤â¤¤¤¤¤±¤É¡¢¤¢¤Ã¤¿¤é¤¢¤Ã¤¿¤Ç¾¯¤·ÊØÍø¤½¤¦¤Ç¤·¤ç¤¦¡©
-¤µ¤é¤Ë¶äÅ·¥é¥¤¥Ö¥é¥ê¤ÎÆÃħ¤È¤·¤Æ¡¢¶äÅ·¥é¥¤¥Ö¥é¥ê¤Î¥Ø¥Ã¥À¤ò½ñ¤¯¤È¤¤Ë½ÐÍè¤ë¸Â¤ê³Ú¤ò¤·¤è¤¦¤È¤¤¤¦È¯ÁÛ¤«¤é¡¢¼ÂÁõÊä½õ·ÏÅý¤Î¥é¥¤¥Ö¥é¥ê¤¬Èó¾ï¤Ë¿¤¤ÅÀ¤¬Í¤ê¤Þ¤¹¡£ SafeBool ¥¤¥Ç¥£¥ª¥à¤òÄ󶡤¹¤ë bool_comparable ¤ä¡¢¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿ºî¤ë¤È¤¤Ë get() ´Ø¿ô¤À¤±ÄêµÁ¤¹¤ì¤Ð¼«Æ°¤Ç·¿ÄêµÁ¤ä±é»»»Ò¿½ÅÄêµÁ¤ò¤·¤Æ¤¯¤ì¤ë pointer_facade ¡¢ boost::enable_if ¤òû¤¤¥Þ¥¯¥í¤Ç°·¤¨¤ë¤è¤¦¤Ë¤·¤¿ preprocessor.enable_if ¤Ê¤É¡¢¤³¤Î¼ê¤ÎÊØÍøµ¡Ç½¤ÏÈó¾ï¤Ë¿¤¯¡¢¤Þ¤¿¼ÂÍÑÀ¤â¾¤ËÈæ¤Ù¤ÆÃʰ㤤¤Ë¹â¤¯¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£¶½Ì£¤¬¤¢¤ì¤Ðõ¤·¤Æ¤ß¤ë¤ÈÌÌÇò¤¤¤Ç¤·¤ç¤¦¡£
-
-¤È¡¢¾¯¤·Ïä¬Ä¹¤¯¤Ê¤Ã¤Æ¤·¤Þ¤¤¤Þ¤·¤¿¡£¤â¤Ã¤È¿§¡¹¸ì¤ê¤¿¤¤¤Î¤Ï»³¡¹¤Ç¤¹¤¬¡¢¤½¤ì¤ÏÀµ¼°¤Ê¥É¥¥å¥á¥ó¥È¤¬½ÐÍè¤Æ¤«¤é¤Ë¤·¤¿¤Û¤¦¤¬¤è¤µ¤½¤¦¤Ç¤¹¡£
-»È¤¦Â¦¤È¤·¤Æ¤â¡¢Ä¹¤¤°§»¢¤Ê¤¾¤òÆɤà¤è¤ê¡¢¼ÂºÝ¤Ë»î¤·¤Æ¤ß¤¿¤Û¤¦¤¬Ê¬¤«¤ë¤³¤È¤Ï¿¤¤¤Ç¤·¤ç¤¦¤·¤Í¡£
-¤È¤¤¤¦¤ï¤±¤Ç°§»¢¤ÏÁ᡹¤ËÀÚ¤ê¾å¤²¤ë¤³¤È¤Ë¤·¤Þ¤¹¤¬¡¢ºÇ¸å¤Ë¾¯¤·¤À¤±¡¢¸À¤ï¤»¤Æ夤¿¤¤¤³¤È¤¬¤¢¤ê¤Þ¤¹¡£
-¶äÅ·¥é¥¤¥Ö¥é¥ê¤Ï̤¤ÀȯŸÅÓ¾å¤Ë¤¢¤ë¥é¥¤¥Ö¥é¥ê¤Ç¤¹¡£
-¤è¤Ã¤Æºî¼Ô¤Î°Õ¿Þ¤»¤ÌÉÔ¶ñ¹ç¤ä¡¢¡Ö¤³¤¦¤·¤¿¤Û¤¦¤¬¤¤¤¤¤è¡×¤È¤¤¤¦ÅÀ¤Ê¤É¡¢¤¤¤¯¤é¤Ç¤â¸ºß¤¹¤ë¤È»×¤ï¤ì¤Þ¤¹¡£
-¤½¤Î¤è¤¦¤ÊÅÀ¤ò¤â¤·¸«¤«¤±¤¿¤é¡¢µ¤¤¬¸þ¤¤¤¿¤È¤¤Ë¤Ç¤âÃΤ餻¤Æ¤â¤é¤¨¤ë¤È¡¢Èó¾ï¤Ë½õ¤«¤ë¤Î¤Ç¤¹¡£
-¶äÅ·¥é¥¤¥Ö¥é¥ê¤Î¥µ¥Ý¡¼¥È¤Ï¶äÅ·¿ïÉ®½¸ http://d.hatena.ne.jp/gintenlabo/ ¤Ç¹Ô¤Ã¤Æ¤¤¤Þ¤¹¤Î¤Ç¡¢¤â¤·µ¤¤Ë¤Ê¤ëÅÀ¤¬¤¢¤ê¤Þ¤·¤¿¤é¥³¥á¥ó¥È¤ò¤ª´ê¤¤¤·¤Þ¤¹¡£Ã±¤Ê¤ë¡Ö¤Ä¤«¤Ã¤Æ¤ß¤¿¤è¡¼¡×Ū¤Ê¥³¥á¥ó¥È¤âÂç´¿·Þ¤Ç¤¹¡£
-¤½¤ì¤Ç¤Ï¡¢¤è¤¥×¥í¥°¥é¥ß¥ó¥°¥é¥¤¥Õ¤ò¡£´ê¤ï¤¯¤Ð¡¢¶äÅ·¥é¥¤¥Ö¥é¥ê¤¬¾¯¤·ÌòΩ¤Á¤Þ¤¹¤è¤¦¤Ë¡£
-
-
-¡¦¥é¥¤¥Ö¥é¥ê°ìÍ÷
+・ライブラリ一覧
<gintenlib/assign.hpp>
-¥³¥Ô¡¼¤µ¤ì¤ë¦¤Î»ö¾ð¤òÍ¥À褷¤¿ std::copy ¥¢¥ë¥´¥ê¥º¥à¤ÎÊÑ·Á
+コピーされる側の事情を優先した std::copy アルゴリズムの変形
<gintenlib/bool_comparable.hpp>
-SafeBool ¥¤¥Ç¥£¥ª¥à¤ò´Êñ¤Ë°·¤¨¤ë¤è¤¦¤Ë¤¹¤ë¥Æ¥ó¥×¥ì¡¼¥È¥¯¥é¥¹
+SafeBool ã\82¤ã\83\87ã\82£ã\82ªã\83 ã\82\92ç°¡å\8d\98ã\81«æ\89±ã\81\88ã\82\8bã\82\88ã\81\86ã\81«ã\81\99ã\82\8bã\83\86ã\83³ã\83\97ã\83¬ã\83¼ã\83\88ã\82¯ã\83©ã\82¹
<gintenlib/call_traits.hpp>
-¼ÂÁõÍÑ¡£ boost::call_traits ¤Ø¤Îû½Ì¥¢¥¯¥»¥¹
+å®\9fè£\85ç\94¨ã\80\82 boost::call_traits ã\81¸ã\81®ç\9f縮ã\82¢ã\82¯ã\82»ã\82¹
<gintenlib/cast.hpp>
-ÌÀ¼¨Åª¤Ë°ÅÌÛÊÑ´¹¤ò¹Ô¤¦´Ø¿ô
+明示的に暗黙変換を行う関数
<gintenlib/clonable_ptr.hpp>
-ÊÝ»ý¤·¤¿¥ª¥Ö¥¸¥§¥¯¥È¤ÎÀµ³Î¤ÊÊ£À½¤òºî¤ë¤³¤È¤Î¤Ç¤¤ë¡¢¶¦ÍÑ¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿
+ä¿\9dæ\8c\81ã\81\97ã\81\9fã\82ªã\83\96ã\82¸ã\82§ã\82¯ã\83\88ã\81®æ£ç¢ºã\81ªè¤\87製ã\82\92ä½\9cã\82\8bã\81\93ã\81¨ã\81®ã\81§ã\81\8dã\82\8bã\80\81å\85±ç\94¨ã\82¹ã\83\9eã\83¼ã\83\88ã\83\9dã\82¤ã\83³ã\82¿
<gintenlib/context_error.hpp>
-ʸ̮¥¨¥é¡¼¡§ ´Ø¿ô¤Ê¤É¤ò¸Æ¤Ó½Ð¤·¤Æ¤Ï¤¤¤±¤Ê¤¤¾õ¶·¤Ç¸Æ¤Ó½Ð¤·¤¿¤È¤¤ËÁ÷½Ð¤µ¤ì¤ëÎã³°
+文脈エラー: 関数などを呼び出してはいけない状況で呼び出したときに送出される例外
<gintenlib/d_enable_if.hpp>
-enable_if ÍѤᣤ·°ú¿ô¤Ë»È¤¦·¿ dummy_arg_t ¤È¡¢dummy_arg_t ÍѤΠenable_if ¤Ç¤¢¤ë d_enable_if Åù
+enable_if 用の隠し引数に使う型 dummy_arg_t と、dummy_arg_t 用の enable_if であ
+る d_enable_if 等
<gintenlib/deep_ptr.hpp>
-¥³¥Ô¡¼»þ¤Ë¾ï¤Ë¿¼¤¤¥³¥Ô¡¼¤ò¹Ô¤¦¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¡£
+コピー時に常に深いコピーを行うスマートポインタ。
<gintenlib/deleter.hpp>
-ñ½ã¤Êºï½ü·Ï¥Õ¥¡¥ó¥¯¥¿µÍ¤á¹ç¤ï¤»
+単純な削除系ファンクタ詰め合わせ
<gintenlib/factorize.hpp>
-À°¿ô¤òÁÇ°ø¿ôʬ²ò¤·½ç¤Ë¥¤¥Æ¥ì¡¼¥¿¤Ë½ÐÎϤ¹¤ë´Ø¿ô factorize
+整数を素因数分解し順にイテレータに出力する関数 factorize
<gintenlib/intrusive_to_shared.hpp>
-boost::intrusive_ptr ¤ò boost::shared_ptr ¤ËÊÑ´¹¤¹¤ë¥Ä¡¼¥ë
+boost::intrusive_ptr を boost::shared_ptr に変換するツール
<gintenlib/to_shared.hpp>
-°ìÈ̤Υ¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤ò boost::shared_ptr ¤ËÊÑ´¹¡Êº£¤Î¤È¤³¤í std::auto_ptr °Ê³°¤ÏÆ°ºî̤³Îǧ¡Ë
+一般のスマートポインタを boost::shared_ptr に変換
<gintenlib/lexical_cast_default.hpp>
<gintenlib/lexical_convert.hpp>
-Îã³°¤òÅꤲ¤Ê¤¤ boost::lexical_cast
+例外を投げない boost::lexical_cast
<gintenlib/list_format.hpp>
-¥³¥ó¥Æ¥Ê¤òÀ°·Á¤·¤Æ¥¹¥È¥ê¡¼¥à½ÐÎÏ
+コンテナを整形してストリーム出力
<gintenlib/list_formatter.hpp>
-¥³¥ó¥Æ¥Ê¤òÀ°·Á¤·¤Æ¥¹¥È¥ê¡¼¥à½ÐÎÏ¡¢³ÈÄ¥ÈÇ
+コンテナを整形してストリーム出力、拡張版
<gintenlib/math.hpp>
-<cmath> ¥¤¥ó¥¯¥ë¡¼¥É¡Ü³Æ¼ïµ¹æÄê¿ô¥Þ¥¯¥í¤ÎÄêµÁ
+<cmath> インクルード+各種記号定数マクロの定義
<gintenlib/move_ptr.hpp>
-std::auto_ptr ¤ÎÈù³ÈÄ¥ÈÇ¡£ swap ¤Ç¤¡¢ºï½ü´Ø¿ô¤ò»ØÄê¤Ç¤¤ë
+std::auto_ptr の微拡張版。 swap でき、削除関数を指定できる
<gintenlib/new_.hpp>
-new ±é»»»Ò¤ò¸Æ¤Ó½Ð¤· shared_ptr ¤Ë³ÊǼ¤¹¤ë´Ø¿ô
+new 演算子を呼び出し shared_ptr に格納する関数
<gintenlib/options.hpp>
-£Ç£Î£Õ getopt() ´Ø¿ô¸ß´¹¤Î¥×¥í¥°¥é¥à¥ª¥×¥·¥ç¥ó²òÀÏ
+GNU getopt() 関数互換のプログラムオプション解析
<gintenlib/pointer_facade.hpp>
-¤é¤¯¤Á¤ó¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¼ÂÁõ¡Ê¥Æ¥¹¥È¥³¡¼¥É¤Ï¤¢¤ê¤Þ¤»¤ó¤¬¥Ø¥Ã¥À¤ò¸«¤ì¤Ð»È¤¤Êý¤Ïʬ¤«¤ë¤Ï¤º¤Ç¤¹¡Ë
+らくちんスマートポインタ実装
<gintenlib/preprocessor/dequote.hpp>
-typename GINTENLIB_DEQUOTE(( type )) ¤È½ñ¤¯¤³¤È¤Ç type ¤òɽ¤¹É½¸½¤Ø¤ÈŸ³«¤µ¤ì¤ë¥Þ¥¯¥í
+typename GINTENLIB_DEQUOTE(( type )) と書くことで type を表す型表現へと展開
<gintenlib/preprocessor/enable_if.hpp>
-enable_if ¤òû¤¯»È¤¨¤ë¥Þ¥¯¥í GINTENLIB_ENABLE_IF(( cond )) Åù
+enable_if を短く使えるマクロ GINTENLIB_ENABLE_IF(( cond )) 等
<gintenlib/reference_counter.hpp>
-boost::intrusive_ptr ÍѤλ²¾È¥«¥¦¥ó¥¿ÉÕ¤¥ª¥Ö¥¸¥§¥¯¥È¤ÎÀ½ºîÊä½õ
+boost::intrusive_ptr 用の参照カウンタ付きオブジェクトの製作補助
<gintenlib/to_string.hpp>
-Ǥ°Õ¤Îɽ¸½¤òʸ»úÎó¤ËÊÑ´¹
+任意の表現を文字列に変換
<gintenlib/typed_saver.hpp>
<gintenlib/value_saver.hpp>
-¥Ç¥¹¥È¥é¥¯¥¿¤ÇÊÑ¿ô¤ÎÃͤò´¬¤Ì᤹¥¯¥é¥¹
+ã\83\87ã\82¹ã\83\88ã\83©ã\82¯ã\82¿ã\81§å¤\89æ\95°ã\81®å\80¤ã\82\92å·»ã\81\8dæ\88»ã\81\99ã\82¯ã\83©ã\82¹
<gintenlib/enable_if.hpp>
<gintenlib/ignore.hpp>
<gintenlib/shared_ptr.hpp>
<gintenlib/type.hpp>
<gintenlib/tribool.hpp>
-ñ¤Ê¤ë boost ¤Ø¤Î using Àë¸À
-
-
-¡¦¥¤¥ó¥¹¥È¡¼¥ë¤Ë¤Ä¤¤¤Æ
-
-¶äÅ·¥é¥¤¥Ö¥é¥ê¤Ï¥Ø¥Ã¥À¤Î¤ß¤Ç¹½À®¤µ¤ì¤¿¥é¥¤¥Ö¥é¥ê¤Ç¤¹¡£
-
-¡¦¥Û¡¼¥à¥Ç¥£¥ì¥¯¥È¥ê¡Ê¤³¤Î¥Õ¥¡¥¤¥ë¤¬¤¢¤ë¥Ç¥£¥ì¥¯¥È¥ê¡Ë¤Ë¥¤¥ó¥¯¥ë¡¼¥É¥Ñ¥¹¤òÄ̤¹¡Ê¿ä¾©¡Ë
-¡¦´û¸¤Î¥¤¥ó¥¯¥ë¡¼¥ÉÍѥǥ£¥ì¥¯¥È¥ê¤Ë¥é¥¤¥Ö¥é¥ê¤Î¥Ç¥£¥ì¥¯¥È¥ê¡Ê¤³¤Î¥Õ¥¡¥¤¥ë¤ÈƱ³¬Áؤˤ¢¤ë gintenlib/ ¡Ë¤ò¥³¥Ô¡¼¤¹¤ë
-¡¦¶äÅ·¥é¥¤¥Ö¥é¥ê¤ò»È¤¤¤¿¤¤¥×¥í¥°¥é¥à¤Î¤¢¤ë¾ì½ê¤Ë¥é¥¤¥Ö¥é¥ê¤Î¥Ç¥£¥ì¥¯¥È¥ê¤ò¥³¥Ô¡¼¤¹¤ë¡ÊÈó¿ä¾©¡Ë
-
-¤³¤È¤Ë¤è¤ê¥¤¥ó¥¹¥È¡¼¥ë¤¹¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡£
+単なる boost への using 宣言
-¡¦¡¦¡¦¤È¡¢¤½¤ÎÁ°¤Ë¡£
-¶äÅ·¥é¥¤¥Ö¥é¥ê¤Ï Boost C++ Libraries ( http://www.boost.org/ ) ¤òÍѤ¤¤ÆºîÀ®¤µ¤ì¤¿¥é¥¤¥Ö¥é¥ê¤Ê¤Î¤Ç¡¢¤½¤Î»ÈÍѤˤÏͽ¤á Boost ¤ò¡Ê ver1.40.0 °Ê¹ß¡Ë¤ò¥¤¥ó¥¹¥È¡¼¥ë¤·¤Æ¤ª¤¤¤Æ¤¯¤À¤µ¤¤¡£¾Ü¤·¤¤ÊýË¡¤Ï Boost ËܲȤ«¡¢±Ñ¸ì¤¬¶ì¼ê¤Ê¾ì¹ç¤Ë¤Ï Let's Boost ( http://www.kmonos.net/alang/boost/ ) ¤ò»²¾È¤¹¤ë¤È¤è¤¤¤Ç¤·¤ç¤¦¡£
-Boost ¤ÏÊØÍø¤Ê¥é¥¤¥Ö¥é¥ê¤Ê¤Î¤Ç¡¢¶äÅ·¥é¥¤¥Ö¥é¥ê¤ò¥¤¥ó¥¹¥È¡¼¥ë¤·¤Ê¤¤¾ì¹ç¤Ç¤â¥ª¥¹¥¹¥á¤Ç¤¹¡£
+・インストールについて
-¡¦¥é¥¤¥»¥ó¥¹¤Ë¤Ä¤¤¤Æ
+銀天ライブラリはヘッダのみで構成されたライブラリです。
-LICENSE ¥Õ¥¡¥¤¥ë¤Ë¤Þ¤È¤á¤Æ¤¢¤ê¤Þ¤¹¡£´Êñ¤Ë¸À¤¦¤È zlib/libpng ¥é¥¤¥»¥ó¥¹¤Ç¤¹¡£
-½ÐÍè¤ë¸Â¤ê¿¤¯¤Î¿Í¤Ë»È¤Ã¤Æ¤â¤é¤¦¤¿¤á¡¢Èó¾ï¤Ë¤æ¤ë¤¤¥é¥¤¥»¥ó¥¹¤È¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£
-¤¹¤Ê¤ï¤Á¡¢»ÈÍѤϻäÍѾ¦ÍѤòÌä¤ï¤º¼«Í³¡¢²þÊѤäºÆÇÛÉۤ⤽¤Î»Ý¤òÌÀµ¤¹¤ì¤Ð¼«Í³¡¢ºî¤Ã¤¿¥×¥í¥°¥é¥à¤Î README ¤Ë¡Ö¶äÅ·¥é¥¤¥Ö¥é¥ê»È¤Ã¤¿¤è¡×¤È½ñ¤¯É¬Íפ⤢¤ê¤Þ¤»¤ó¡Ê½ñ¤¤¤Æ¤â¤é¤¨¤ë¤È´î¤Ó¤Þ¤¹¤¬¡Ë¡£
-¤È¤¤¤¦¤«¥³¡¼¥ÉÊÒ¤òÍøÍѤ¹¤ëÄøÅ٤Ǥ¢¤ì¤Ð¡¢¥½¡¼¥¹¥³¡¼¥ÉÆâ¤Ç¤¢¤Ã¤Æ¤â¡Ö¤³¤ì¤Ï¶äÅ·¥é¥¤¥Ö¥é¥ê¤Ë½ñ¤¤¤Æ¤¢¤Ã¤¿¤è¡×¤Ê¤ó¤Æ¸ÀµÚ¤¹¤ëɬÍפϤ¢¤ê¤Þ¤»¤ó¡Ê´Ø¿ô´Ý¤´¤È¥³¥Ô¥Ú¤¹¤ë¥ì¥Ù¥ë¤À¤ÈήÀФ˽ñ¤¤¤ÆÍߤ·¤¤¤Ç¤¹¤¬¡Ë¡£
-¤É¤¦¤¾¤ªµ¤·Ú¤Ë»È¤Ã¤Æ¤¯¤À¤µ¤¤¡£
+・ホームディレクトリ(このファイルがあるディレクトリ)にインクルードパスを通す
+・既存のインクルード用ディレクトリにライブラリのディレクトリ(このファイルと同
+ 階層にある gintenlib/ )をコピーする
+・銀天ライブラリを使いたいプログラムのある場所にライブラリのディレクトリをコピ
+ ーする(非推奨)
+ことによりインストールすることが出来ます。
-¡¦º¤¤Ã¤¿¤³¤È¤¬¤¢¤Ã¤¿¤é
+・・・と、その前に。
+銀天ライブラリは Boost C++ Libraries ( http://www.boost.org/ ) を用いて作成され
+たライブラリなので、その使用には予め Boost を( ver1.40.0 以降)をインストール
+しておいてください。
-¶äÅ·¿ïÉ®½¸ http://d.hatena.ne.jp/gintenlabo/ ¤Þ¤Ç¥¢¥¯¥»¥¹¤ò¤ª´ê¤¤¤·¤Þ¤¹¡£ wiki ¤È¤«¤Ï¼ûÍפ¬¤¢¤Ã¤¿¤éºî¤ë¤«¤â¤·¤ì¤Þ¤»¤ó¡£
-¤¢¤ë¤¤¤Ï¡¢¤Ä¤¤¤Ã¤¿¡¼ http://twitter.com/ ¤Ç #gintenlib ¤ò¤Ä¤±¤ÆÒ줯¤È¤«¡£³ä¤ÈÉÑÈˤ˥Á¥§¥Ã¥¯¤¹¤ëͽÄê¤Ê¤Î¤Ç¿ʬµ¤¤Å¤¯¤È»×¤¤¤Þ¤¹¡£
+・ライセンスについて
-¡¦º¤¤Ã¤¿¤³¤È¤¬Ìµ¤±¤ì¤Ð
+LICENSE ファイルにまとめてあります。簡単に言うと zlib/libpng ライセンスです。
+出来る限り多くの人に使ってもらうため、非常にゆるいライセンスとなっています。
-¤Ê¤¯¤Æ¤â¤¤¤¤¥é¥¤¥Ö¥é¥ê¤À¤±¤É¡¢»î¤·¤Ë»È¤Ã¤Æ¤ß¤ë¤È¡¢¾¯¤·¤ÏÊØÍø¤«¤â¤·¤ì¤Þ¤»¤ó¤è¡©
+・困ったことがあったら
-¡¦¹¹¿·ÍúÎò
-2009/12/09 ½éÈÇ
+銀天随筆集 http://d.hatena.ne.jp/gintenlabo/ までアクセスをお願いします。
<gintenlib/assign.hpp>
- assign ¡§ ¥³¥Ô¡¼¤µ¤ì¤ë¦¤ÎÅÔ¹ç¤òÍ¥À褹¤ë copy ¥¢¥ë¥´¥ê¥º¥à
+ assign : コピーされる側の都合を優先する copy アルゴリズム
- Àë¸À¡§
+ 宣言:
template< typename FwdOutIte, typename InIte >
InIte assign( FwdOutIte begin, FwdOutIte end, InIte src );
template< typename Range, typename InIte >
InIte assign( Range& dest, InIte src );
- µ¡Ç½¡§
- [ begin, end ) ¶è´Ö¡¢¤¢¤ë¤¤¤Ï¶è´Ö dest ¤ò¡¢¥¤¥Æ¥ì¡¼¥¿ src ¤Ë¤è¤Ã¤Æ½é´ü²½¤·¤Þ¤¹¡£
- Ìá¤êÃͤϺǸå¤ËÂåÆþ¤·¤¿ src ¤Î¼¡¤ÎÍ×ÁǤò¼¨¤¹¥¤¥Æ¥ì¡¼¥¿¤Ë¤Ê¤ê¤Þ¤¹¡£
+ 機能:
+ [ begin, end ) 区間、あるいは区間 dest を、イテレータ src によって初期化します。
+ 戻り値は最後に代入した src の次の要素を示すイテレータになります。
- Åù²Á¥³¡¼¥É¡§
- // ¥¤¥Æ¥ì¡¼¥¿ÈǤΤߵ½Ò
+ 等価コード:
+ // イテレータ版のみ記述
for( FwdOutIte ite = begin; ite != end; ++ite, ++src )
{
*ite = *src;
}
- »ÈÍÑÎ㡧
+ 使用例:
int a[10];
boost::array<int, 10> b;
- // a ¤ò¡¢boost::counting_iterator ¤ò»È¤¤ 1 ¡Á 10 ¤ÎÃͤǽé´ü²½
+ // a を、boost::counting_iterator を使い 1 〜 10 の値で初期化
gintenlib::assign( a, boost::counting_iterator<int>(1) );
- // b ¤òµÕ½ç¤Ë a ¤Ç½é´ü²½
+ // b を逆順に a で初期化
gintenlib::assign( b.rbegin(), b.rend(), &a[0] );
- // ɽ¼¨
+ // 表示
cout << gintenlib::list_format( a ) << endl;
cout << gintenlib::list_format( b ) << endl;
- Ê䡧
- ¡¦¼ç¤Ë¸ÇÄêĹ¤Î¥³¥ó¥Æ¥Ê¤ò½é´ü²½¤ò¤¹¤ë¾ìÌ̤òÁÛÄꤷ¤Æ¤¤¤Þ¤¹¡£
- ¡¦²ÄÊÑĹ¤Î¥³¥ó¥Æ¥Ê¤Î¾ì¹ç¤Ï¡¢insert_iterator ¤ò»È¤Ã¤Æ copy ¤·¤¿Êý¤¬¸ú²ÌŪ¤Ç¤¹¡£
+ 補足:
+ ・主に固定長のコンテナを初期化をする場面を想定しています。
+ ・可変長のコンテナの場合は、insert_iterator を使って copy した方が効果的です。
*/
namespace gintenlib
{
- // [ begin, end ) ¶è´Ö¤ò src ¤Ç½é´ü²½
+ // [ begin, end ) 区間を src で初期化
template< typename FwdOutIte, typename InIte >
inline InIte assign( FwdOutIte begin, FwdOutIte end, InIte src )
{
return src;
}
- // dest ¤ò src ¤Ç½é´ü²½
+ // dest を src で初期化
template< typename Range, typename InIte >
inline InIte assign( Range& dest, const InIte& src )
{
#define GINTENLIB_INCLUDED_BOOL_COMPARABLE_HPP_
/*
- bool_comparable : safe_bool¥¤¥Ç¥£¥ª¥àÄó¶¡
+ bool_comparable : safe_boolイディオム提供
- Àë¸À¡§
+ 宣言:
template<typename Derived>
class bool_comparable
{
public:
- // safe_bool ËÜÂÎ
+ // safe_bool 本体
operator unspecified_bool_type() const;
- // ÇÉÀ¸¤·¤¿¥¯¥é¥¹¤Î¦¤Ç operator! ¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¡¢
- // ÇÉÀ¸¤·¤¿¥¯¥é¥¹¤Î boolean_test() ¥á¥ó¥Ð´Ø¿ô¤¬¤¢¤ì¤Ð¤½¤ÎÈÝÄê¤òÊÖ¤¹¡£
- // operator!() ¤â boolean_test() ¤â¤Ê¤±¤ì¤Ð¡¢¥¨¥é¡¼
+ // 派生したクラスの側で operator! が定義されていない場合、
+ // 派生したクラスの boolean_test() メンバ関数があればその否定を返す。
+ // operator!() ã\82\82 boolean_test() ã\82\82ã\81ªã\81\91ã\82\8cã\81°ã\80\81ã\82¨ã\83©ã\83¼
bool operator!() const;
- // bool ¤È¤ÎÈæ³Ó¡£ int ¤Î¤È¤¤ÏÈ¿±þ¤·¤Ê¤¤¤è¤¦¤Ë¤Ê¤Ã¤Æ¤Þ¤¹
+ // bool との比較。 int のときは反応しないようになってます
friend bool operator==( const bool_comparable& lhs, bool rhs );
friend bool operator==( bool lhs, const bool_comparable& rhs );
friend bool operator!=( const bool_comparable& lhs, bool rhs );
}; // class bool_comparable<Derived>
- // ¾¡¢¸Æ¤Ó½Ð¤µ¤ì¤ë¤È¥³¥ó¥Ñ¥¤¥ë¥¨¥é¡¼¤Ë¤Ê¤ë operator== ¤È operator!= ¤¬Àë¸À¤µ¤ì¤Æ¤¤¤Þ¤¹
+ // 他、呼び出されるとコンパイルエラーになる operator== と operator!= が宣言されています
- µ¡Ç½¡§
- boost::operators ¤ß¤¿¤¤¤Ê´¶¤¸¤Ë¡¢´Êñ¤Ë safe_bool ¥¤¥Ç¥£¥ª¥à¤ò¼Â¸½¤·¤Þ¤¹¡£
- »ÈÍÑË¡¤Ï¡¢bool_comparable ¤Î¥Æ¥ó¥×¥ì¡¼¥È°ú¿ô¤ËÀ½ºî¤¹¤ë¥¯¥é¥¹¤Î̾Á°¤òÆþ¤ì¤Æ public ·Ñ¾µ¡£
- ¤½¤·¤ÆÀ½ºî¤¹¤ë¥¯¥é¥¹¤Ë¡¢
+ 機能:
+ boost::operators みたいな感じに、簡単に safe_bool イディオムを実現します。
+ 使用法は、bool_comparable のテンプレート引数に製作するクラスの名前を入れて public 継承。
+ そして製作するクラスに、
bool operator!() const;
- ´Ø¿ô¤«¡¢¤¢¤ë¤¤¤Ï
+ 関数か、あるいは
bool boolean_test() const;
- ´Ø¿ô¤Î¤É¤Á¤é¤«¤òÄêµÁ¤¹¤ì¤Ð£Ï£Ë¤Ç¤¹¡ÊξÊý¤¢¤ë¾ì¹ç¤Ï operator!() ¤¬Í¥À褵¤ì¤Þ¤¹¡Ë¡£
+ 関数のどちらかを定義すればOKです(両方ある場合は operator!() が優先されます)。
- »ÈÍÑË¡ :
- // Îã¤È¤·¤Æ boost::optional Ū¤Ê²¿¤«¤òºî¤ê¤Þ¤·¤ç¤¦
+ 使用法 :
+ // 例として boost::optional 的な何かを作りましょう
#include <boost/scoped_ptr.hpp>
template<typename T>
class my_optional
- : public gintenlib::bool_comparable< my_optional<T> > // ¤³¤Î¤è¤¦¤Ë»È¤¦
+ : public gintenlib::bool_comparable< my_optional<T> > // このように使う
{
- // ËÜÂÎÉôʬ¤Ï¤Ê¤ó¤éµ¤¤Ë¤»¤º½ñ¤¤¤Æ¤è¤¤
+ // 本体部分はなんら気にせず書いてよい
public:
typedef T value_type;
reference operator*() { return *p; }
const_reference operator*() const { return *p; }
- // operator!() ¤ò³Î¼Â¤Ë¼ÂÁõ¤¹¤ë¤³¤È¤ò˺¤ì¤Ê¤±¤ì¤Ð¡£
+ // operator!() を確実に実装することを忘れなければ。
bool operator!() const
{
return !p;
}
- // ¤³¤ì¤Ë¤è¤ê¡¢boolÈæ³Ó¤â½ÐÍè¤ë¤è¤¦¤Ë¤Ê¤ë
+ // これにより、bool比較も出来るようになる
- // ¤Á¤Ê¤ß¤Ë operator!() ¤¸¤ã¤Ê¤¯¤Æ
+ // ちなみに operator!() じゃなくて
// bool boolean_test() const { return p.get(); }
- // ¤³¤ì¤Ç¤â¤¤¤¤¡Ê¤½¤Î¾ì¹ç¡¢operator! ¤Ï¼«Æ°ÄêµÁ¡Ë
+ // これでもいい(その場合、operator! は自動定義)
- // ¤½¤Î¤Û¤«¡¢¥³¥Ô¡¼¥³¥ó¥¹¥È¥é¥¯¥¿¤È¤«ÂåÆþ±é»»»Ò¤È¤«¤ÏÌÌÅݤÀ¤«¤é¾Êά
+ // そのほか、コピーコンストラクタとか代入演算子とかは面倒だから省略
private:
- // ÌÌÅݤʥݥ¤¥ó¥¿´ÉÍý¤È¤«¤·¤¿¤¯¤Ê¤¤¤Î¤Ç scoped_ptr ¤ò»È¤¦
+ // 面倒なポインタ管理とかしたくないので scoped_ptr を使う
boost::scoped_ptr<T> p;
};
{
my_optional<int> a, b(1), c(0);
- // if ¤Î¾ò·ïÉô¤È¤·¤Æ
+ // if の条件部として
if( a )
{
assert( !"a is empty." );
}
- // && ¤ä || ¤ÈÁȤ߹ç¤ï¤»¤Æ
+ // && や || と組み合わせて
assert( b && c );
- // ¥¼¥í¤È¤ÎÈæ³Ó
+ // ゼロとの比較
assert( a == 0 && b != 0 && c != 0 );
- // assert( b == 1 ); // 1 ¤È¤ÏÈæ³Ó¤Ç¤¤Ê¤¤
+ // assert( b == 1 ); // 1 とは比較できない
- // bool ÃͤȤÎÈæ³Ó
+ // bool 値との比較
assert( a == false && b == true && c == true );
// static_cast
assert( static_cast<bool>(b) == static_cast<bool>(c) );
- // assert( a != b ); // ¥³¥ì¤Ï¥À¥á¡Ê¤â¤· b ¤È c ¤òÈæ³Ó¤·¤¿¤é¡©¡Ë
+ // assert( a != b ); // コレはダメ(もし b と c を比較したら?)
- Ãí°Õ»ö¹à¡§
- ¡¦boost::enable_if ¤ò»È¤Ã¤Æ¤¤¤Þ¤¹¡£¸Å¤¤¥³¥ó¥Ñ¥¤¥é¤Ç¤ÏÆ°¤¤Þ¤»¤ó¡£
- ¡¦¤½¤ì¤¬·ù¤Ê¤é GINTENLIB_BOOL_COMPARABLE_NO_ENABLE_IF ¥Þ¥¯¥í¤òÄêµÁ¤¹¤ì¤Ð£Ï£Ë¤Ç¤¹¡£
- ¡¦¤¿¤À¤·¡¢¤½¤Î¾ì¹ç¡¢¾å¤ÎÎã¤Ç¤Î¡Öb == 1¡×Ū¤Êɽ¸½¤¬¥³¥ó¥Ñ¥¤¥ëÄ̤äƤ·¤Þ¤¤¤Þ¤¹¡£
+ 注意事項:
+ ・boost::enable_if を使っています。古いコンパイラでは動きません。
+ ・それが嫌なら GINTENLIB_BOOL_COMPARABLE_NO_ENABLE_IF マクロを定義すればOKです。
+ ・ただし、その場合、上の例での「b == 1」的な表現がコンパイル通ってしまいます。
- ¡¦¡Ö a == b ¡×¤Î¤è¤¦¤Ê¡¢ÇÉÀ¸Àè¤Î¥¯¥é¥¹Æ±»Î¤Ç¤ÎÈæ³Ó¤Ï¡¢¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï¥³¥ó¥Ñ¥¤¥ë¥¨¥é¡¼¤Ë¤Ê¤ê¤Þ¤¹¡£
- ¡¦¤Ç¤¹¤¬¡¢ÅöÁ³¡¢ÇÉÀ¸Àè¤Ç operator== ¤òÄêµÁ¤·¤Æ¤ª¤±¤Ð¡¢¤¤Á¤ó¤ÈÈæ³Ó¤Ç¤¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£
- ¡¦¤¿¤À¤·¡¢ÇÉÀ¸Àè¤Î¥¯¥é¥¹¤¬¡Ö 0 ¤«¤é°ÅÌÛÊÑ´¹²Äǽ¡×¤Ç¤¢¤ê¡Öoperator==¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡×¾ì¹ç¤Ï¡¢
- ¡Ö x == 0 ¡×¤Î¤è¤¦¤ÊÈæ³Ó¤¬¡¢¥¼¥í¤È¤ÎÈæ³Ó¤Ë¸Â¤ê¤Ç¤¹¤¬¡¢½ÐÍè¤Ê¤¯¤Ê¤Ã¤Æ¤·¤Þ¤¤¤Þ¤¹:
+ ・「 a == b 」のような、派生先のクラス同士での比較は、デフォルトではコンパイルエラーになります。
+ ・ですが、当然、派生先で operator== を定義しておけば、きちんと比較できるようになります。
+ ・ただし、派生先のクラスが「 0 から暗黙変換可能」であり「operator==が定義されている」場合は、
+ 「 x == 0 」のような比較が、ゼロとの比較に限りですが、出来なくなってしまいます:
struct convertible_from_int
: gintenlib::bool_comparable<convertible_from_int>,
private boost::equality_comparable<convertible_from_int>
{
int value;
- convertible_from_int( int x = 0 ) : value(x) {} // int ¤«¤é°ÅÌÛÊÑ´¹¤Ç¤¤ë¤È¡¦¡¦¡¦
+ convertible_from_int( int x = 0 ) : value(x) {} // int から暗黙変換できると・・・
bool operator!() const { return value == 0; }
- // operator== ¤Ë¤è¤ëÈæ³Ó¤¬½ÐÍè¤ë¾ì¹ç
+ // operator== による比較が出来る場合
friend bool operator==( const convertible_from_int& lhs, const convertible_from_int& rhs )
{
return lhs.value == rhs.value;
int main()
{
convertible_from_int x, y = 2;
- assert( !x ); // ¤³¤¦¤¤¤¦¤Î¤ÏÉáÄ̤˽ÐÍè¤ë¤¬
+ assert( !x ); // こういうのは普通に出来るが
assert( y );
assert( x == false );
assert( y == true );
- // assert( x == 0 ); // ¥³¥ì¤¬¼Â¹Ô¤Ç¤¤Ê¤¤¡ÊÛ£Ëæ¤Ë¤Ê¤Ã¤Æ¤·¤Þ¤¦¡Ë
- // assert( y != 0 ); // ÅöÁ³¤³¤ì¤â¥À¥á
+ // assert( x == 0 ); // コレが実行できない(曖昧になってしまう)
+ // assert( y != 0 ); // 当然これもダメ
- assert( y == 2 ); // ¤Ç¤â¥³¥ì¤Ï£Ï£Ë
- assert( x != 1 ); // ¥³¥ì¤â£Ï£Ë
+ assert( y == 2 ); // でもコレはOK
+ assert( x != 1 ); // コレもOK
}
- ¡¦¤½¤Î¾ì¹ç¤Ï int ¤È¤ÎÈæ³Ó¤òÊ̸ÄÄêµÁ¤·¤Æ¤ä¤ì¤Ð£Ï£Ë¤Ç¤¹¡§
+ ・その場合は int との比較を別個定義してやればOKです:
struct convertible_from_int
: gintenlib::bool_comparable<convertible_from_int>,
private boost::equality_comparable<convertible_from_int>,
private boost::equality_comparable<convertible_from_int, int>
{
int value;
- convertible_from_int( int x = 0 ) : value(x) {} // int ¤«¤é°ÅÌÛÊÑ´¹¤Ç¤¤ë¾ì¹ç¤Ç¤â
+ convertible_from_int( int x = 0 ) : value(x) {} // int から暗黙変換できる場合でも
- bool boolean_test() const { return value; } // boolean_test ¤ò»È¤Ã¤Æ¤ß¤ë¡£
+ bool boolean_test() const { return value; } // boolean_test を使ってみる。
friend bool operator==( const piyo& lhs, const piyo& rhs )
{
return lhs.value == rhs.value;
}
- // int ¤È¤ÎÈæ³Ó¤òÌÀ¼¨Åª¤ËÄêµÁ¤µ¤¨¤¹¤ì¤Ð
+ // int との比較を明示的に定義さえすれば
friend bool operator==( const convertible_from_int& lhs, int rhs )
{
return lhs.value == rhs;
int main()
{
convertible_from_int x, y(2)
- assert( x == 0 ); // £Ï£Ë
+ assert( x == 0 ); // OK
assert( y != 0 );
}
namespace gintenlib
{
- // ¥Ø¥ë¥Ñ¹½Â¤ÂÎ
+ // ヘルパ構造体
struct bool_comparable_helper
{
- // operator bool_type() ¤ÎÌá¤êÃͤȤ·¤Æ»È¤ï¤ì¤ëÃÍ
+ // operator bool_type() の戻り値として使われる値
void bool_value() const {}
private:
- // ¥³¥ó¥Ñ¥¤¥ë¥¨¥é¡¼¤òµ¯¤³¤¹¤¿¤á¤Î private ´Ø¿ô
+ // コンパイルエラーを起こすための private 関数
bool this_type_does_not_support_comparisons_();
};
- // ËÜÂÎ
+ // 本体
template<typename Derived>
class bool_comparable
{
- // safe-bool ¤Ë»È¤¦·¿¡Ê¥á¥ó¥Ð´Ø¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¡Ë
+ // safe-bool に使う型(メンバ関数へのポインタ)
typedef void (bool_comparable::*bool_type)() const;
- // ÇÉÀ¸¤·¤¿¥¯¥é¥¹¤òÆÀ¤ë´Ø¿ô
+ // 派生したクラスを得る関数
const Derived& derived() const { return *static_cast<const Derived*>(this); }
Derived& derived() { return *static_cast< Derived*>(this); }
- // ¾¤Î¥Æ¥ó¥×¥ì¡¼¥È¤Ç¤â derived ¤Ï»È¤¤¤¿¤¤¤¼
+ // 他のテンプレートでも derived は使いたいぜ
template<typename U> friend class bool_comparable;
public:
- // ËÜÂê
+ // 本題
operator bool_type() const
{
return bool_test_() ? bool_value_() : 0;
- // bool_test_, bool_value_ ¤Ï¸å¤ÇÄêµÁ¤¹¤ë
+ // bool_test_, bool_value_ は後で定義する
}
- // bool ¤È¤ÎÈæ³Ó
+ // bool との比較
#ifndef GINTENLIB_BOOL_COMPARABLE_NO_ENABLE_IF
- // enable_if ¤Ç bool ¤ÈÈæ³Ó¤¹¤ë»þ¤À¤±Í¸ú¤Ë¤¹¤ë¤³¤È¤Ç¡¢x == 1 ¤Î¤è¤¦¤ÊÈæ³Ó¤ò̵Îϲ½¤¹¤ë
- // todo: g++ °Ê³°¤Î¥³¥ó¥Ñ¥¤¥é¤Ç¤ÎÆ°ºî¥Á¥§¥Ã¥¯
+ // enable_if で bool と比較する時だけ有効にすることで、x == 1 のような比較を無力化する
+ // todo: g++ 以å¤\96ã\81®ã\82³ã\83³ã\83\91ã\82¤ã\83©ã\81§ã\81®å\8b\95ä½\9cã\83\81ã\82§ã\83\83ã\82¯
- // ¼ÂÁõ
+ // 実装
template<typename U>
friend typename enable_if<boost::is_same<U, bool>, bool>::type
operator==( const Derived& lhs, U rhs )
#else // #ifndef GINTENLIB_BOOL_COMPARABLE_NO_ENABLE_IF
- // °ì±þ enable_if ¤ò»È¤ï¤Ê¤¤ÈǤâÍÑ°Õ
- // ¤³¤Î¾ì¹ç¡¢ x == 1 ¤Î¤è¤¦¤Êɽ¸½¤¬Ä̤äƤ·¤Þ¤¦¤¬»ÅÊý¤Ê¤¤¤Í
+ // 一応 enable_if を使わない版も用意
+ // この場合、 x == 1 のような表現が通ってしまうが仕方ないね
friend bool operator==( const Derived& lhs, bool rhs )
{
return static_cast<bool>(lhs) == rhs;
#endif // #ifndef GINTENLIB_BOOL_COMPARABLE_NO_ENABLE_IF
private:
- // ¼ÂÁõÊä½õ
- // bool_type ¤È¤·¤ÆÊÖ¤¹ÃÍ
+ // 実装補助
+ // bool_type として返す値
static bool_type bool_value_()
{
- // ´Ø¿ô¤ò̵Â̤˺î¤é¤»¤Ê¤¤¹©Éס£¤É¤¦¤» bool_type ¤ÎÃͤϻȤï¤Ê¤¤¤·
+ // 関数を無駄に作らせない工夫。どうせ bool_type の値は使わないし
return reinterpret_cast<bool_type>( &bool_comparable_helper::bool_value );
}
- // ¥Æ¥¹¥È´Ø¿ô
- // ¤Þ¤º Derived::operator!() ¤ò¸«¤Ë¹Ô¤¯
+ // テスト関数
+ // まず Derived::operator!() を見に行く
bool bool_test_() const
{
return !( !derived() );
}
public:
- // Derived ¦¤Ç operator!() ¤¬ÄêµÁ¤µ¤ì¤Æ̵¤¤¤Ê¤é
- // Derived::boolean_test() ´Ø¿ô¤¬¤Ê¤¤¤«Ãµ¤·¡¢Ìµ¤±¤ì¤Ð¥³¥ó¥Ñ¥¤¥ë¥¨¥é¡¼
+ // Derived 側で operator!() が定義されて無いなら
+ // Derived::boolean_test() é\96¢æ\95°ã\81\8cã\81ªã\81\84ã\81\8bæ\8e¢ã\81\97ã\80\81ç\84¡ã\81\91ã\82\8cã\81°ã\82³ã\83³ã\83\91ã\82¤ã\83«ã\82¨ã\83©ã\83¼
bool operator!() const
{
return !( derived().boolean_test() );
}
- // friend ´Ø¿ôÈÇ¡£Â¸ºß¤¹¤ë°ÕÌ£¤ÏÆäË̵¤¤¡£
+ // friend 関数版。存在する意味は特に無い。
friend bool boolean_test( const bool_comparable& x )
{
return x.bool_test_();
}
- // Èæ³Ó¤Ï¥¨¥é¡¼¤Ë¤Ê¤ë¡Ê Derived ¦¤ÇÆÃÊ̤ËÄêµÁ¤¹¤ì¤Ð£Ï£Ë¡Ë
+ // 比較はエラーになる( Derived 側で特別に定義すればOK)
- // ÅùÃÍÈæ³Ó
+ // 等値比較
friend bool operator==( const bool_comparable& lhs, const bool_comparable& rhs )
{
return bool_comparable_helper().this_type_does_not_support_comparisons_();
}
- // ÉÔÅùÃÍÈæ³Ó
+ // 不等値比較
friend bool operator!=( const bool_comparable& lhs, const bool_comparable& rhs )
{
return bool_comparable_helper().this_type_does_not_support_comparisons_();
}
protected:
- // ÇÉÀ¸¥¯¥é¥¹°Ê³°¤«¤é¤Î¹½Ã۶ػß
+ // 派生クラス以外からの構築禁止
bool_comparable() {}
~bool_comparable() {}
<gintenlib/call_traits.hpp>
- call_traits ¡§ boost::call_traits ¡Ü¦Á
+ call_traits : boost::call_traits +α
- Àë¸À¡§
+ 宣言:
template<typename T>
struct call_traits
: boost::call_traits<T>
typedef T type;
};
- µ¡Ç½¡§
- boost::call_traits ¤Ë¡ÖÍ¿¤¨¤é¤ì¤¿·¿¤ò¤½¤Î¤Þ¤ÞÊÖ¤¹¡×¥á¥¿´Ø¿ô¤Îµ¡Ç½¤ò²Ã¤¨¤¿¤â¤Î¤Ç¤¹¡£
- reference ¤ä param_type ¤Î¼èÆÀ¤â¤·¤¿¤¤¤·¡¢¥á¥¿´Ø¿ô¤È¤·¤Æ¤â»È¤¤¤¿¤¤¡¢¤Ê¤ó¤Æ¶ÉÌ̤ǻȤ¤¤Þ¤¹¡£
- ñ½ã¤Ë boost::call_traits ¤Ï gintenlib Æâ¤Ç¤Î»ÈÍѤ¬Â¿¤¤¤Î¤Ç¡¢Ã»½Ì¤È¤·¤Æ»È¤¦°ÕÌ£¤â¤¢¤ê¤Þ¤¹¡£
+ 機能:
+ boost::call_traits に「与えられた型をそのまま返す」メタ関数の機能を加えたものです。
+ reference や param_type の取得もしたいし、メタ関数としても使いたい、なんて局面で使います。
+ 単純に boost::call_traits は gintenlib 内での使用が多いので、短縮として使う意味もあります。
*/
namespace gintenlib
{
- // typename call_traits<T>::type ¤Ï T ¤ËÅù¤·¤¤
+ // typename call_traits<T>::type は T に等しい
template<typename T>
struct call_traits
: boost::call_traits<T>
<gintenlib/cast.hpp>
- cast ¡§ ÌÀ¼¨Åª¤Ê°ÅÌÛ¥¥ã¥¹¥È
+ cast : 明示的な暗黙キャスト
- Àë¸À¡õÄêµÁ¡§
- // °ú¿ô¤ò¤½¤Î¤Þ¤ÞÊÖ¤¹
+ 宣言&定義:
+ // 引数をそのまま返す
template<typename T>
inline T cast( typename boost::call_traits<T>::param_type x ) { return x; }
- µ¡Ç½¡§
- °ÅÌÛÊÑ´¹¤òÌÀ¼¨Åª¤Ë¹Ô¤¦¤¿¤á¤Î¥¥ã¥¹¥È¤Ç¤¹¡£ cast<void*>( 0 ) ¤Î¤è¤¦¤Ë»È¤¤¤Þ¤¹¡£
- ¼ç¤Ë¿½ÅÄêµÁ¤µ¤ì¤¿´Ø¿ô¤Î¸Æ¤Ó½Ð¤·¤òÀ©¸æ¤¹¤ë¤È¤¤Ë»È¤¤¤Þ¤¹¡£
- Boost ¤Ë¤â implicit_cast ¤È¤¤¤¦Æ±µ¡Ç½¤Î¥¥ã¥¹¥È¤¬¤¢¤ê¤Þ¤¹¤¬¡¢
- ¤³¤Á¤é¤Î¤Û¤¦¤¬Ê¸»ú¿ô¤¬¾¯¤Ê¤¤¤È¤¤¤¦ÅÀ¤ÇÍøÅÀ¤¬¤¢¤ê¤Þ¤¹¡£
+ 機能:
+ 暗黙変換を明示的に行うためのキャストです。 cast<void*>( 0 ) のように使います。
+ 主に多重定義された関数の呼び出しを制御するときに使います。
+ Boost にも implicit_cast という同機能のキャストがありますが、
+ こちらのほうが文字数が少ないという点で利点があります。
- »ÈÍÑÎ㡧
- void hoge( int ){ cout << "int ÈǤǤ¹\n"; }
- void hoge( void* ){ cout << "void* ÈǤǤ¹\n"; }
+ 使用例:
+ void hoge( int ){ cout << "int 版です\n"; }
+ void hoge( void* ){ cout << "void* 版です\n"; }
- // ¥¯¥é¥¹¤ËÂФ·¤Æ
- // noncopyable ¤Ê¥¯¥é¥¹¤Ë¤·¤Æ¤ª¤¯
+ // クラスに対して
+ // noncopyable なクラスにしておく
class base : boost::noncopyable {};
struct derived : base {};
- void fuga( base& ){ cout << "base& ÈǤǤ¹\n"; }
- void fuga( derived& ){ cout << "derived& ÈǤǤ¹\n"; }
+ void fuga( base& ){ cout << "base& 版です\n"; }
+ void fuga( derived& ){ cout << "derived& 版です\n"; }
int main()
{
- // ͽ¤á using Àë¸À¤¹¤ì¤Ð»Íʸ»ú¤Ç»È¤¨¤Æ¹¬¤»
+ // 予め using 宣言すれば四文字で使えて幸せ
using gintenlib::cast;
- hoge( 0 ); // int ÈÇ
- hoge( cast<void*>(0) ); // void* ÈÇ¡£static_cast<void*>(0) ¤Ç¤â£Ï£Ë¤À¤¬Ä¹¤¤
+ hoge( 0 ); // int 版
+ hoge( cast<void*>(0) ); // void* 版。static_cast<void*>(0) でもOKだが長い
- derived x; // ¤¢¤ë¤¤¤Ï base x;
- fuga( x ); // ¥Ç¥Õ¥©¥ë¥È¸Æ¤Ó½Ð¤·
- fuga( cast<base&>(x) ); // base& ÈÇ¡£
- fuga( cast<derived&>(x) ); // derived& ÈÇ¡£base x; ¤Î¾ì¹ç¤Ï¥³¥ó¥Ñ¥¤¥ë¥¨¥é¡¼
- // static_cast ¤À¤È¡¢¥³¥ó¥Ñ¥¤¥ë¥¨¥é¡¼¤Ë¤Ê¤é¤Ê¤¤
+ derived x; // あるいは base x;
+ fuga( x ); // デフォルト呼び出し
+ fuga( cast<base&>(x) ); // base& 版。
+ fuga( cast<derived&>(x) ); // derived& ç\89\88ã\80\82base x; ã\81®å ´å\90\88ã\81¯ã\82³ã\83³ã\83\91ã\82¤ã\83«ã\82¨ã\83©ã\83¼
+ // static_cast だと、コンパイルエラーにならない
}
- Ê䡧
- ¡¦°ÅÌÛÊÑ´¹¤òÌÀ¼¨Åª¤Ë¤ä¤Ã¤Æ²¿¤¬³Ú¤·¤¤¤«¤È¤¤¤¨¤Ð¡¦¡¦¡¦»ÈÍÑÎã¤ò¸«¤Æ¤¯¤À¤µ¤¤¡£¤³¤ì¤¬Á´¤Æ¤Ç¤¹¡£
- ¡¦¤³¤Î¤è¤¦¤Ë¡¢´Ø¿ô¤Î¿½ÅÄêµÁ¤ä¥Æ¥ó¥×¥ì¡¼¥È¤ËÂФ·¡¢Àµ¤·¤¤¤â¤Î¤ò»ØÄꤹ¤ë¤È¤¤Ë»È¤¨¤Þ¤¹¡£
- ¡¦static_cast ¤È¤Î°ã¤¤¤Ï¡¢ Source ¤Î·¿¤¬°ÅÌÛŪ¤Ë Target ¤ËÊÑ´¹¤Ç¤¤ë»þ¤À¤±¥¥ã¥¹¥È¤Ç¤¤ëÅÀ¡£
- ¡¦¤Þ¤¡ÉáÄÌ¤Ï static_cast ¤Ç¤â½½Ê¬¤Ê¤ó¤Ç¤¹¤¬¡¢¥¯¥é¥¹¤Î·Ñ¾µ¤È¤«¤ò»È¤¦¤È¡¢¤ä¤Ã¤Ñ¤ê´í¸±¤Ê¤Î¤Ç¡£
- ¡¦¾¯¤·Á°¤Þ¤Ç¤Î¼ÂÁõ¤Ï boost::enable_if ¤ò»È¤Ã¤Æ¤¤¤Þ¤·¤¿¤¬¡¢½¤Àµ¤µ¤ì¤Þ¤·¤¿¡£
- ¡¦boost::call_traits ¤µ¤¨Æ°¤±¤ÐÆ°¤¤Þ¤¹¡£
+ 補足:
+ ・暗黙変換を明示的にやって何が楽しいかといえば・・・使用例を見てください。これが全てです。
+ ・このように、関数の多重定義やテンプレートに対し、正しいものを指定するときに使えます。
+ ・static_cast との違いは、 Source の型が暗黙的に Target に変換できる時だけキャストできる点。
+ ・まぁ普通は static_cast でも十分なんですが、クラスの継承とかを使うと、やっぱり危険なので。
+ ・少し前までの実装は boost::enable_if を使っていましたが、修正されました。
+ ・boost::call_traits さえ動けば動きます。
*/
namespace gintenlib
{
- // °ÅÌÛ¥¥ã¥¹¥È´Ø¿ô
+ // 暗黙キャスト関数
template<typename T>
inline T cast( typename boost::call_traits<T>::param_type x )
{
<gintenlib/clonable_ptr.hpp>
- clonable_ptr ¡§ ¿¼¤¤¥³¥Ô¡¼¤¬²Äǽ¤Ê»²¾È¥«¥¦¥ó¥È¼°¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿
+ clonable_ptr ï¼\9a æ·±ã\81\84ã\82³ã\83\94ã\83¼ã\81\8cå\8f¯è\83½ã\81ªå\8f\82ç\85§ã\82«ã\82¦ã\83³ã\83\88å¼\8fã\82¹ã\83\9eã\83¼ã\83\88ã\83\9dã\82¤ã\83³ã\82¿
- Àë¸À¡§
+ 宣言:
template<typename T>
struct clonable_ptr
{
typedef T* pointer;
typedef typename boost::add_reference<T>::type reference;
- // ¥Ç¥Õ¥©¥ë¥È¥³¥ó¥¹¥È¥é¥¯¥¿
+ // ã\83\87ã\83\95ã\82©ã\83«ã\83\88ã\82³ã\83³ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
clonable_ptr();
- // ¥Ý¥¤¥ó¥¿¤«¤éºî¤ë¥³¥ó¥¹¥È¥é¥¯¥¿
+ // ã\83\9dã\82¤ã\83³ã\82¿ã\81\8bã\82\89ä½\9cã\82\8bã\82³ã\83³ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
template<typename U>
explicit clonable_ptr( U* p );
template<typename U>
clonable_ptr( const clonable_ptr<U>& src );
- // ¥Ç¥¹¥È¥é¥¯¥¿
+ // ã\83\87ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
~clonable_ptr() {}
// nothrow swap
void reset( U* p );
- // ¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿´ØÏ¢¤Î¤¢¤ì¤³¤ì
+ // スマートポインタ関連のあれこれ
T* get() const;
friend T* get_pointer( const clonable_ptr& );
T* operator->() const;
bool operator!() const;
- // »²¾È¥«¥¦¥ó¥È¤Î¿ô¤òÊÖ¤¹
+ // 参照カウントの数を返す
int use_count() const;
- // »²¾È¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤¬¡¢¤³¤Î¥Ý¥¤¥ó¥¿¤Î¤ß¤«¤é»²¾È¤µ¤ì¤Æ¤¤¤ë¾ì¹ç true
+ // 参照するオブジェクトが、このポインタのみから参照されている場合 true
bool unique() const;
- // ¥ª¥Ö¥¸¥§¥¯¥È¤ÎÊ£À½¤òºî¤ê½Ð¤·¤ÆÊÖ¤¹
+ // オブジェクトの複製を作り出して返す
clonable_ptr<typename boost::remove_const<T>::type> clone() const;
- // unique ¤Ç¤Ê¤±¤ì¤Ð»²¾È¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤òÊ£À½¤·¤Æ unique ¤Ë¤¹¤ë
+ // unique でなければ参照するオブジェクトを複製して unique にする
void to_unique();
- // boost::shared_ptr ¤Ø¤ÎÊÑ´¹
+ // boost::shared_ptr への変換
boost::shared_ptr<T> to_shared() const;
friend boost::shared_ptr<T> to_shared( const clonable_ptr& target );
};
- // Èæ³Ó
+ // 比較
template<typename T1, typename T2>
inline bool operator==( const clonable_ptr<T1>&, const clonable_ptr<T2>& );
template<typename T1, typename T2>
template<typename T1, typename T2>
friend clonable_ptr<T1> const_pointer_cast( const clonable_ptr<T2>& src );
- µ¡Ç½¡§
- ÂоݤΡֿ¼¤¤¥³¥Ô¡¼¡×¤òÀ¸À®¤Ç¤¤ë»²¾È¥«¥¦¥ó¥È¼°¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¡£
- ¼ç¤ËÂоݤη¿¤òÀµ³Î¤Ëµ²±¤·Ê£À½¤¹¤ëÄøÅ٤ε¡Ç½¤ò»ý¤Á¤Þ¤¹¡£
- ÆäËÊØÍø¤Ê¤Î¤¬ to_unique ¥á¥ó¥Ð´Ø¿ô¤Ç¡¢¤³¤Î¥Ý¥¤¥ó¥¿¤Î¸ºßÍýͳ¤ÎÂçȾ¤¬¤³¤ì¤Ë½¸Ì󤵤ì¤Þ¤¹¡£
- ¥³¥Ô¡¼¤Ë¥³¥¹¥È¤Î¤«¤«¤ë¥ª¥Ö¥¸¥§¥¯¥È¤ò°·¤¦¤È¤¡¢ÉáÃʤÏÀõ¤¤¥³¥Ô¡¼¤Ç¥³¥Ô¡¼¥³¥¹¥È¤òºï¸º¡¢
- ¥ª¥Ö¥¸¥§¥¯¥È¤ËÊѹ¹¤ò²Ã¤¨¤ë¤È¤¤Ï¤½¤ÎÁ°¤Ë to_unique ¤ò¸Æ¤Ó½Ð¤¹¡¢¤Ê¤ó¤Æ»È¤¤Êý¤¬°ìÈÌŪ¤«¤È¡£
- ¤â¤Á¤í¤ó¡¢¡ÖÂоݤΥª¥Ö¥¸¥§¥¯¥È¤ÎÀµ³Î¤Ê¥³¥Ô¡¼¤òºî¤ì¤ë¡×¤È¤¤¤¦ÅÀ¤ËÃåÌܤ·¤¿»È¤¤Êý¤â¥¢¥ê¤Ç¤¹¡£
- ¹âµ¡Ç½¤Ç¤¹¤¬¡¢¥³¥Ô¡¼ÉÔǽ¤Ê¥ª¥Ö¥¸¥§¥¯¥È¤Ï¤½¤â¤½¤â³ÊǼ¤Ç¤¤Ê¤¤¤Î¤Ç¡¢¤½¤³¤À¤±¤ÏÃí°Õ¤¬É¬Íס£
- ¤Þ¤¿¡¢²¾ÁÛ´Ø¿ô¤È¥Æ¥ó¥×¥ì¡¼¥È¤ò»È¤Ã¤¿¼ÂÁõ¤Ê¤Î¤Ç¡¢¥³¥ó¥Ñ¥¤¥ë¸å¤Î¥µ¥¤¥º¤ÏÂ礤¯¤Ê¤ê¤Þ¤¹¡£
- ÊØÍø¤À¤±¤ÉÍê¤ê¤¹¤®¤º¡¢Â¾¤Î¾å¼ê¤¤¼ÂÁõ¤¬¤¢¤ì¤Ð¤½¤Á¤é¤òÍ¥À褷¤Æ¤ä¤Ã¤Æ¤¯¤À¤µ¤¤¡£
+ 機能:
+ 対象の「深いコピー」を生成できる参照カウント式スマートポインタ。
+ 主に対象の型を正確に記憶し複製する程度の機能を持ちます。
+ 特に便利なのが to_unique メンバ関数で、このポインタの存在理由の大半がこれに集約されます。
+ コピーにコストのかかるオブジェクトを扱うとき、普段は浅いコピーでコピーコストを削減、
+ オブジェクトに変更を加えるときはその前に to_unique を呼び出す、なんて使い方が一般的かと。
+ もちろん、「対象のオブジェクトの正確なコピーを作れる」という点に着目した使い方もアリです。
+ 高機能ですが、コピー不能なオブジェクトはそもそも格納できないので、そこだけは注意が必要。
+ また、仮想関数とテンプレートを使った実装なので、コンパイル後のサイズは大きくなります。
+ 便利だけど頼りすぎず、他の上手い実装があればそちらを優先してやってください。
*/
{
namespace detail_
{
- // ¥«¥¦¥ó¥È¤µ¤ì¤ë¥ª¥Ö¥¸¥§¥¯¥È
+ // カウントされるオブジェクト
struct clonable_counted_base
: reference_counter<clonable_counted_base>
{
// virtual destructor
virtual ~clonable_counted_base(){}
- // ËÜÂΡ¢Ê£À½¤òºî¤ë
+ // 本体、複製を作る
typedef std::pair<clonable_counted_base*, void*> cloned_type;
virtual cloned_type clone() const = 0;
}; // clonable_counted_base
- // make_clonable ÍÑ impl
+ // make_clonable 用 impl
template< typename T >
struct clonable_counted_impl_obj
: clonable_counted_base
{
- // À©ºî
+ // 制作
explicit clonable_counted_impl_obj( const T& src )
: obj(src) {}
- // ²òÊü
+ // 解放
// virtual ~clonable_counted_impl_obj() {}
- // Ê£À½À©ºî
+ // 複製制作
typedef typename boost::remove_const<T>::type T_;
typedef clonable_counted_impl_obj<T_> impl_type;
return std::make_pair( pt, pt->get() );
}
- // ÊÝ»ý¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¢¥É¥ì¥¹¤ò¼èÆÀ
+ // 保持するオブジェクトのアドレスを取得
T* get() { return &obj; }
private:
}; // clonable_counted_impl_obj
- // ¥Ý¥¤¥ó¥¿¤ÇÅϤµ¤ì¤¿¾ì¹ç¤ËÂбþ
+ // ポインタで渡された場合に対応
template< typename T >
struct clonable_counted_impl_p
: clonable_counted_base
explicit clonable_counted_impl_p( T* p_ )
: p( p_ ) {}
- // ²òÊü½èÍý
+ // 解放処理
virtual ~clonable_counted_impl_p()
{
boost::checked_delete(p);
}
- // Ê£À½À©ºî
+ // 複製制作
using clonable_counted_base::cloned_type;
typedef typename boost::remove_const<T>::type T_;
typedef clonable_counted_impl_obj<T_> impl_type;
return std::make_pair( pt, pt->get() );
}
- // ÊÝ»ý¤¹¤ë¥Ý¥¤¥ó¥¿¤Î¥¢¥É¥ì¥¹¤ò¼èÆÀ
+ // 保持するポインタのアドレスを取得
T* get() const { return p; }
private:
}; // clonable_counted_impl_p
- // cloning_ptr ÍѤλ²¾È¥«¥¦¥ó¥¿
+ // cloning_ptr ç\94¨ã\81®å\8f\82ç\85§ã\82«ã\82¦ã\83³ã\82¿
struct clonable_count
{
- // ¥Ç¥Õ¥©¥ë¥È½é´ü²½
+ // デフォルト初期化
clonable_count() {}
- // T ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È p_ ¤Ë´ØÏ¢ÉÕ¤±¤é¤ì¤¿¥«¥¦¥ó¥¿¤òºî¤ë
+ // T 型のオブジェクト p_ に関連付けられたカウンタを作る
template<typename T>
explicit clonable_count( T* p_ )
: p( p_ ? new clonable_counted_impl_p<T>(p_) : 0 ) {}
- // clonable_counted_base* ¤«¤é¤Î¹½ÃÛ
+ // clonable_counted_base* からの構築
clonable_count( clonable_counted_base* p_ )
: p( p_ ) {}
- // ¥Ç¥¹¥È¥é¥¯¥¿¤Ï¼«Æ°ÄêµÁ¤µ¤ì¤¿ÅۤǤª£ë
+ // デストラクタは自動定義された奴でおk
// ~clonable_count(){}
// no throw swap
one.swap( another );
}
- // Ê£À½À©ºî
+ // 複製制作
typedef std::pair<clonable_count, void*> cloned_type;
- // clonable_count ¤Ï clonable_counted_base* ¤«¤é°ÅÌÛÊÑ´¹¤Ç¤¤ë
+ // clonable_count は clonable_counted_base* から暗黙変換できる
cloned_type clone() const
{
return p ? cloned_type( p->clone() ) : cloned_type( 0, 0 );
}
- // ÆâÉô¤Î¥«¥¦¥ó¥È¤ò»ÈÍѤ¹¤ë
+ // 内部のカウントを使用する
int use_count() const { return p ? p->use_count() : 0; }
- // ¥æ¥Ë¡¼¥¯¤«Èݤ«
+ // ユニークか否か
bool unique() const { return use_count() == 1; }
private:
typedef detail_::clonable_count clonable_count;
public:
- // ¥Ç¥Õ¥©¥ë¥È¥³¥ó¥¹¥È¥é¥¯¥¿
+ // ã\83\87ã\83\95ã\82©ã\83«ã\83\88ã\82³ã\83³ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
clonable_ptr() : p(), count() {}
- // ¥Ý¥¤¥ó¥¿¤«¤éºî¤ë¥³¥ó¥¹¥È¥é¥¯¥¿
+ // ã\83\9dã\82¤ã\83³ã\82¿ã\81\8bã\82\89ä½\9cã\82\8bã\82³ã\83³ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
template<typename U>
explicit clonable_ptr( U* p_ )
: p( p_ ), count( p_ ) {}
- // copy constructor ¤Ç¤Ï clone ¤·¤Ê¤¤
+ // copy constructor では clone しない
clonable_ptr( const clonable_ptr& src )
: p( src.p ), count( src.count ) {}
template<typename U>
clonable_ptr( const clonable_ptr<U>& src )
: p( src.p ), count( src.count ) {}
- // ¥Ç¥¹¥È¥é¥¯¥¿¤Î½èÍý¤Ï clonable_count ¤ËǤ¤»¤ë
+ // デストラクタの処理は clonable_count に任せる
// ~clonable_ptr() {}
// swap
one.swap( another );
}
- // ÂåÆþ±é»»
+ // 代入演算
this_type& operator=( const this_type& rhs )
{
this_type(rhs).swap( *this );
this_type(p_).swap( *this );
}
- // get() ¤µ¤¨ÄêµÁ¤¹¤ì¤Ð¸å¤Ï pointer_facade ¤Ë¤è¤ê¼«Æ°
+ // get() さえ定義すれば後は pointer_facade により自動
T* get() const { return p; }
- // ËÜÂÎ
+ // 本体
- // Ê£À½À©ºî
+ // 複製制作
typedef typename boost::remove_const<T>::type T_;
typedef clonable_ptr<T_> cloned_type;
cloned_type clone() const
{
return cloned_type( count.clone() );
}
- // »²¾È¥«¥¦¥ó¥È·×»»
+ // 参照カウント計算
int use_count() const { return count.use_count(); }
bool unique() const { return count.unique(); }
- // unique ¤¸¤ã¤Ê¤±¤ì¤ÐÊ£À½¤·¤Æ unique ¤Ë
+ // unique じゃなければ複製して unique に
void to_unique()
{
if( p != 0 && !unique() )
to_shared_helper( const clonable_count& count_ )
: count( count_ ) {}
- // ¥Ç¥¹¥È¥é¥¯¥¿¤ÇŬµ¹¤ä¤Ã¤Æ¤¯¤ì¤ë¤Î¤Ç
- // operator() ¤Ç¤Ï²¿¤â¹Ô¤ï¤Ê¤¤
+ // デストラクタで適宜やってくれるので
+ // operator() では何も行わない
void operator()( T* ) const {}
private:
clonable_count count;
};
- // shared_ptr ¤ËÊÑ´¹
+ // shared_ptr に変換
boost::shared_ptr<T> to_shared() const
{
return p ? boost::shared_ptr<T>( p, to_shared_helper(count) ) : boost::shared_ptr<T>();
/*
<gintenlib/context_error.hpp>
- context_error: ʸ̮¥¨¥é¡¼¥¯¥é¥¹
+ context_error: æ\96\87è\84\88ã\82¨ã\83©ã\83¼ã\82¯ã\83©ã\82¹
- ÀâÌÀ¡§
- ´Ø¿ô¤Ê¤É¤ò¡¢¸Æ¤Ó½Ð¤·¤Æ¤Ï¤¤¤±¤Ê¤¤¾õ¶·¤Ç¸Æ¤Ó½Ð¤·¤¿¤È¤¤ËÁ÷½Ð¤µ¤ì¤ëÎã³°¤Ç¤¹¡£
+ 説明:
+ 関数などを、呼び出してはいけない状況で呼び出したときに送出される例外です。
*/
<gintenlib/d_enable_if.hpp>
- d_enable_if ¡§ °ú¿ôÍÑ¤Ë boost::enable_if ¤Î»È¤¤¾¡¼ê¤ò¾¯¤·¤À¤±²þÁ±
+ d_enable_if : 引数用に boost::enable_if の使い勝手を少しだけ改善
- Àë¸À¡§
+ 宣言:
struct dummy_arg_t {};
template<typename Cond>
template<typename Cond>
struct d_disable_if : disable_if<Cond, dummy_arg_t> {};
- »ÈÍÑÎ㡧
- // gintenlib::cast ¤Î¼ÂÁõ¤¬¤¤¤¤»ÈÍÑÎã¤Ê¤Î¤Ç¤½¤ì¤Ç¡ÊÃí¡§ÀΤμÂÁõ¡¢º£¤Ï enable_if ¤Ï»È¤Ã¤Æ¤Þ¤»¤ó¡Ë
- using namespace gintenlib; // gintenlib::d_enable_if ¤È¤«½ñ¤¯¤ÎÀµÄ¾¤á¤ó¤É¤¤
+ 使用例:
+ // gintenlib::cast の実装がいい使用例なのでそれで(注:昔の実装、今は enable_if は使ってません)
+ using namespace gintenlib; // gintenlib::d_enable_if とか書くの正直めんどい
- // °ú¿ô¤ò Target ·¿¤Ø°ÅÌÛÊÑ´¹¤¹¤ë
- // Ä̾ïÈÇ¡¢Target ¤¬»²¾È·¿¤Ç¤Ê¤±¤ì¤Ð¤³¤Ã¤Á¤¬¸Æ¤Ð¤ì¤ë
+ // 引数を Target 型へ暗黙変換する
+ // 通常版、Target が参照型でなければこっちが呼ばれる
template< typename Target, typename Source >
inline Target cast( const Source& src,
typename d_disable_if< boost::is_reference<Target> >::type = dummy_arg_t() )
return src;
}
- // »²¾ÈÈÇ
+ // 参照版
template< typename Target, typename Source >
inline Target cast( Source& src,
typename d_enable_if< boost::is_reference<Target> >::type = dummy_arg_t() )
return src;
}
- // ¤Ê¤¼¤³¤¦½ñ¤¯¤«¡¢¤Á¤ç¤Ã¤È¤À¤±Êä¡£
- // ¸«¤¿¤È¤ª¤êÂèÆó°ú¿ô¤Ï¥À¥ß¡¼¤Ç¡¢¤³¤¦½ñ¤«¤Ê¤¯¤Æ¤â¾ïÅå¼êÃʤȤ·¤Æ
+ // なぜこう書くか、ちょっとだけ補足。
+ // 見たとおり第二引数はダミーで、こう書かなくても常套手段として
// typename boost::disable_if< boost::is_reference<Target> >::type* = 0
- // ¤Èµ½Ò¤¹¤ë¤³¤È¤â½ÐÍè¤ë¤Î¤À¤¬¡¢¤³¤Î¾ì¹ç¡¢¤¦¤Ã¤«¤ê
- // cast<¤Ê¤ó¤¿¤é>( x, 0 );
- // ¤È¤«¸Æ¤Ó½Ð¤·¤¿¾ì¹ç¤Ë¤â¡Ê¥¨¥é¡¼¤Ë¤Ê¤ë¤Ù¤¤Ï¤º¤¬¡Ë¥³¥ó¥Ñ¥¤¥ë¤¬Ä̤äƤ·¤Þ¤¦¡£
- // ¥³¥ó¥Ñ¥¤¥ëÄ̤ë¤À¤±¤Ê¤é¤Þ¤À¤·¤â¡¢¤â¤· cast ¤¬£²°ú¿ô¥Ð¡¼¥¸¥ç¥ó¤Ç¿½ÅÄêµÁ¤µ¤ì¤Æ¤¤¤¿¾ì¹ç¡¢
- // ¡Ê¤¿¤È¤¨¤Ð cast<Src>( Target x, int param ) ¤È¤«¡Ë
- // cast<Src>( x, 1 ) ¤Ê¤é¥³¥ó¥Ñ¥¤¥ëÄ̤뤱¤É cast<Src>( x, 0 ) ¤À¤ÈÄ̤é¤Ê¤¤¤è¡¢
- // ¤È¤«¤¤¤¦°ÕÌ£ÉÔÌÀ¤Ê»öÂ֤ˤʤäƺ®Í𤹤붲¤ì¤¬¤¢¤ë¡£
- // d_disable_if ¤¬¤¢¤ë¤Î¤Ï¤½¤Î¤¿¤á¡¢ÀìÍѤΥ¯¥é¥¹¤òÍÑ°Õ¤·¤Æ¤ë¤Î¤Ç
- // ¤¦¤Ã¤«¤ê cast<Target>( x, 0 ) ¤È¤«¸Æ¤ó¤Ç¤â¥¨¥é¡¼¤Ë¤Ê¤ë¤Î¤Ç°Â¿´
+ // と記述することも出来るのだが、この場合、うっかり
+ // cast<なんたら>( x, 0 );
+ // とか呼び出した場合にも(エラーになるべきはずが)コンパイルが通ってしまう。
+ // コンパイル通るだけならまだしも、もし cast が2引数バージョンで多重定義されていた場合、
+ // (たとえば cast<Src>( Target x, int param ) とか)
+ // cast<Src>( x, 1 ) ならコンパイル通るけど cast<Src>( x, 0 ) だと通らないよ、
+ // とかいう意味不明な事態になって混乱する恐れがある。
+ // d_disable_if があるのはそのため、専用のクラスを用意してるので
+ // うっかり cast<Target>( x, 0 ) とか呼んでもエラーになるので安心
- µ¡Ç½¡§
- ¾åµ¤Ç½ñ¤¤¤¿¤è¤¦¤Ë¡¢´Ø¿ô¤ËÂФ· enable_if ¤ò»È¤¦¾ì¹ç¤Ë¡¢
- ¥À¥ß¡¼¤È¤Ê¤ë·¿¤¬Â¸ºß¤·¤Æ¤¤¤ë¤È³Ú¤Ê¤Î¤Ç¡¢ dummy_arg_t ¤òͽ¤áÍÑ°Õ¤·¤Æ¤ª¤¤Þ¤¹
- ¤Þ¤¿¡¢¤½¤ÎÅÔÅÙ¥À¥ß¡¼·¿¤ò enable_if ¤ÎÂèÆó°ú¿ô¤Ç»ØÄꤹ¤ë¤Î¤ÏÌÌÅݤʤΤǡ¢¤½¤Î¼ê´Ö¤â¾Ê¤¤Þ¤¹¡£
- ¤Á¤Ê¤ß¤Ë d_enable_if ¤Î d ¤Ï dummy ¤Îά¡£
+ 機能:
+ 上記で書いたように、関数に対し enable_if を使う場合に、
+ ダミーとなる型が存在していると楽なので、 dummy_arg_t を予め用意しておきます
+ また、その都度ダミー型を enable_if の第二引数で指定するのは面倒なので、その手間も省きます。
+ ちなみに d_enable_if の d は dummy の略。
*/
namespace gintenlib
{
- // enable_if ÍÑ¥À¥ß¡¼°ú¿ô¥¯¥é¥¹
+ // enable_if ç\94¨ã\83\80ã\83\9fã\83¼å¼\95æ\95°ã\82¯ã\83©ã\82¹
struct dummy_arg_t {};
- // ¥À¥ß¡¼°ú¿ôÈÇ enable_if
+ // ダミー引数版 enable_if
template<typename Cond>
struct d_enable_if : enable_if<Cond, dummy_arg_t> {};
template<typename Cond>
<gintenlib/deep_ptr.hpp>
- deep_ptr ¡§ ¿¼¤¤¥³¥Ô¡¼¤ò¤¹¤ë¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿
+ deep_ptr ï¼\9a æ·±ã\81\84ã\82³ã\83\94ã\83¼ã\82\92ã\81\99ã\82\8bã\82¹ã\83\9eã\83¼ã\83\88ã\83\9dã\82¤ã\83³ã\82¿
- Àë¸À¡§
+ 宣言:
template<typename T>
struct deep_ptr;
- // ´ðËÜŪ¤Ê¥á¥½¥Ã¥É¤Ï¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤ÈƱ¤¸¤Ê¤Î¤Ç¾Êά
+ // 基本的なメソッドはスマートポインタと同じなので省略
- µ¡Ç½¡§
- ¥³¥Ô¡¼¤¹¤ë¤È¤¤Ë¡¢¥ª¥Ö¥¸¥§¥¯¥È¤Î¡Ö¿¼¤¤¥³¥Ô¡¼¡×¤òÀ½ºî¤¹¤ë¥Ý¥¤¥ó¥¿¡£
- ¤³¤Î¥¯¥é¥¹¤Ï´ðËÜŪ¤Ë boost::optional ¤ÇÂåÍѤǤ¤Þ¤¹¡£
- ¤½¤Î¤¿¤á¡¢¤¢¤¨¤Æ deep_ptr ¤ò»È¤¦¥á¥ê¥Ã¥È¤Ï¿¤¯¤¢¤ê¤Þ¤»¤ó¡£
+ 機能:
+ コピーするときに、オブジェクトの「深いコピー」を製作するポインタ。
+ このクラスは基本的に boost::optional で代用できます。
+ そのため、あえて deep_ptr を使うメリットは多くありません。
- ¡¦new ¤µ¤ì¤¿¤â¤Î¤òľÀܼõ¤±¼è¤ê¤¿¤¤¾ì¹ç
- ¡¦ÊÑ¿ô¼«ÂΤΥµ¥¤¥º¤¬µ¤¤Ë¤Ê¤ë¾ì¹ç
- ¡¦Ì¤ÄêµÁ¤Î·¿¤ò»ý¤¿¤»¤¿¤¤¾ì¹ç¡Ê¥¯¥é¥¹ÆâÉô¤Ç¡¢¤½¤Î¥¯¥é¥¹¤ÎÃͤò»ý¤Á¤¿¤¤¾ì¹ç¤Ê¤É
+ ・new されたものを直接受け取りたい場合
+ ・変数自体のサイズが気になる場合
+ ・未定義の型を持たせたい場合(クラス内部で、そのクラスの値を持ちたい場合など
- ¤»¤¤¤¼¤¤¤¬¤³¤ÎÄøÅ٤Ǥ¹¡£¤½¤ÎÃæ¤ÇÈæ³ÓŪ½ÅÍפʤΤ¬»°ÈÖÌܤǤ¢¤ê¡¢
- boost::optional ¤Î¾ì¹ç¡¢boost::optional<T> ·¿¤ÎÊÑ¿ô¤òÄêµÁ¤·¤¿»þÅÀ¤Ç T ¤Î·¿¤ÎÄêµÁ¤¬·è¤Þ¤Ã¤Æ¤¤¤Ê¤¤¤È¤¤¤±¤Þ¤»¤ó¡Ê sizeof(T) ¤¬É¬ÍפʤΤǡˡ£
- ¤·¤«¤· deep_ptr ¤Ê¤é¡¢¼ÂºÝ¤Ë¥³¥Ô¡¼¤µ¤ì¤ë»þ¤Þ¤Ç¡¢Âоݤη¿¤ÎÄêµÁ¤ò¿¤Ð¤»¤Þ¤¹¡Ê sizeof(T*) ¤Ï¾ï¤Ë°ìÄê¤Ê¤Î¤Ç¡Ë¡£
- ¤È¤¤¤¦¤ï¤±¤Ç¡¢new ¤Î¥³¥¹¥È¤¬·Ú¤¤¥ª¥Ö¥¸¥§¥¯¥È¡Ê¥á¥â¥ê¥×¡¼¥ë¤ò»È¤Ã¤¿ operator new ¤¬¼ÂÁõ¤µ¤ì¤Æ¤¤¤ë¾ì¹ç¤È¤«¡Ë¤Ê¤é¤Ð°Õ³°¤È»È¤¤Æ»¤Ï¤¢¤ë¤Î¤«¤â¤·¤ì¤Þ¤»¤ó¡£
- ¤Á¤Ê¤ß¤Ë¤³¤Î¥Ý¥¤¥ó¥¿¤Ï¡¢¥Ð¥°ËɻߤΤ¿¤áƱ¤¸·¿Æ±»Î¡Ê const Åù¤Î½¤¾þ»Ò¤Ï½ü¤¯¡Ë¤Ç¤·¤«¥³¥Ô¡¼¤Ç¤¤Þ¤»¤ó¡£
+ せいぜいがこの程度です。その中で比較的重要なのが三番目であり、
+ boost::optional の場合、boost::optional<T> 型の変数を定義した時点で T の型の定義が決まっていないといけません( sizeof(T) が必要なので)。
+ しかし deep_ptr なら、実際にコピーされる時まで、対象の型の定義を伸ばせます( sizeof(T*) は常に一定なので)。
+ というわけで、new のコストが軽いオブジェクト(メモリプールを使った operator new が実装されている場合とか)ならば意外と使い道はあるのかもしれません。
+ ちなみにこのポインタは、バグ防止のため同じ型同士( const 等の修飾子は除く)でしかコピーできません。
*/
typedef typename boost::remove_cv<T>::type object_type;
- // ¥Ç¥Õ¥©¥ë¥È¥³¥ó¥¹¥È¥é¥¯¥¿
+ // ã\83\87ã\83\95ã\82©ã\83«ã\83\88ã\82³ã\83³ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
deep_ptr() : p() {}
- // ¥Ý¥¤¥ó¥¿¤«¤éºî¤ë¥³¥ó¥¹¥È¥é¥¯¥¿
+ // ã\83\9dã\82¤ã\83³ã\82¿ã\81\8bã\82\89ä½\9cã\82\8bã\82³ã\83³ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
template<typename U>
explicit deep_ptr( U* p_,
typename enable_if_same_class<T, U>::type* = 0 )
: p( p_ ) {}
- // ¥³¥Ô¡¼¥³¥ó¥¹¥È¥é¥¯¥¿
+ // ã\82³ã\83\94ã\83¼ã\82³ã\83³ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
deep_ptr( const deep_ptr& src )
: p( src.make_clone_() ) {}
- // ¾¤Î¼ïÎà¤Î deep_ptr ¤«¤é¤ÎÊÑ´¹¤Ï¡¢const ¤ä volatile ½¤¾þ¤·¤«°Û¤Ê¤é¤Ê¤¤¾ì¹ç¤Î¤ßOK
+ // 他の種類の deep_ptr からの変換は、const や volatile 修飾しか異ならない場合のみOK
template< typename U >
deep_ptr( const deep_ptr<U>& src,
typename enable_if_same_class<T, U>::type* = 0 )
: p( src.make_clone_() ) {}
- // ¥Ç¥¹¥È¥é¥¯¥¿
- // scoped_ptr() ¤Î¤ª¤«¤²¤Ç²¿¤â¤·¤Ê¤¯¤Æ¤¤¤¤
+ // ã\83\87ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
+ // scoped_ptr() のおかげで何もしなくていい
// ~deep_ptr(){}
// nothrow swap ( for operator= )
one.swap( another );
}
- // ÂåÆþ±é»»¤Ï copy ¤·¤Æ swap
+ // 代入演算は copy して swap
deep_ptr& operator=( const deep_ptr& src )
{
deep_ptr( src ).swap( *this );
}
// get pointer
- // ¤³¤ì¤È pointer_facade ¤«¤é¤¤¤í¤¤¤í¤È¼«Æ°À¸À®
+ // これと pointer_facade からいろいろと自動生成
T* get() const { return p.get(); }
- // Ãæ¿È¤òÀÚ¤êÂؤ¨¤ë
+ // 中身を切り替える
void reset()
{
deep_ptr().swap( *this );
deep_ptr( ptr ).swap( *this );
}
- // shared_ptr ¤ËÊÑ´¹¤¹¤ë
+ // shared_ptr に変換する
shared_ptr<T> to_shared() const
{
return shared_ptr<T>( make_clone_() );
}
- // friend ÈÇ
+ // friend 版
friend shared_ptr<T> to_shared( const deep_ptr& target )
{
return target.to_shared();
private:
boost::scoped_ptr<T> p;
- // p ¤ËÊÝ»ý¤µ¤ì¤Æ¤ë¥ª¥Ö¥¸¥§¥¯¥È¤ÎÊ£À½¤òºî¤ë
+ // p に保持されてるオブジェクトの複製を作る
object_type* make_clone_() const
{
return p ? new object_type(*p) : 0;
<gintenlib/deleter.hpp>
- deleter ¡§ ñ½ã¤Ê delete ±é»»»Ò¤ÈÅù²Á¤Ê¥Õ¥¡¥ó¥¯¥¿
- typed_deleter ¡§ ·¿¤Î»ØÄꤵ¤ì¤¿ deleter
- dummy_deleter ¡§ ²¿¤â¤·¤Ê¤¤¥Õ¥¡¥ó¥¯¥¿
- typed_dummy_deleter ¡§ ·¿¤¬»ØÄꤵ¤ì¤Æ¤ë¤±¤É²¿¤â¤·¤Ê¤¤¥Õ¥¡¥ó¥¯¥¿
+ deleter ï¼\9a å\8d\98ç´\94ã\81ª delete æ¼\94ç®\97å\90ã\81¨ç\89価ã\81ªã\83\95ã\82¡ã\83³ã\82¯ã\82¿
+ typed_deleter : 型の指定された deleter
+ dummy_deleter ï¼\9a ä½\95ã\82\82ã\81\97ã\81ªã\81\84ã\83\95ã\82¡ã\83³ã\82¯ã\82¿
+ typed_dummy_deleter ï¼\9a å\9e\8bã\81\8cæ\8c\87å®\9aã\81\95ã\82\8cã\81¦ã\82\8bã\81\91ã\81©ä½\95ã\82\82ã\81\97ã\81ªã\81\84ã\83\95ã\82¡ã\83³ã\82¯ã\82¿
- µ¡Ç½¡§
- ¥Ý¥¤¥ó¥¿ delete ÍѤδؿô¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¹¡£¤½¤ì°Ê³°¤Î²¿Êª¤Ç¤â¤¢¤ê¤Þ¤»¤ó¡£
- deleter ¤Ï boost::checked_delete ¤ò¸Æ¤ó¤Ç¤Þ¤¹¤¬¡¢¤³¤ÎÃæ¤Ç¤Ïñ¤Ë delete ±é»»»Ò¤ò¸Æ¤ó¤Ç¤¤¤ë¤À¤±¡£
- dummy_deleter ¤Ï delete ±é»»»Ò¤¹¤é¸Æ¤Ð¤Ê¤¤¡¢Ã±¤Ê¤ë¥×¥ì¡¼¥¹¥Û¥ë¥À¡¼¤È¤·¤Æµ¡Ç½¤·¤Þ¤¹¡£
- ¤½¤ì¤¾¤ì·¿ÉեС¼¥¸¥ç¥ó¤â¤¢¤ê¡¢¤½¤ì¤é¤Ï unary_function ¤Î¾ò·ï¤òËþ¤¿¤·¤Æ¤¤¤Þ¤¹¡£
+ 機能:
+ ポインタ delete 用の関数オブジェクトです。それ以外の何物でもありません。
+ deleter は boost::checked_delete を呼んでますが、この中では単に delete 演算子を呼んでいるだけ。
+ dummy_deleter は delete 演算子すら呼ばない、単なるプレースホルダーとして機能します。
+ それぞれ型付バージョンもあり、それらは unary_function の条件を満たしています。
*/
namespace gintenlib
{
- // ¤¿¤Àñ¤Ë delete ¤¹¤ë¤À¤±¤Î¥Õ¥¡¥ó¥¯¥¿
+ // ã\81\9fã\81 å\8d\98ã\81« delete ã\81\99ã\82\8bã\81 ã\81\91ã\81®ã\83\95ã\82¡ã\83³ã\82¯ã\82¿
struct deleter
{
typedef void result_type;
}; // struct deleter
- // ·¿¤Î«Çû¤µ¤ì¤¿ deleter
+ // 型の束縛された deleter
template<typename T>
struct typed_deleter : std::unary_function<T*, void>
{
}; // struct typed_deleter<T>
- // ²¿¤â¤·¤Ê¤¤ deleter
+ // 何もしない deleter
struct dummy_deleter
{
typedef void result_type;
}; // struct dummy_deleter
- // ·¿Â«Çû¤µ¤ì¤Æ¤ë¤±¤É²¿¤â¤·¤Ê¤¤ deleter
+ // 型束縛されてるけど何もしない deleter
template<typename T>
struct typed_dummy_deleter : std::unary_function<T*, void>
{
<gintenlib/destructor.hpp>
- destructor ¡§ ¥Ç¥¹¥È¥é¥¯¥¿¸Æ¤Ó½Ð¤·¤ÈÅù²Á¤Ê¥Õ¥¡¥ó¥¯¥¿
- typed_destructor ¡§ ·¿¤Î»ØÄꤵ¤ì¤¿ destructor
+ destructor ï¼\9a ã\83\87ã\82¹ã\83\88ã\83©ã\82¯ã\82¿å\91¼ã\81³å\87ºã\81\97ã\81¨ç\89価ã\81ªã\83\95ã\82¡ã\83³ã\82¯ã\82¿
+ typed_destructor : 型の指定された destructor
- µ¡Ç½¡§
- ¥Ç¥¹¥È¥é¥¯¥¿¸Æ¤Ó½Ð¤·ÍѤδؿô¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¹¡£¤½¤ì°Ê³°¤Î²¿Êª¤Ç¤â¤¢¤ê¤Þ¤»¤ó¡£
- deleter ¤Ï boost::checked_delete ¤ò¸Æ¤ó¤Ç¤Þ¤¹¤¬¡¢¤³¤ÎÃæ¤Ç¤Ïñ¤Ë delete ±é»»»Ò¤ò¸Æ¤ó¤Ç¤¤¤ë¤À¤±¡£
- dummy_deleter ¤Ï delete ±é»»»Ò¤¹¤é¸Æ¤Ð¤Ê¤¤¡¢Ã±¤Ê¤ë¥×¥ì¡¼¥¹¥Û¥ë¥À¡¼¤È¤·¤Æµ¡Ç½¤·¤Þ¤¹¡£
- ¤½¤ì¤¾¤ì·¿ÉեС¼¥¸¥ç¥ó¤â¤¢¤ê¡¢¤½¤ì¤é¤Ï unary_function ¤Î¾ò·ï¤òËþ¤¿¤·¤Æ¤¤¤Þ¤¹¡£
+ 機能:
+ デストラクタ呼び出し用の関数オブジェクトです。それ以外の何物でもありません。
+ deleter は boost::checked_delete を呼んでますが、この中では単に delete 演算子を呼んでいるだけ。
+ dummy_deleter は delete 演算子すら呼ばない、単なるプレースホルダーとして機能します。
+ それぞれ型付バージョンもあり、それらは unary_function の条件を満たしています。
*/
namespace gintenlib
{
- // ¥Ç¥¹¥È¥é¥¯¥¿¤ò¸Æ¤Ó½Ð¤¹¥Õ¥¡¥ó¥¯¥¿
+ // ã\83\87ã\82¹ã\83\88ã\83©ã\82¯ã\82¿ã\82\92å\91¼ã\81³å\87ºã\81\99ã\83\95ã\82¡ã\83³ã\82¯ã\82¿
struct destructor
{
typedef void result_type;
}; // struct destructor
- // ·¿¤Î«Çû¤µ¤ì¤¿ destructor
+ // 型の束縛された destructor
template<typename T>
struct typed_destructor
: std::unary_function<T*, void>
<gintenlib/enable_if.hpp>
- enable_if ¡§ boost::enable_if ¤Î using Àë¸À
+ enable_if : boost::enable_if の using 宣言
- Àë¸À¡§
+ 宣言:
using boost::enable_if;
using boost::enable_if_c;
using boost::disable_if;
using boost::disable_if_c;
- µ¡Ç½¡§
- ñ½ã¤Ë gintenlib Æâ¤Ç boost::enable_if ¤ò»È¤¦µ¡²ñ¤Ï¿¤¤¤Î¤Ç¡¢
- ͽ¤á using Àë¸À¤·¤Æ¤ª¤±¤Ð¡¢¤¤¤Á¤¤¤Á boost:: ¤È»ØÄꤷ¤Æ¤ä¤ëɬÍפ¬Ìµ¤¯¤Æ³Ú¡¢¤À¤±¤Î¥Ø¥Ã¥À¤Ç¤¹¡£
- ¤¢¤È¤Ï TR1 ¤Ø¤ÎÂбþ¤ò¤·¤ä¤¹¤¤¤è¤¦¤Ë¡¢¤È¤¤¤¦°ÕµÁ¤â¤¢¤ê¤Þ¤¹¡£
- ¤½¤Î¾ì¹ç¤Ï¸ß´¹À¤¬¼º¤ï¤ì¤ë²ÄǽÀ¤â¤¢¤ë¤Î¤Ç¡¢¤ä¤ë¤È¤¹¤ì¤Ð¥á¥¸¥ã¡¼¥Ð¡¼¥¸¥ç¥ó¥¢¥Ã¥×»þ¤Ç¤·¤ç¤¦¤¬¡£
+ 機能:
+ 単純に gintenlib 内で boost::enable_if を使う機会は多いので、
+ 予め using 宣言しておけば、いちいち boost:: と指定してやる必要が無くて楽、だけのヘッダです。
+ あとは TR1 への対応をしやすいように、という意義もあります。
+ その場合は互換性が失われる可能性もあるので、やるとすればメジャーバージョンアップ時でしょうが。
*/
/*
<gintenlib/factorize.hpp>
- factorize ¡§ À°¿ô¤Î°ø¿ôʬ²ò
+ factorize : 整数の因数分解
- Àë¸À¡§
+ 宣言:
template<typename Int, typename OutIte>
OutIte factorize( Int n, OutIte out );
- µ¡Ç½¡§
- À°¿ô n ¤ÎÁÇ°ø¿ô¤ò¡¢¾®¤µ¤¤½ç¤Ë½ÐÎÏ¥¤¥Æ¥ì¡¼¥¿ out ¤Ë½ÐÎϤ·¤Þ¤¹¡£
- n ¤Ï 0 ¤è¤êÂ礤¯¤Ê¤±¤ì¤Ð¤¤¤±¤Þ¤»¤ó¡Ê 0 °Ê²¼¤Ë¤Ê¤é¤Ê¤¤¤è¤¦»öÁ°¤Ë¥Á¥§¥Ã¥¯¤¹¤Ù¤¤Ç¤¹¡Ë¡£
- ¡ÖÀ°¿ô¡×¤È¤·¤Æ»È¤¨¤ë·¿¤Ï¡¢À°¿ô·¿¤«¤é°ÅÌÛÊÑ´¹¤Ç¤¡¢»Í§±é»»¤ª¤è¤ÓÂç¾®Èæ³Ó¤¬²Äǽ¤Ê·¿¤Ç¤¹¡£
+ 機能:
+ 整数 n の素因数を、小さい順に出力イテレータ out に出力します。
+ n は 0 より大きくなければいけません( 0 以下にならないよう事前にチェックすべきです)。
+ 「整数」として使える型は、整数型から暗黙変換でき、四則演算および大小比較が可能な型です。
- »ÈÍÑÎ㡧
+ 使用例:
// 143 = 11 * 13
- // '11 13 '¤Èɽ¼¨¤µ¤ì¤ë
+ // '11 13 'と表示される
gintenlib::factorize( 143, std::ostream_iterator<int>( std::cout, " " ) );
- Ê䡧
- ¡¦Ã±½ã¤Ê¥Æ¥ó¥×¥ì¡¼¥È¤Ê¤Î¤Ç¡¢·¿¤ò»ØÄꤷ¤¿¤¤¾ì¹ç¤Ï factorize<short>( 143, out ) ¤Î¤è¤¦¤Ë½ñ¤±¤Þ¤¹¡£
- ¡¡¤¬¡¢Â¾¤Î¥Æ¥ó¥×¥ì¡¼¥È¤Ç¤Ï¾å¼ê¤¯¤¤¤«¤Ê¤¤¤³¤È¤â¤¢¤ë¤¿¤á¡¢Åý°ìÀ¤Î°Ù¤Ë¤â gintenlib::cast ¤òÍѤ¤¤¿Êý¤¬¤è¤¤¤«¤â¤·¤ì¤Þ¤»¤ó¡£
- ¡¡¤½¤Î¾ì¹ç¤Ï factorize( cast<short>(143), out ) ¤Î¤è¤¦¤Ë½ñ¤¤Þ¤¹¡Ê gintenlib:: ¤Ïά¡Ë
+ 補足:
+ ・単純なテンプレートなので、型を指定したい場合は factorize<short>( 143, out ) のように書けます。
+ が、他のテンプレートでは上手くいかないこともあるため、統一性の為にも gintenlib::cast を用いた方がよいかもしれません。
+ その場合は factorize( cast<short>(143), out ) のように書きます( gintenlib:: は略)
*/
namespace gintenlib
{
- // ÁÇ°ø¿ôʬ²ò¤·¤Æ out ¤Ë½ÐÎÏ
+ // 素因数分解して out に出力
template<typename Int, typename OutIte>
OutIte factorize( Int n, OutIte out )
{
- // °ú¿ô¥Á¥§¥Ã¥¯
+ // å¼\95æ\95°ã\83\81ã\82§ã\83\83ã\82¯
if( n <= 0 )
{
throw std::invalid_argument( "gintenlib.factorize: n should be greater than 0" );
}
- // Êä½õ¥Õ¥¡¥ó¥¯¥¿
- // Ʊ¤¸µ½Ò¤ò²¿²ó¤â½ñ¤¯¤Î¤ÏÌÌÅݤʤΤÇ
+ // è£\9cå\8a©ã\83\95ã\82¡ã\83³ã\82¯ã\82¿
+ // 同じ記述を何回も書くのは面倒なので
struct helper_
{
Int& n; OutIte& out;
}
} doit( n, out );
- // ¼ÂºÝ¤Î½èÍý
- // ¤Þ¤º 2 ¤È 3¡¢¤³¤ì¤Ï i ¤â´Þ¤á¤Æ¥¤¥ó¥é¥¤¥óŸ³«¤µ¤ì¤ë¤È¤¤¤¤¤Ê
+ // 実際の処理
+ // まず 2 と 3、これは i も含めてインライン展開されるといいな
if( !doit(2) ){ return out; }
if( !doit(3) ){ return out; }
- // ¼¡¤ÏÈÆÍѤÀ¤¬¡¢2 ¤È 3 ¤ÎÇÜ¿ô¤ÏÁÇ¿ô¤Ç¤Ï¤Ê¤¤¤Î¤Ç¾Êά¤¹¤ë
- // ¤½¤Î¤¿¤á¤Ë¤Ï¡¢6n - 1 ¤È 6n + 1 ¤Î¤ß¸¡º÷¤¹¤ì¤Ð¤è¤¤
+ // 次は汎用だが、2 と 3 の倍数は素数ではないので省略する
+ // そのためには、6n - 1 と 6n + 1 のみ検索すればよい
Int i = 5;
for(;;)
{
<gintenlib/ignore.hpp>
- ignore ¡§ ¤¢¤é¤æ¤ëÂåÆþ¤ò̵»ë¤¹¤ëÊÑ¿ô
+ ignore : あらゆる代入を無視する変数
- Àë¸À¡§
+ 宣言:
using boost::fusion::ignore;
- µ¡Ç½¡§
- ¤¢¤é¤æ¤ëÂåÆþÁàºî¤ò¼õ¤±ÉÕ¤±¤Ê¤¤ÊÑ¿ô ignore ¤òÄêµÁ¤·¤Þ¤¹¡£
+ 機能:
+ あらゆる代入操作を受け付けない変数 ignore を定義します。
- »ÈÍÑÎ㡧
+ 使用例:
struct vector
{
double x, y;
double x;
v.get_xy( x, gintenlib::ignore );
- Ê䡧
- ¡¦¤¢¤ó¤Þ¤ê»È¤ï¤Ê¤¤¤«¤â
+ 補足:
+ ・あんまり使わないかも
*/
<gintenlib/intrusive_to_shared.hpp>
- intrusive_to_shared ¡§ intrusive_ptr ¤ò shared_ptr ¤ËÊÑ´¹
+ intrusive_to_shared : intrusive_ptr を shared_ptr に変換
- Àë¸À¡§
+ 宣言:
template<typename T>
boost::shared_ptr<T> intrusive_to_shared( const boost::intrusive_ptr<T>& p );
template<typename T>
boost::shared_ptr<T> to_shared( const boost::intrusive_ptr<T>& p );
- µ¡Ç½¡§
- intrusive_ptr ¤ò shared_ptr ¤ËÊÑ´¹¤·¤Þ¤¹¡£
- intrusive_ptr_add_ref ¤ä intrusive_ptr_release ¤Î¥³¥¹¥È¤¬¹â¤¤¾ì¹ç¤ä¡¢
- ¤¢¤ë¤¤¤Ïñ¤Ë shared_ptr ¤È¤·¤Æ¤ÎÃͤ¬Íߤ·¤¤¾ì¹ç¤Ê¤É¤Ë»È¤¨¤Þ¤¹¡£
- ¤Ê¤ª¥Ø¥Ã¥À̾¤Ï intrusive_to_shared ¤Ç¤¹¤¬¡¢¾Êά̾¤Ç¤¢¤ë to_shared ¤Ç¤â»È¤¨¤Þ¤¹¡£
- ¤à¤·¤í <gintenlib/to_shared.hpp> ¤È¤Î·ó¤Í¹ç¤¤¤«¤é¡¢¤³¤Á¤é¤ò»È¤¦¤³¤È¤ò¿ä¾©¤·¤Æ¤¤¤Þ¤¹¡£
+ 機能:
+ intrusive_ptr を shared_ptr に変換します。
+ intrusive_ptr_add_ref や intrusive_ptr_release のコストが高い場合や、
+ あるいは単に shared_ptr としての値が欲しい場合などに使えます。
+ なおヘッダ名は intrusive_to_shared ですが、省略名である to_shared でも使えます。
+ むしろ <gintenlib/to_shared.hpp> との兼ね合いから、こちらを使うことを推奨しています。
*/
namespace gintenlib
{
- // deleter ¤È¤·¤Æ»È¤¦Êä½õ¥Õ¥¡¥ó¥¯¥¿
+ // deleter ã\81¨ã\81\97ã\81¦ä½¿ã\81\86è£\9cå\8a©ã\83\95ã\82¡ã\83³ã\82¯ã\82¿
struct intrusive_ptr_releaser
{
typedef void result_type;
- // ptr ¤ò¥ê¥ê¡¼¥¹¤¹¤ë
+ // ptr をリリースする
template<typename T>
void operator()( T* ptr ) const
{
}; // class intrusive_ptr_releaser
- // ËÜÂÎ
- // intrusive_ptr ÈÇ
+ // 本体
+ // intrusive_ptr 版
template<typename T>
inline shared_ptr<T> intrusive_to_shared( const boost::intrusive_ptr<T>& p )
{
- // À¸¥Ý¥¤¥ó¥¿ÈǤËñ½ã¤ËžÁ÷¤¹¤ë¤À¤±
+ // 生ポインタ版に単純に転送するだけ
return intrusive_to_shared( p.get(), true );
}
- // À¸¥Ý¥¤¥ó¥¿ÈÇ
+ // 生ポインタ版
template<typename T>
inline shared_ptr<T> intrusive_to_shared( T* p, bool add_ref = true )
{
if(p)
{
- // »²¾È¥«¥¦¥ó¥ÈÁý¤ä¤·¤Æ¤«¤é shared_ptr ¤ËÆͤùþ¤à
- // boost::shared_ptr ¤Ï¥³¥ó¥¹¥È¥é¥¯¥¿¤ÇÎã³°¤òÅꤲ¤¦¤ë¤¬¡¢¤½¤Î¾ì¹ç¤Ç¤â
- // ¤Á¤ã¤ó¤Èºï½ü¥Õ¥¡¥ó¥¯¥¿¤ò¸Æ¤Ó½Ð¤·¤Æ¤¯¤ì¤ë¤Î¤ÇÌäÂê¤Ê¤¤
+ // 参照カウント増やしてから shared_ptr に突っ込む
+ // boost::shared_ptr はコンストラクタで例外を投げうるが、その場合でも
+ // ちゃんと削除ファンクタを呼び出してくれるので問題ない
if( add_ref ){ intrusive_ptr_add_ref( p ); }
return shared_ptr<T>( p, intrusive_ptr_releaser() );
}
- // NULL ¤Î¾ì¹ç¤Ï¶õ¤Î shared_ptr ¤òÊÖ¤¹
+ // NULL の場合は空の shared_ptr を返す
return shared_ptr<T>();
}
- // ¾Êά̾¾Î
- // ¾¤Î¾ì½ê¤Ç to_shared ¤Î°ìÈÌŪ¤Ê¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤ËÂФ¹¤ëÄêµÁ¤â¤¢¤ë¤¬¡¢
- // intrusive_ptr ¤Ë´Ø¤·¤Æ¤Ï¤³¤Á¤é¤ÎÊý¤¬¸úΨ¤¬Îɤ¤¡£
+ // 省略名称
+ // 他の場所で to_shared の一般的なスマートポインタに対する定義もあるが、
+ // intrusive_ptr に関してはこちらの方が効率が良い。
template<typename T>
inline shared_ptr<T> to_shared( const boost::intrusive_ptr<T>& p )
{
- // ñ½ã¤ËžÁ÷¤¹¤ë¤À¤±
+ // 単純に転送するだけ
return intrusive_to_shared( p );
}
/*
<gintenlib/is_same_class.hpp>
- is_same_class ¡§ const, volatile ¤ò½ü¤¤¤¿¾õÂ֤Ǥη¿¤ÎÈæ³Ó
+ is_same_class : const, volatile を除いた状態での型の比較
- Àë¸À¡§
+ 宣言:
template< typename T1, typename T2 >
class is_same_class
{
class enable_if_same_class
: enable_if< is_same_class<T1, T2>, T > {};
- µ¡Ç½¡§
- ²¼¤ÎÄêµÁ¤ò¸«¤ì¤Ð°ìÌÜÎÆÁ³¡£remove_cv ¤·¤Æ is_same Èæ³Ó¤·¤Þ¤¹¡£
- Èæ³ÓŪ¿¤¤Áàºî¤Ê¤Î¤Ç¡¢Ã»¤¯»È¤¨¤ë¤è¤¦¤Ë¡£
+ 機能:
+ 下の定義を見れば一目瞭然。remove_cv して is_same 比較します。
+ 比較的多い操作なので、短く使えるように。
*/
namespace gintenlib
{
- // CV ½¤¾þ¤ò½ü¤¤¤ÆƱ¤¸¥¯¥é¥¹¤«Èݤ«
+ // CV 修飾を除いて同じクラスか否か
template<typename T1, typename T2>
struct is_same_class
: boost::is_same< typename boost::remove_cv<T1>::type,
typename boost::remove_cv<T2>::type > {};
- // CV ½¤¾þ¤ò½ü¤¤¤ÆƱ¤¸¤Ê¤é͸ú¤Ë¤Ê¤ë
+ // CV 修飾を除いて同じなら有効になる
template<typename T1, typename T2, typename T = void>
struct enable_if_same_class
: enable_if< is_same_class<T1, T2>, T > {};
/*
<gintenlib/lexical_cast_default.hpp>
- lexical_cast_default ¡§ Îã³°¤òÅꤲ¤Ê¤¤ boost::lexical_cast
+ lexical_cast_default : 例外を投げない boost::lexical_cast
- Àë¸À¡§
+ 宣言:
template< typename Target, typename Source >
Target lexical_cast_default( const Source& src );
template< typename Target, typename Source >
Target lexical_cast_default( const Source& src, const Target& default_value );
- µ¡Ç½¡§
- boost::lexical_cast ¤ÈƱÍͤˡ¢Ê¸»úÎóɽ¸½¤òÃçΩ¤Á¤Ë·¿ÊÑ´¹¤ò¹Ô¤¤¤Þ¤¹¡£
- boost::lexical_cast ¤È¤Î°ã¤¤¤Ï¡¢¼ºÇÔ¤·¤¿¾ì¹ç¤ËÎã³°¤òÅꤲ¤º default_value ¤òÊÖ¤¹ÅÀ¡£
- ÂèÆó°ú¿ô¤ò¾Êά¤·¤¿¾ì¹ç¤Ë¤Ï¡¢¥Ç¥Õ¥©¥ë¥È½é´ü²½Ãͤ¬ÊÖ¤ê¤Þ¤¹¡£
+ 機能:
+ boost::lexical_cast と同様に、文字列表現を仲立ちに型変換を行います。
+ boost::lexical_cast との違いは、失敗した場合に例外を投げず default_value を返す点。
+ 第二引数を省略した場合には、デフォルト初期化値が返ります。
- »ÈÍÑÎ㡧
- // hoge ¤Ï¿ôÃͤòɽ¤·¤Æ¤¤¤ë¤«¤â¤·¤ì¤Ê¤¤¡Öʸ»úÎó¤ËÊÑ´¹¤Ç¤¤ë²¿¤«¡×
+ 使用例:
+ // hoge は数値を表しているかもしれない「文字列に変換できる何か」
int i = gintenlib::lexical_cast_default<int>( hoge, -1 ),
j = gintenlib::lexical_cast_default<int>( hoge );
- // hoge ¤¬¿ôÃͤòɽ¤·¤Æ¤¤¤Ê¤±¤ì¤Ð¡¢i = -1, j = 0¡Êint¤Î½é´üÃ͡ˤˤʤë
+ // hoge が数値を表していなければ、i = -1, j = 0(intの初期値)になる
- Ê䡧
- ¡¦´ðËÜŪ¤Ë boost::lexical_cast ¤ÎÎã³°½èÍý¤¬ÌÌÅݤʾì¹ç¤Ë»È¤¤¤Þ¤¹¡£
- ¡¦default_value¤ÈƱ¤¸Ãͤ¬Ê֤俤Ȥ·¤Æ¤â¡¢¥¥ã¥¹¥È¤Ë¼ºÇÔ¤·¤¿¤È¤Ï¸Â¤é¤Ê¤¤¤Î¤ÇÍ×Ãí°Õ¡£
- ¡ÊÊÑ´¹¸µ¤Îɽ¸½¤¹¤ëÃͤ¬¡¢¤¿¤Þ¤¿¤Þ default_value ¤ÈƱ¤¸¤À¤Ã¤¿¤Î¤«¤â¤·¤ì¤Ê¤¤¤Î¤Ç¡Ë
+ 補足:
+ ・基本的に boost::lexical_cast の例外処理が面倒な場合に使います。
+ ・default_valueと同じ値が返ったとしても、キャストに失敗したとは限らないので要注意。
+ (変換元の表現する値が、たまたま default_value と同じだったのかもしれないので)
*/
namespace gintenlib
{
- // src ¤òʸ»úÎó¤ËÊÑ´¹¤·¡¢¤½¤Îʸ»úÎó¤ò Target ·¿¤ËÊÑ´¹
- // ¼ºÇÔ¤·¤¿¾ì¹ç¤Ë¤Ï default_value ¤¬ÊÖ¤ë
+ // src を文字列に変換し、その文字列を Target 型に変換
+ // 失敗した場合には default_value が返る
template< typename Target, typename Source >
Target lexical_cast_default( const Source& src, const Target& default_value )
{
} // lexical_cast_default
- // src ¤òʸ»úÎó¤ËÊÑ´¹¤·¡¢¤½¤Îʸ»úÎó¤ò Target ·¿¤ËÊÑ´¹
- // ¼ºÇÔ¤·¤¿¾ì¹ç¤Ë¤Ï Target() ¤¬ÊÖ¤ë
+ // src を文字列に変換し、その文字列を Target 型に変換
+ // 失敗した場合には Target() が返る
template< typename Target, typename Source >
Target lexical_cast_default( const Source& src )
{
<gintenlib/lexical_convert.hpp>
- lexical_convert ¡§ C¥é¥¤¥¯¤Ë½èÍý¤Ç¤¤ë boost::lexical_cast
+ lexical_convert : Cライクに処理できる boost::lexical_cast
- Àë¸À¡§
+ 宣言:
template< typename Target, typename Source >
bool lexical_convert( Target& dest, const Source& src );
- µ¡Ç½¡§
- ÂèÆó°ú¿ô¤ò boost::lexical_cast ¤Ë¤è¤Ã¤ÆÊÑ´¹¤·¡¢¤½¤Î·ë²Ì¤òÂè°ì°ú¿ô¤ËÂåÆþ¤·¤Þ¤¹¡£
- Àµ¾ï¤ËÊÑ´¹¤¬¹Ô¤ï¤ì¤¿¾ì¹ç¡¢Ìá¤êÃͤȤ·¤Æ true ¤¬ÊÖ¤µ¤ì¤Þ¤¹¡£
- ÊÑ´¹¤¬¼ºÇÔ¤·¤¿¾ì¹ç¤Ë¤Ï¡¢Âè°ì°ú¿ô¤ÏÊѲ½¤»¤º¡¢Ìá¤êÃÍ¤Ï false ¤Ë¤Ê¤ê¤Þ¤¹¡£
+ 機能:
+ 第二引数を boost::lexical_cast によって変換し、その結果を第一引数に代入します。
+ 正常に変換が行われた場合、戻り値として true が返されます。
+ 変換が失敗した場合には、第一引数は変化せず、戻り値は false になります。
- »ÈÍÑÎ㡧
- // hoge ¤Ï¿ôÃͤòɽ¤·¤Æ¤¤¤ë¤«¤â¤·¤ì¤Ê¤¤¡Öʸ»úÎó¤ËÊÑ´¹¤Ç¤¤ë²¿¤«¡×
+ 使用例:
+ // hoge は数値を表しているかもしれない「文字列に変換できる何か」
int i;
if( gintenlib::lexical_convert( i, hoge ) )
{
- // hoge ¤¬¿ôÃͤòɽ¤·¤Æ¤¤¤¿¾ì¹ç¤Î½èÍý
+ // hoge が数値を表していた場合の処理
}
else
{
- // hoge ¤¬¿ôÃͤòɽ¤·¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Î½èÍý
+ // hoge が数値を表していなかった場合の処理
}
- Ê䡧
- ¡¦´ðËÜŪ¤Ë boost::lexical_cast ¤ÎÎã³°½èÍý¤¬ÌÌÅݤʾì¹ç¤Ë»È¤¤¤Þ¤¹¡£
- ¡¦»ÈÍÑÎã¤Î¥½¡¼¥¹¥³¡¼¥É¤Ï¡¢boost::lexical_cast ¤Î¤ß¤ò»È¤Ã¤Æ¼¡¤Î¤è¤¦¤Ë½ñ¤¯»ö¤â½ÐÍè¤Þ¤¹¡§
+ 補足:
+ ・基本的に boost::lexical_cast の例外処理が面倒な場合に使います。
+ ・使用例のソースコードは、boost::lexical_cast のみを使って次のように書く事も出来ます:
int i;
try
{
i = boost::lexical_cast<int>(hoge);
- // hoge ¤¬¿ôÃͤòɽ¤·¤Æ¤¤¤¿¾ì¹ç¤Î½èÍý
+ // hoge が数値を表していた場合の処理
}
catch( boost::bad_lexical_cast )
{
- // hoge ¤¬¿ôÃͤòɽ¤·¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Î½èÍý
+ // hoge が数値を表していなかった場合の処理
}
*/
namespace gintenlib
{
- // src ¤òʸ»úÎó¤ËÊÑ´¹¤·¡¢¤½¤Îʸ»úÎó¤ò Target ·¿¤ËÊÑ´¹¤·¤Æ dest ¤ËÂåÆþ
- // À®¸ù¤·¤¿¾ì¹ç¤Ë¤Ï true ¤¬¡¢¼ºÇÔ¤·¤¿¾ì¹ç¤Ë¤Ï false ¤¬ÊÖ¤ë
+ // src を文字列に変換し、その文字列を Target 型に変換して dest に代入
+ // 成功した場合には true が、失敗した場合には false が返る
template< typename Target, typename Source >
bool lexical_convert( Target& dest, const Source& src )
{
<gintenlib/list_format.hpp>
- list_format ¡§ ¥³¥ó¥Æ¥Ê¤Î¤ª¼ê·Ú¥¹¥È¥ê¡¼¥à½ÐÎÏ
+ list_format : コンテナのお手軽ストリーム出力
- Àë¸À¡§
+ 宣言:
template< typename Range >
unspecified list_format( const Range& src );
template< typename InIte, typename Pre, typename Delim, typename Post >
unspecified list_format( const InIte& begin, const InIte& end, const Pre& pre, const Delim& delim, const Post& post );
- µ¡Ç½¡§
- Ǥ°Õ¤Î¥³¥ó¥Æ¥Ê¤äÇÛÎó¡Ê boost »ÈÍÑÈǤǤÏǤ°Õ¤Î range ¡Ë¤ò¡¢¥¹¥È¥ê¡¼¥à¤Ëή¤»¤ë¤è¤¦²Ã¹©¤·¤Þ¤¹¡£
- ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï ( 1, 2, 3, 4 ) ¤Î¤è¤¦¤Ë½ÐÎϤµ¤ì¤Þ¤¹¤¬¡¢°ú¿ô¤ò»ØÄꤹ¤ë¤³¤È¤Ç¥¹¥¿¥¤¥ë¤ÏÊѹ¹¤Ç¤¤Þ¤¹¡£
+ 機能:
+ 任意のコンテナや配列( boost 使用版では任意の range )を、ストリームに流せるよう加工します。
+ デフォルトでは ( 1, 2, 3, 4 ) のように出力されますが、引数を指定することでスタイルは変更できます。
- »ÈÍÑÎ㡧
- // v ¤ÏǤ°Õ¤Î¥³¥ó¥Æ¥Ê¡£( 1, 2, 3 ) ¤Î¤è¤¦¤Ëɽ¼¨¤µ¤ì¤Þ¤¹
+ 使用例:
+ // v は任意のコンテナ。( 1, 2, 3 ) のように表示されます
cout << gintenlib::list_format(v) << endl;
- // °ú¿ô¤ò»ØÄꤹ¤ì¤Ð¡¢[ 1 | 2 | 3 ] ¤Î¤è¤¦¤Êɽ¼¨¤Ë¤â¤Ç¤¤Þ¤¹
+ // 引数を指定すれば、[ 1 | 2 | 3 ] のような表示にもできます
cout << gintenlib::list_format( v, "[ ", " | ", " ]" ) << endl;
- // ¤Þ¤¿¡¢¥¤¥Æ¥ì¡¼¥¿¤ò»È¤Ã¤Æ½ÐÎÏÂоݤò»ØÄꤹ¤ë¤³¤È¤â½ÐÍè¤Þ¤¹¡£
- // ¤³¤Î¾ì¹ç¤ÏµÕ½ç¤Îɽ¼¨¤Ë¤Ê¤ê¤Þ¤¹
+ // また、イテレータを使って出力対象を指定することも出来ます。
+ // この場合は逆順の表示になります
cout << gintenlib::list_format( v.rbegin(), v.rend() ) << endl;
- Ê䡧
- ¡¦´ðËÜŪ¤Ë list_format ´Ø¿ô¤Ï¡¢¡ÖÌá¤êÃͤò¥¹¥È¥ê¡¼¥à¤Ëή¤¹¡×¤È¤¤¤¦»È¤¤Êý¤Î¤ß¤òÁÛÄꤷ¤Æ¤¤¤Þ¤¹¡£
- ¡¦¤¿¤À¤·¡¢list_format ´Ø¿ô¤ÎÌá¤êÃÍ¤Ë boost::lexical_cast ¤òŬ±þ¤¹¤ë¤³¤È¤Ï²Äǽ¤Ç¤¹¡£
- ¡¦¤Þ¤¿¡¢Ìá¤êÃͤò gintenlib::output_element ¥ª¥Ö¥¸¥§¥¯¥È¤Ë³ÊǼ¤¹¤ë¤³¤È¤â½ÐÍè¤Þ¤¹¡£
- ¡¦¾åµ°Ê³°¤ÎÌÜŪ¤Ç»È¤Ã¤¿¾ì¹ç¡¢list_format ´Ø¿ô¤ÎÆ°ºî¤ÏÉÔÄê¤È¤Ê¤ê¤Þ¤¹¡£
+ 補足:
+ ・基本的に list_format 関数は、「戻り値をストリームに流す」という使い方のみを想定しています。
+ ・ただし、list_format 関数の戻り値に boost::lexical_cast を適応することは可能です。
+ ・また、戻り値を gintenlib::output_element オブジェクトに格納することも出来ます。
+ ・上記以外の目的で使った場合、list_format 関数の動作は不定となります。
*/
namespace gintenlib
{
- // ¼ÂºÝ¤Ë¥¹¥È¥ê¡¼¥à¤Ëή¤¹¥¯¥é¥¹
+ // å®\9fé\9a\9bã\81«ã\82¹ã\83\88ã\83ªã\83¼ã\83 ã\81«æµ\81ã\81\99ã\82¯ã\83©ã\82¹
template< typename InIte, typename Pre = const char*,
typename Delim = const char*, typename Post = const char* >
struct list_format_impl_
typename boost::call_traits<Delim>::value_type delim_;
typename boost::call_traits<Post>::value_type post_;
- // ½ÐÎϤμÂÁõ
- // ¥Æ¥ó¥×¥ì¡¼¥È¤Ë¤è¤ê std::ostream ¤Ë¸Â¤é¤º½ÐÎϤǤ¤Þ¤¹
+ // 出力の実装
+ // テンプレートにより std::ostream に限らず出力できます
template<typename Stream>
friend Stream& operator<< ( Stream& os, const list_format_impl_& src )
{
- // ¶õ¤Î¥ê¥¹¥È¤òɽ¼¨¤µ¤»¤è¤¦¤È¤·¤¿¾ì¹ç¡¢²¿¤âɽ¼¨¤µ¤ì¤Ê¤¤
+ // 空のリストを表示させようとした場合、何も表示されない
if( src.begin_ == src.end_ ){ return os; }
- // ɽ¼¨ËÜÂÎ
+ // 表示本体
os << src.pre_;
InIte ite = src.begin_;
}; // struct list_format_impl_
- // ´Ø¿ôËÜÂÎ
+ // 関数本体
- // ¥³¥ó¥Æ¥ÊÈÇ
+ // コンテナ版
- // °ìÈÌ·Á¡£Ç¤°Õ¤Î pre, delim, post ¤Ë´Ø¤·¤Æ
- // os << pre << Í×ÁÇ£± << delim << Í×ÁÇ£² << ... << delim << Í×ÁÇ£î << end;
- // ¤È¤¤¤¦¥¤¥á¡¼¥¸¤Ç½ÐÎϤµ¤ì¤ë¡£
+ // 一般形。任意の pre, delim, post に関して
+ // os << pre << 要素1 << delim << 要素2 << ... << delim << 要素n << end;
+ // というイメージで出力される。
template< typename Range, typename Pre, typename Delim, typename Post >
inline const list_format_impl_< typename boost::range_iterator<const Range>::type, Pre, Delim, Post >
list_format
( begin(src), end(src), pre, delim, post );
}
- // ¾ÊάÈÇ¡£( Í×ÁÇ£±, Í×ÁÇ£², ... , Í×ÁÇ£î ) ¤È¤¤¤¦´¶¤¸¤Ë½ÐÎÏ
+ // 省略版。( 要素1, 要素2, ... , 要素n ) という感じに出力
template< typename Range >
inline const list_format_impl_< typename boost::range_iterator<const Range>::type >
list_format( const Range& src )
}
- // ¥¤¥Æ¥ì¡¼¥¿ÈÇ
+ // イテレータ版
- // °ìÈÌ·Á
+ // 一般形
template< typename InIte, typename Pre, typename Delim, typename Post >
inline const list_format_impl_<InIte, Pre, Delim, Post>
list_format
return list_format_impl_<InIte, Pre, Delim, Post>( begin, end, pre, delim, post );
}
- // ¾ÊάÈÇ
+ // 省略版
template< typename InIte >
inline const list_format_impl_<InIte>
list_format( const InIte& begin, const InIte& end )
<gintenlib/list_formatter.hpp>
- list_formatter ¡§ ¥Õ¥¡¥ó¥¯¥¿ÈÇ list_format¡Êconst char* ÈÇ¡Ë
+ list_formatter : ファンクタ版 list_format(const char* 版)
- Àë¸À¡§
+ 宣言:
template< typename Elem >
struct basic_list_formatter
{
);
typedef gintenlib_value_t(Elem) element_type;
- // ¥á¥ó¥Ð¡ÖÊÑ¿ô¡×¡¢¼«Í³¤Ë³°Éô¤«¤é¥¢¥¯¥»¥¹¤Ç¤¤ë
+ // メンバ「変数」、自由に外部からアクセスできる
element_type pre, delim, post;
- // ½ÐÎÏÈϰϤò»ØÄꤷ¡¢¥¹¥È¥ê¡¼¥à¤Ëή¤»¤ë¤è¤¦¤Ë¤¹¤ë
+ // 出力範囲を指定し、ストリームに流せるようにする
template< typename InIte >
list_format_impl_< InIte, Elem, Elem, Elem >
operator()( const InIte& begin, const InIte& end ) const;
- // ½ÐÎÏÈϰϤò range ¤Ç»ØÄê
+ // 出力範囲を range で指定
template< typename Range >
list_format_impl_< gintenlib_const_ite_of(Range), Elem, Elem, Elem >
operator()( const Range& src ) const;
- // ostream_iterator ¤Î¤è¤¦¤Ë¿¶Éñ¤¦¥¤¥Æ¥ì¡¼¥¿¤òÀ½ºî¡£
- // ¥¤¥Æ¥ì¡¼¥¿¤¬´û¤ËÀ½ºî¤µ¤ì¤Æ¤¤¤¿¾ì¹ç¤Ï¡¢¤¤¤Ã¤¿¤ó¥ê¥¹¥È¤¬ÊĤ¸¤é¤ì¤ë
+ // ostream_iterator のように振舞うイテレータを製作。
+ // イテレータが既に製作されていた場合は、いったんリストが閉じられる
template< typename Stream >
iterator<Stream> make_iterator( Stream& os ) const;
typedef basic_list_formatter<const char*> list_formatter;
- µ¡Ç½¡§
- list_format(v) ¤ä list_format( begin, end ) ¤È»È¤¦Éôʬ¤Ç¡¢Âå¤ï¤ê¤Ë»ÈÍѤǤ¤ë¥Õ¥¡¥ó¥¯¥¿¡£
+ 機能:
+ list_format(v) や list_format( begin, end ) と使う部分で、代わりに使用できるファンクタ。
list_formatter formatter( pre, delim, post );
cout << formatter(v) << endl;
- ¤³¤Î¥³¡¼¥É¤Î¼Â¹Ô·ë²Ì¤Ï cout << list_format( v, pre, delim, post ) << endl; ¤ÈÅù²Á¡£
- ͽ¤á pre, delim, post ¤ÎÀßÄê¤ò¤·¤Æ¤ª¤¤¤Æ»È¤¤¤Þ¤ï¤·¤¿¤¤¾ì¹ç¤Ë»ÈÍѤǤ¤ë¡£
+ このコードの実行結果は cout << list_format( v, pre, delim, post ) << endl; と等価。
+ 予め pre, delim, post の設定をしておいて使いまわしたい場合に使用できる。
- ¤â¤¦°ì¤Ä¤Îµ¡Ç½¤È¤·¤Æ¡¢make_iterator() ¥á¥ó¥Ð´Ø¿ô¤ò¸Æ¤Ö¤³¤È¤Ç½ÐÎÏ¥¤¥Æ¥ì¡¼¥¿¤ò¹½ÃۤǤ¤ëµ¡Ç½¤â¤¢¤ê¡¢
+ もう一つの機能として、make_iterator() メンバ関数を呼ぶことで出力イテレータを構築できる機能もあり、
cout << formatter(v);
cout << formatter( v.begin(), v.end() );
copy( v.begin(), v.end(), formatter.make_iterator(cout) );
- ¤³¤Î»°¤Ä¤Îʸ¤Î¼Â¹Ô·ë²Ì¤Ï¡¢¤É¤ì¤âÅù¤·¤¤¡£
+ この三つの文の実行結果は、どれも等しい。
- »ÈÍÑÎ㡧
- // ¹½ÃÛ¤·¤Æ
+ 使用例:
+ // 構築して
gintenlib::list_formatter formatter( "[ ", " | ", " ]\n" );
- // Ǥ°Õ¤Î¥³¥ó¥Æ¥Ê v ¤ËÂФ·¡¢Å¬ÍѤ¹¤ë
+ // 任意のコンテナ v に対し、適用する
cout << formatter(v);
- // µÕ½ç¤Ëɽ¼¨¤ò¤·¤Æ¤ß¤ë
+ // 逆順に表示をしてみる
cout << formatter( v.rbegin(), v.rend() );
- // µÕ½ç¤Ëɽ¼¨¤¹¤ë¤Ë¤Ï¡¢¤³¤¦½ñ¤¤¤Æ¤â¤è¤¤
+ // 逆順に表示するには、こう書いてもよい
reverse_copy( v.begin(), v.end(), formatter.ite(cout) );
- Ê䡧
- ¡¦pre, delim, post ¤Ï const char* ¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
- Ǥ°ÕÍ×ÁǤò³ÊǼ¤·¤¿¤¤¾ì¹ç¤Ï¡¢list_formatter_ex ¤òÍѤ¤¤ë¡£
- ¡¦operator() ¤ÎŬÍÑ·ë²Ì¤Î¼è¤ê°·¤¤¤Ï¡¢ list_format ´Ø¿ô¤ÎÌá¤êÃͤÈƱ¤¸¤è¤¦¤Ë°·¤¦¡£
- ¡¦½ÐÎÏ¥¤¥Æ¥ì¡¼¥¿¤ò»ÈÍѤ¹¤ë¾ì¹ç¤ÎÃí°Õ»ö¹à¡§
- ¡¦pre Í×ÁǤϡֺǽé¤ÎÍ×ÁǤ¬¼ÂºÝ¤Ë½ÐÎϤµ¤ì¤ëľÁ°¡×¤Ë½ÐÎϤµ¤ì¤ë¡£
- ¡¦delim Í×ÁǤϡÖÆó²óÌܰʹߤÎÍ×ÁǤ¬½ÐÎϤµ¤ì¤ëľÁ°¡×¤Ë½ÐÎϤµ¤ì¤ë¡£
- ¡¦post Í×ÁǤϡ֥³¥Ô¡¼¤ò´Þ¤á¡¢Á´¤Æ¤Î¥¤¥Æ¥ì¡¼¥¿¤¬ÇË´þ¤µ¤ì¤¿¤È¤¡×¤Ë½ÐÎϤµ¤ì¤ë¡£
- ¤¿¤À¤·¡¢Ì¤¤À pre ¤¬½ÐÎϤµ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¡¢post ¤â½ÐÎϤµ¤ì¤Ê¤¤¡£
- ¡¦¤â¤·Á´¤Æ¤Î¥¤¥Æ¥ì¡¼¥¿¤¬ÇË´þ¤µ¤ì¤ëÁ°¤Ë¿·¤¿¤Ê¥¤¥Æ¥ì¡¼¥¿¤òÀ½ºî¤·¤¿¾ì¹ç¡¢
- ¤½¤Î»þÅÀ¤Ç post Í×ÁǤ¬½ÐÎϤµ¤ì¡¢¡Ö²¿¤â½ÐÎϤµ¤ì¤Æ¤¤¤Ê¤¤¡×¾õÂ֤ˤʤ롣
+ 補足:
+ ・pre, delim, post は const char* でなければならない。
+ 任意要素を格納したい場合は、list_formatter_ex を用いる。
+ ・operator() の適用結果の取り扱いは、 list_format 関数の戻り値と同じように扱う。
+ ・出力イテレータを使用する場合の注意事項:
+ ・pre 要素は「最初の要素が実際に出力される直前」に出力される。
+ ・delim 要素は「二回目以降の要素が出力される直前」に出力される。
+ ・post 要素は「コピーを含め、全てのイテレータが破棄されたとき」に出力される。
+ ただし、未だ pre が出力されていなければ、post も出力されない。
+ ・もし全てのイテレータが破棄される前に新たなイテレータを製作した場合、
+ その時点で post 要素が出力され、「何も出力されていない」状態になる。
*/
( param_type pre_, param_type delim_, param_type post_ )
: pre(pre_), delim(delim_), post(post_), iterator_count_(0) {}
- // ¥á¥ó¥ÐÊÑ¿ô¤Ê¤Î¤Ç¡¢¼«Í³¤Ë¥¢¥¯¥»¥¹¤Ç¤¤ë¡£
+ // メンバ変数なので、自由にアクセスできる。
element_type pre, delim, post;
- // ½ÐÎÏÈϰϤò¥¤¥Æ¥ì¡¼¥¿¤Ç»ØÄꤷ¤Æ¡¢¥¹¥È¥ê¡¼¥à¤Ëή¤»¤ë¤è¤¦¤Ë
+ // 出力範囲をイテレータで指定して、ストリームに流せるように
template< typename InIte >
list_format_impl_< InIte, Elem, Elem, Elem >
operator()( const InIte& begin, const InIte& end ) const
{
return list_format_impl_< InIte, Elem, Elem, Elem >( begin, end, pre, delim, post );
}
- // ½ÐÎÏÈϰϤò range ¤Ç»ØÄꤷ¤Æ¡¢¥¹¥È¥ê¡¼¥à¤Ëή¤»¤ë¤è¤¦¤Ë
+ // 出力範囲を range で指定して、ストリームに流せるように
template< typename Range >
list_format_impl_< typename boost::range_iterator<const Range>::type, Elem, Elem, Elem >
operator()( const Range& src ) const
( boost::begin(src), boost::end(src), pre, delim, post );
}
- // ¥¤¥Æ¥ì¡¼¥¿
+ // ã\82¤ã\83\86ã\83¬ã\83¼ã\82¿
template< typename Stream >
struct iterator
: std::iterator< std::output_iterator_tag, void, void, void, void >
iterator( const basic_list_formatter& formatter, Stream& os )
: formatter_(&formatter), os_(&os)
{
- // ½ÐÎϤ¬¡ÖÊĤ¸¤Æ¡×¤Ê¤¤¤Ê¤é¡¢ÊĤ¸¤ë
+ // 出力が「閉じて」ないなら、閉じる
close();
- // ¤³¤Î»þÅÀ¤Ç¥«¥¦¥ó¥È¤ÏÉé
+ // この時点でカウントは負
--formatter_->iterator_count_;
}
{
if( formatter_->iterator_count_ > 0 )
{
- // count ¤¬Àµ <==> ´û¤Ë²¿¤«½ÐÎϤµ¤ì¤Æ¤¤¤ë
+ // count が正 <==> 既に何か出力されている
if( --formatter_->iterator_count_ == 0 )
{
- // count ¤¬ 0 ¤Ë¤Ê¤Ã¤¿ <==> ¤â¤¦Â¾¤Î¥¤¥Æ¥ì¡¼¥¿¤Ï̵¤¤
+ // count が 0 になった <==> もう他のイテレータは無い
*os_ << formatter_->post;
}
}
one.swap(other);
}
- // ¼ÂºÝ¤Î½ÐÎÏ
+ // 実際の出力
template< typename T >
iterator& operator=( const T& val )
{
return *this;
}
- // ¡Ö½ÐÎϤòÊĤ¸¤ë¡×
+ // 「出力を閉じる」
iterator& close()
{
- // ¥«¥¦¥ó¥È¤¬Àµ <==> ½ÐÎϤ¬¡ÖÊĤ¸¤Æ¡×¤Ê¤¤
+ // カウントが正 <==> 出力が「閉じて」ない
if( formatter_->iterator_count_ > 0 )
{
- // ÊĤ¸¤ë
+ // 閉じる
*os_ << formatter_->post;
- // ¡Ö̤½ÐÎϡפؤÈÀßÄê
+ // 「未出力」へと設定
formatter_->iterator_count_ = -formatter_->iterator_count_;
}
return *this;
}
- // »²¾È³°¤·¤â¡¢Á°ÃÖ¡¿¸åÃÖ¥¤¥ó¥¯¥ê¥á¥ó¥È¤â¡¢²¿¤â¤·¤Ê¤¤
+ // 参照外しも、前置/後置インクリメントも、何もしない
iterator& operator*(){ return *this; }
iterator& operator++(){ return *this; }
iterator& operator++(int){ return *this; }
template< typename Stream >
friend struct iterator;
- // ½ÐÎÏ¥¤¥Æ¥ì¡¼¥¿¤òºî¤ë
+ // 出力イテレータを作る
template< typename Stream >
iterator<Stream> make_iterator( Stream& os ) const
{
/*
<gintenlib/math.hpp>
- math ¡§ M_PI ¤È¤¤¤Ã¤¿Äê¿ô¥Þ¥¯¥í¤ò³Î¼Â¤Ë #define ¤·¤Æ¤¯¤ì¤ë <cmath> ¥Ø¥Ã¥À
+ math : M_PI といった定数マクロを確実に #define してくれる <cmath> ヘッダ
- µ¡Ç½¡§
- <cmath> ¥Ø¥Ã¥À¤Ï¼ÂÁõ¤Ë¤è¤Ã¤Æ³Æ¼ï¿ô³ØÄê¿ô¤¬ define ¤µ¤ì¤Ê¤¤¾ì¹ç¤¬¤¢¤ë¤Î¤Ç¡¢
- ¤½¤¦¤¤¤¦¾ì¹ç¤ËÂбþ¤¹¤ë¤¿¤á¤Î¥Ø¥Ã¥À¤Ç¤¹¡£
- ³ÆÄê¿ô¤Î°ÕÌ£¤Ï¤½¤ì¤¾¤ì¤Î¥³¥á¥ó¥È¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡£
+ 機能:
+ <cmath> ヘッダは実装によって各種数学定数が define されない場合があるので、
+ そういう場合に対応するためのヘッダです。
+ 各定数の意味はそれぞれのコメントを参照してください。
*/
#include <cmath>
-// ¼«Á³Âпô¤ÎÄì e
+// 自然対数の底 e
#ifndef M_E
#define M_E 2.71828182845904523536
#endif
#define M_LN10 2.30258509299404568402
#endif
-// ±ß¼þΨ¦Ð
+// 円周率π
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
-// ¦Ð / 2
+// π / 2
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif
-// ¦Ð / 4
+// π / 4
#ifndef M_PI_4
#define M_PI_4 0.785398163397448309616
#endif
-// 1 / ¦Ð
+// 1 / π
#ifndef M_1_PI
#define M_1_PI 0.318309886183790671538
#endif
-// 2 / ¦Ð
+// 2 / π
#ifndef M_2_PI
#define M_2_PI 0.636619772367581343076
#endif
-// 2 / sqrt(¦Ð)
+// 2 / sqrt(π)
#ifndef M_2_SQRTPI
#define M_2_SQRTPI 1.12837916709551257390
#endif
<gintenlib/move_ptr.hpp>
- move_ptr ¡§ ½ê͸¢°ÜÆ°¼°¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿
+ move_ptr ï¼\9a æ\89\80æ\9c\89権移å\8b\95å¼\8fã\82¹ã\83\9eã\83¼ã\83\88ã\83\9dã\82¤ã\83³ã\82¿
- Àë¸À¡§
+ 宣言:
template<typename T, typename Deleter>
struct move_ptr
{
- // ´ðËÜŪ¤Ê¥á¥½¥Ã¥É¤Ï auto_ptr ¤ÈƱ¤¸¤Ê¤Î¤Ç¾Êά
+ // 基本的なメソッドは auto_ptr と同じなので省略
- // ¥Ç¥ê¡¼¥¿¤Î·¿
+ // デリータの型
typedef Deleter deleter;
- // ¥Ý¥¤¥ó¥¿¡Ê¤È¥Ç¥ê¡¼¥¿¡Ë¤«¤éºî¤ë¥³¥ó¥¹¥È¥é¥¯¥¿
+ // ã\83\9dã\82¤ã\83³ã\82¿ï¼\88ã\81¨ã\83\87ã\83ªã\83¼ã\82¿ï¼\89ã\81\8bã\82\89ä½\9cã\82\8bã\82³ã\83³ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
explicit move_ptr( T* p_, const Deleter& del_ = Deleter() );
- // release ¤¹¤ë¤ÈƱ»þ¤Ë deleter ¤ò¼èÆÀ¤¹¤ë
- // Ä̾ï¤Î release ´Ø¿ô¤âÅöÁ³¤¢¤ê¤Þ¤¹
+ // release すると同時に deleter を取得する
+ // 通常の release 関数も当然あります
T* release( Deleter& del_ );
- // deleter ¤ò¼èÆÀ¤¹¤ë
+ // deleter を取得する
Deleter get_deleter() const;
};
- µ¡Ç½¡§
- std::auto_ptr ¤ò¡¢Ç¤°Õ¤Î¥Ç¥ê¡¼¥¿¤ò»ØÄê¤Ç¤¤ë¤è¤¦³ÈÄ¥¤·¤¿½ê͸¢°ÜÆ°¼°¥Ý¥¤¥ó¥¿¤Ç¤¹¡£
- ¤½¤ì¤ÈƱ»þ¤Ë swap ¸Æ¤Ó½Ð¤·¤â½ÐÍè¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£
- ¤½¤ì°Ê³°¤Ï¡¢ºÙ¤«¤¤¤È¤³¤í¤Þ¤Ç std::auto_ptr ¤ÈƱ¤¸¤è¤¦¤Ë¿¶Éñ¤¦¤è¤¦¹©Éפ·¤Æ¤¤¤Þ¤¹¡£
- ¤¬¡¢¥Ç¥ê¡¼¥¿¤¬Ç¤°Õ¤Ë¤Ê¤Ã¤¿ÅÔ¹ç¾å¡¢Îã³°°ÂÁ´À¤Ç¤Ï¼ã´³Àȼå¤Ë¤Ê¤Ã¤Æ¤·¤Þ¤Ã¤Æ¤¤¤Þ¤¹¡£
- ¤Ê¤ª¡¢¥Ç¥ê¡¼¥¿¤È¤·¤Æ»È¤¨¤ë¤Î¤Ï¡¢¡Ö¥Ç¥Õ¥©¥ë¥È¹½ÃÛ²Äǽ¡×¤Ç¡Ö¥³¥Ô¡¼¤Ç¤¤ë¡×¡Ö¥Õ¥¡¥ó¥¯¥¿¡×¡£
- Îã³°°ÂÁ´À¤ò¹Í¤¨¤ë¤È¡Ö¥Ç¥Õ¥©¥ë¥È¹½ÃÛ»þ¡×¡Ö swap »þ¡×¤ËÎã³°¤òÅꤲ¤Ê¤¤¡¢¤È¤¤¤¦¾ò·ï¤âɬÍפǤ¹¡£
- ¤Þ¤¿¡¢¥Ç¥Õ¥©¥ë¥È¹½ÃÛ¤µ¤ì¤¿¥Ç¥ê¡¼¥¿¤ËÂФ·¤Æ´Ø¿ô¸Æ½Ð¤·¤¬¹Ô¤ï¤ì¤ë¤³¤È¤Ïͤê¤Þ¤»¤ó¡£
- ¤Ê¤Î¤Ç¡¢´Ø¿ô¥Ý¥¤¥ó¥¿¤ò¥Ç¥ê¡¼¥¿¤È¤·¤Æ»È¤¦¤³¤È¤âÉáÄ̤ˣϣˡ£
+ 機能:
+ std::auto_ptr を、任意のデリータを指定できるよう拡張した所有権移動式ポインタです。
+ それと同時に swap 呼び出しも出来るようになっています。
+ それ以外は、細かいところまで std::auto_ptr と同じように振舞うよう工夫しています。
+ が、デリータが任意になった都合上、例外安全性では若干脆弱になってしまっています。
+ なお、デリータとして使えるのは、「デフォルト構築可能」で「コピーできる」「ファンクタ」。
+ 例外安全性を考えると「デフォルト構築時」「 swap 時」に例外を投げない、という条件も必要です。
+ また、デフォルト構築されたデリータに対して関数呼出しが行われることは有りません。
+ なので、関数ポインタをデリータとして使うことも普通にOK。
*/
{
namespace detail
{
- // ´Ø¿ô¤ÎÃÍÊÖ¤·¤Î¤¿¤á¤Î¡¢¤Á¤ç¤Ã¤È¤·¤¿¹©É×
+ // 関数の値返しのための、ちょっとした工夫
template< typename T, typename Deleter >
struct move_ptr_ref_
{
} // namespace detail
- // ËÜÂÎ
+ // 本体
template< typename T, typename Deleter = ::gintenlib::deleter >
struct move_ptr : bool_comparable< move_ptr<T, Deleter> >
{
typedef T& reference;
typedef Deleter deleter;
- // ¥Ç¥Õ¥©¥ë¥È¥³¥ó¥¹¥È¥é¥¯¥¿
+ // ã\83\87ã\83\95ã\82©ã\83«ã\83\88ã\82³ã\83³ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
move_ptr() : pair_( 0, deleter() ) {}
- // ¥Ý¥¤¥ó¥¿¡Ê¤È¥Ç¥ê¡¼¥¿¡Ë¤«¤éºî¤ë¥³¥ó¥¹¥È¥é¥¯¥¿
+ // ã\83\9dã\82¤ã\83³ã\82¿ï¼\88ã\81¨ã\83\87ã\83ªã\83¼ã\82¿ï¼\89ã\81\8bã\82\89ä½\9cã\82\8bã\82³ã\83³ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
explicit move_ptr( pointer p_, const deleter& del_ = deleter() )
: pair_( p_, del_ ) {}
- // ½ê͸¢°ÜÆ°¥³¥ó¥¹¥È¥é¥¯¥¿
+ // æ\89\80æ\9c\89権移å\8b\95ã\82³ã\83³ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
move_ptr( move_ptr& src ) : pair_( 0, deleter() )
{
swap(src);
}
- // ¾¤Î move_ptr ¤«¤é¤Î½ê͸¢°ÜÆ°
- // ·¿¤ò¤Þ¤¿¤¤¤À swap ¤¬ÉÔ²Äǽ¤Ê°Ê¾å¡¢Èù̯¤ËÎã³°°ÂÁ´¤¸¤ã¤Ê¤¤¤Î¤ÇÃí°Õ
+ // 他の move_ptr からの所有権移動
+ // 型をまたいだ swap が不可能な以上、微妙に例外安全じゃないので注意
template< typename U, typename D >
move_ptr( move_ptr<U, D>& src ) : pair_( src.p(), src.del() )
{
src.release();
}
- // ¥Ç¥¹¥È¥é¥¯¥¿
+ // ã\83\87ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
~move_ptr()
{
if( p() )
}
// release pointer
- // ¥Ý¥¤¥ó¥¿¤ò¥ê¥ê¡¼¥¹¤·¡¢¥Ç¥ê¡¼¥¿¤ò½é´ü²½¤·¤Þ¤¹¡£
- // deleter ¤Î swap ¤¬Îã³°¤òÅꤲ¤Ê¤±¤ì¤ÐÎã³°°ÂÁ´¤Ç¤¹¡£
+ // ポインタをリリースし、デリータを初期化します。
+ // deleter の swap が例外を投げなければ例外安全です。
pointer release()
{
pointer ptr = 0;
return ptr;
}
- // ¥Ý¥¤¥ó¥¿¤ò¥ê¥ê¡¼¥¹¤·¡¢¥Ç¥ê¡¼¥¿¤â¼èÆÀ¡£
- // ÅϤµ¤ì¤ë»²¾È¤Ë²¿¤¬ÂåÆþ¤µ¤ì¤Æ¤¤¤Æ¤â¹½¤¤¤Þ¤»¤ó¡£
- // Îã³°°ÂÁ´À¤ò¹Íθ¤· swap ¤Ë¤è¤ë¼ÂÁõ¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£
+ // ポインタをリリースし、デリータも取得。
+ // 渡される参照に何が代入されていても構いません。
+ // 例外安全性を考慮し swap による実装を行っています。
pointer release( deleter& del_ )
{
pointer ptr = 0;
}
public:
- // ÃͤǤμõ¤±ÅϤ·¤Î¤¿¤á¤Î¡¢¤Á¤ç¤Ã¤È¤·¤¿¥Æ¥¯
+ // å\80¤ã\81§ã\81®å\8f\97ã\81\91渡ã\81\97ã\81®ã\81\9fã\82\81ã\81®ã\80\81ã\81¡ã\82\87ã\81£ã\81¨ã\81\97ã\81\9fã\83\86ã\82¯
move_ptr( const detail::move_ptr_ref_<T, Deleter>& src ) : pair_(src.pair_) {}
move_ptr& operator=( const detail::move_ptr_ref_<T, Deleter>& src )
<gintenlib/new_.hpp>
- new_ ¡§ ¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿ÈÇ new ±é»»»Ò
+ new_ : スマートポインタ版 new 演算子
- Àë¸À¡§
+ 宣言:
template<typename T>
struct ptr
{
template<typename Derived>
struct enable_static_new_;
- // ¤Û¤«¤Ë¡¢new_ ¤ÈƱ¤¸µ¡Ç½¤ò»ý¤Ã¤¿¥Õ¥¡¥ó¥¯¥¿¡¢ new_ptr<T> ¤¬Â¸ºß¤¹¤ë¡£
+ // ほかに、new_ と同じ機能を持ったファンクタ、 new_ptr<T> が存在する。
- µ¡Ç½¡§
- T ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤ò new ±é»»»Ò¤ÇÀ½ºî¤·¡¢boost::shared_ptr<T> ¤Ë³ÊǼ¤·¤ÆÊÖ¤¹´Ø¿ô¡£
- ´ðËÜŪ¤ÊÆ°ºî¤Ï boost::make_shared ¤ÈÁ´¤¯Æ±ÍͤǤ¢¤ë¤¬¡¢´ö¤Ä¤«¤Î°ã¤¤¤¬¤¢¤ë¡£
- ¤³¤Î´Ø¿ô¤«¤é¤Î new ¥¢¥¯¥»¥¹¤Ï¡¢Á´¤Æ new_core_access ¥¯¥é¥¹¤òÄ̤·¤Æ¹Ô¤ï¤ì¤ë¤¿¤á¡¢
+ 機能:
+ T 型のオブジェクトを new 演算子で製作し、boost::shared_ptr<T> に格納して返す関数。
+ 基本的な動作は boost::make_shared と全く同様であるが、幾つかの違いがある。
+ この関数からの new アクセスは、全て new_core_access クラスを通して行われるため、
friend class gintenlib::new_core_access;
- ¤ÈÀë¸À¤·¤¿¾å¤Ç¥³¥ó¥¹¥È¥é¥¯¥¿¤ò private Éôʬ¤Ë¤ª¤±¤Ð¡¢new_ °Ê³°¤«¤é¤Î¹½ÃÛ¤ò¶Ø»ß½ÐÍè¤ë¡£
- ¤â¤· private ¥³¥ó¥¹¥È¥é¥¯¥¿¤ÎÁ´¤Æ¤ò¸ø³«¤¹¤ë¤Î¤¬·ù¤Ê¾ì¹ç¤Ï¡¢
- enable_static_new_ ¥Æ¥ó¥×¥ì¡¼¥È¥¯¥é¥¹¤ò»È¤¦¤³¤È¤Ç¡¢¸Æ¤Ó½Ð¤·¤ò¥«¥¹¥¿¥Þ¥¤¥º¤Ç¤¤ë¡£
- ¤½¤Î¾ì¹ç¡¢¥³¥ó¥¹¥È¥é¥¯¥¿¤ÎÂå¤ï¤ê¤Ë new_ ¤È¤¤¤¦Ì¾Á°¤ÎÀÅŪ´Ø¿ô¤¬¸Æ¤Ð¤ì¤ë¤è¤¦¤Ë¤Ê¤ë¡£
+ と宣言した上でコンストラクタを private 部分におけば、new_ 以外からの構築を禁止出来る。
+ もし private コンストラクタの全てを公開するのが嫌な場合は、
+ enable_static_new_ テンプレートクラスを使うことで、呼び出しをカスタマイズできる。
+ その場合、コンストラクタの代わりに new_ という名前の静的関数が呼ばれるようになる。
- »ÈÍÑÎ㡧
+ 使用例:
boost::shared_ptr<hoge> p = gintenlib::new_<hoge>( 1, 2, 3 );
- // boost::shared_ptr<hoge> p( new hoge( 1, 2, 3 ) ); ¤ÈƱ¤¸
+ // boost::shared_ptr<hoge> p( new hoge( 1, 2, 3 ) ); と同じ
- ÍøÅÀ¡§
- ´ðËÜŪ¤ÊÍøÅÀ¤Ï boost::make_shared ¤ÈƱ¤¸¤Ç¤¹¡£
- ¤¹¤Ê¤ï¤ÁÎã³°°ÂÁ´À¤Î¶¯²½¤È¼Â¹Ô®Å٤κÇŬ²½¤ò´üÂԤǤ¤Þ¤¹¡£
- ¤³¤Î new_ ¥é¥¤¥Ö¥é¥ê¤Ï¡¢¤½¤ì¤Ë²Ã¤¨¡¢¥¢¥¯¥»¥¹À©¸Â¤ò¹Ô¤¦¤³¤È¤¬½ÐÍè¤Þ¤¹¡£
- ¤³¤ì¤Ë¤è¤ê¡¢ enable_shared_from_this ¤ò»È¤Ã¤¿¥¯¥é¥¹¤Ê¤É¡Ö³Î¼Â¤Ë shared_ptr ¤ËÆþ¤ì¤¿¤¤¡×
- ¥¯¥é¥¹¤ò°·¤¦¾ì¹ç¤Î°ÂÁ´À¤¬¾å¾º¤·¤Þ¤¹¡£
- ¤È¤Ï¤¤¤¨¡¢°ìÈ̤ˤϥ¹¥¿¥Ã¥¯¤Ë¤âÃÖ¤±¤¿Êý¤¬¤¤¤¤¤Î¤Ç¡¢»È¤¤¤É¤³¤í¤Ï¹Í¤¨¤Þ¤·¤ç¤¦¡£
+ 利点:
+ 基本的な利点は boost::make_shared と同じです。
+ すなわち例外安全性の強化と実行速度の最適化を期待できます。
+ この new_ ライブラリは、それに加え、アクセス制限を行うことが出来ます。
+ これにより、 enable_shared_from_this を使ったクラスなど「確実に shared_ptr に入れたい」
+ クラスを扱う場合の安全性が上昇します。
+ とはいえ、一般にはスタックにも置けた方がいいので、使いどころは考えましょう。
- È÷¹Í¡§
- °ú¿ô¤Ï const& ¤ÇÅϤµ¤ì¤Þ¤¹¡£Èóconst»²¾È¤òÅϤ·¤¿¤¤¾ì¹ç¤Ë¤Ï boost::ref ¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡£
+ 備考:
+ 引数は const& で渡されます。非const参照を渡したい場合には boost::ref を使ってください。
*/
#include <boost/type_traits/is_base_of.hpp>
-// °ú¿ô¤ÎºÇÂçÃÍ
+// 引数の最大値
#ifndef GINTENLIB_ARG_COUNT
#define GINTENLIB_ARG_COUNT 10
#endif
namespace gintenlib
{
- // new_ ¤ÎÌá¤êÃͤΥݥ¤¥ó¥¿·¿¡Ê¸½ºß¤Ï boost::shared_ptr °ìÂò¡Ë
+ // new_ の戻り値のポインタ型(現在は boost::shared_ptr 一択)
template<typename T>
struct ptr
{
typedef shared_ptr<T> type;
};
- // ¤³¤Î¥¯¥é¥¹¤«¤é·Ñ¾µ¤¹¤ë¤³¤È¤Ç¡¢¥³¥ó¥¹¥È¥é¥¯¥¿¤Ç¤Ï¤Ê¤¯ static ¤Î new_ ´Ø¿ô¤¬¸Æ¤Ð¤ì¤ë¤è¤¦¤Ë¤Ê¤ë
+ // このクラスから継承することで、コンストラクタではなく static の new_ 関数が呼ばれるようになる
template<typename Derived >
struct enable_static_new_
{
};
- // ¾å¤Î¥¯¥é¥¹¤ò·Ñ¾µ¤·¤Æ¤¤¤ë¤«¤É¤¦¤«¤òȽÃǤ¹¤ë¥¯¥é¥¹
+ // ä¸\8aã\81®ã\82¯ã\83©ã\82¹ã\82\92ç¶\99æ\89¿ã\81\97ã\81¦ã\81\84ã\82\8bã\81\8bã\81©ã\81\86ã\81\8bã\82\92å\88¤æ\96ã\81\99ã\82\8bã\82¯ã\83©ã\82¹
template<typename T>
struct enable_if_enabled_static_new_
: enable_if< boost::is_base_of< enable_static_new_<T>, T > > {};
- // ¥¯¥é¥¹¤Î private ¥á¥ó¥Ð¥¢¥¯¥»¥¹ÍѤΥ¯¥é¥¹¡£
- // ¥³¥ó¥¹¥È¥é¥¯¥¿¤Ê¤¤¤· new_ ÀÅŪ´Ø¿ô¤ò private ¤Ë¤ª¤¤¤¿¾å¤Ç¡¢
+ // クラスの private メンバアクセス用のクラス。
+ // コンストラクタないし new_ 静的関数を private においた上で、
// friend class gintenlib::new_core_access;
- // ¤È¤¹¤ì¤Ð¡¢ new_ ¤ò²ð¤·¤Æ¤·¤«À½ºî¤Ç¤¤Ê¤¤¥¯¥é¥¹¤Ë¤Ê¤ë¡£
+ // とすれば、 new_ を介してしか製作できないクラスになる。
class new_core_access
{
- // ¤³¤Î¥¯¥é¥¹¤Ï new_ptr ¥Õ¥¡¥ó¥¯¥¿¤Î¤ß¤¬»ÈÍѤǤ¤ë
+ // このクラスは new_ptr ファンクタのみが使用できる
template<typename T, typename>
friend class new_ptr;
- // Ä̾ï¤Î¥³¥ó¥¹¥È¥é¥¯¥¿¤ò¸Æ¤Ó½Ð¤¹ new
- // placement new ¤¬½ÐÍ褿¤Î¤Ç¤Û¤ÜÄÄÉå²½¾õÂÖ
+ // 通常のコンストラクタを呼び出す new
+ // placement new が出来たのでほぼ陳腐化状態
template<typename T>
static typename ptr<T>::type normal_new()
{
return typename ptr<T>::type( new T() );
}
- // ¿°ú¿ôÈÇ
+ // 多引数版
#define GINTENLIB_GEN( z, n, d ) \
template< typename T, BOOST_PP_ENUM_PARAMS( n, typename A ) > \
static typename ptr<T>::type normal_new \
#undef GINTENLIB_GEN
- // placement new ¤ò¸Æ¤Ó½Ð¤¹
+ // placement new を呼び出す
template<typename T>
static T* placement_new( void* p )
{
return ::new (p) T();
}
- // ¿°ú¿ôÈÇ
+ // 多引数版
#define GINTENLIB_GEN( z, n, d ) \
template< typename T, BOOST_PP_ENUM_PARAMS( n, typename A ) > \
static T* placement_new \
#undef GINTENLIB_GEN
- // new_ ÀÅŪ´Ø¿ô¤ò¸Æ¤Ó½Ð¤¹ new
+ // new_ 静的関数を呼び出す new
template<typename T>
static typename ptr<T>::type static_new()
{
return typename ptr<T>::type( T::new_() );
}
- // ¿°ú¿ôÈÇ
+ // 多引数版
#define GINTENLIB_GEN( z, n, d ) \
template< typename T, BOOST_PP_ENUM_PARAMS( n, typename A ) > \
static typename ptr<T>::type static_new \
#undef GINTENLIB_GEN
private:
- // ¸µ¤«¤é private ¤À¤¬¡¢¶¯Ä´¤¹¤ë°ÕÌ£¤Ç¤Ä¤±¤Æ¤ª¤¯¡£
- // ¤³¤Î¥¯¥é¥¹¤Ï¹½ÃۤǤ¤Ê¤¤¡£
+ // 元から private だが、強調する意味でつけておく。
+ // このクラスは構築できない。
new_core_access();
};
- // ´Ø¿ô¥ª¥Ö¥¸¥§¥¯¥ÈÈÇ new_¡Ê¥³¥ó¥¹¥È¥é¥¯¥¿ÈÇ¡Ë
+ // 関数オブジェクト版 new_(コンストラクタ版)
template<typename T, typename = void>
struct new_ptr
{
typedef typename ptr<T>::type result_type;
- // <boost/make_shared.hpp> ¤Ë½¬¤¤¡¢¸úΨŪ¤Ê¼ÂÁõ¤ò¹Ô¤¦
+ // <boost/make_shared.hpp> に習い、効率的な実装を行う
result_type operator()() const
{
- // ²¾¤Î shared_ptr ¤òºî¤Ã¤Æ»²¾È¥«¥¦¥ó¥È¤òºîÀ®¤·
+ // 仮の shared_ptr を作って参照カウントを作成し
shared_ptr<T> pt( static_cast<T*>(0), deleter() );
- // »²¾È¥«¥¦¥ó¥ÈÆâ¤Î¥Ç¥ê¡¼¥¿¤Î¥¢¥É¥ì¥¹¤ò¼èÆÀ¤¹¤ë
+ // 参照カウント内のデリータのアドレスを取得する
optional_storage<T> &storage = boost::get_deleter<deleter>(pt)->storage;
void* pv = storage.address();
- // ¥Ç¥ê¡¼¥¿Æâ¤ËÍÑ°Õ¤µ¤ì¤¿Îΰè¤Ë¥ª¥Ö¥¸¥§¥¯¥È¤ò¹½ÃÛ¤·¡¢
+ // デリータ内に用意された領域にオブジェクトを構築し、
T* pt2 = new_core_access::template placement_new<T>( pv );
storage.set_initialized();
- // ¹½ÃÛ¤µ¤ì¤¿¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¢¥É¥ì¥¹¤ÈºÇ½é¤Ëºî¤Ã¤¿»²¾È¥«¥¦¥ó¥È¤«¤é¡¢
- // ²þ¤á¤Æ shared_ptr ¤òÀ©ºî¤¹¤ë
+ // 構築されたオブジェクトのアドレスと最初に作った参照カウントから、
+ // 改めて shared_ptr を制作する
return make_result( pt, pt2 );
}
- // ¿°ú¿ôÈÇ
+ // 多引数版
#define GINTENLIB_GEN( z, n, d ) \
template< BOOST_PP_ENUM_PARAMS( n, typename A ) > \
result_type operator() \
#undef GINTENLIB_GEN
private:
- // ¥«¥¹¥¿¥à¥Ç¥ê¡¼¥¿
+ // ã\82«ã\82¹ã\82¿ã\83 ã\83\87ã\83ªã\83¼ã\82¿
struct deleter
{
deleter(){}
- // ¥³¥Ô¡¼¤Ç¤Ï²¿¤â¤·¤Ê¤¤¤è¤¦ºÇŬ²½
+ // コピーでは何もしないよう最適化
deleter( const deleter& ) {}
- // ¥ª¥Ö¥¸¥§¥¯¥È¤¬³ÊǼ¤µ¤ì¤ëÎΰè
+ // オブジェクトが格納される領域
optional_storage<T> storage;
typedef void result_type;
}; // struct deleter
- // ½ªÎ»½èÍý
+ // 終了処理
result_type make_result( const result_type& pt, T* pt2 ) const
{
- // enable_shared_from_this ¤ò»È¤Ã¤Æ¤¤¤ë¾ì¹ç¡¢Àµ¤·¤¯¥¢¥É¥ì¥¹¤òÀßÄꤹ¤ëɬÍפ¬¤¢¤ë
+ // enable_shared_from_this を使っている場合、正しくアドレスを設定する必要がある
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
- // ¤³¤Î¥³¥ó¥¹¥È¥é¥¯¥¿¤Ï pt ¤Î»²¾È¥«¥¦¥ó¥È¤È pt2 ¤Î¥¢¥É¥ì¥¹¤ò»È¤Ã¤Æ shared_ptr ¤òºî¤ë
+ // このコンストラクタは pt の参照カウントと pt2 のアドレスを使って shared_ptr を作る
return result_type( pt, pt2 );
}
}; // struct new_ptr<T>
- // ´Ø¿ô¥ª¥Ö¥¸¥§¥¯¥ÈÈÇ new_¡ÊÀÅŪ´Ø¿ôÈÇ¡Ë
+ // 関数オブジェクト版 new_(静的関数版)
template<typename T>
struct new_ptr< T, typename enable_if_enabled_static_new_<T>::type >
{
{
return new_core_access::template static_new<T>();
}
- // ¿°ú¿ôÈÇ
+ // 多引数版
#define GINTENLIB_GEN( z, n, d ) \
template< BOOST_PP_ENUM_PARAMS( n, typename A ) > \
result_type operator() \
};
- // ËÜÂÎ
+ // 本体
template<typename T>
inline typename ptr<T>::type new_()
{
return new_ptr<T>()();
}
- // ¿°ú¿ôÈÇ
+ // 多引数版
#define GINTENLIB_GEN( z, n, d ) \
template< typename T, BOOST_PP_ENUM_PARAMS( n, typename A ) > \
inline typename ptr<T>::type new_ \
<gintenlib/optional_storage.hpp>
- optional_storage ¡§ ¸å¤«¤é½é´ü²½¤Ç¤¤ë¥á¥â¥êÎΰè
+ optional_storage : 後から初期化できるメモリ領域
- Àë¸À¡§
+ 宣言:
template<typename T>
struct optional_storage
: private boost::noncopyable
typedef T element_type;
typedef T value_type;
- // ¹½ÃÛ¡¿ÇË´þ
+ // 構築/破棄
optional_storage();
~optional_storage() throw ();
- // Ãæ¤Î¥Ç¡¼¥¿¤òÇË´þ¤¹¤ë
+ // 中のデータを破棄する
void destory();
- // ¥«¥¹¥¿¥à¥Ç¥¹¥È¥é¥¯¥¿¤ò»È¤Ã¤Æ¥Ç¡¼¥¿¤òÇË´þ¤¹¤ë
+ // カスタムデストラクタを使ってデータを破棄する
template<typename Destructor>
void destory( Destructor d );
- // storage ¤ÎÀ¸¥¢¥É¥ì¥¹¤òÆÀ¤ë
+ // storage の生アドレスを得る
void* address();
const void* address() const;
- // ½é´ü²½¤º¤ß¤«Èݤ«
+ // 初期化ずみか否か
bool initialized() const;
- // ½é´ü²½¤º¤ß¥Þ¡¼¥¯¤ò¤Ä¤±¤ë
+ // 初期化ずみマークをつける
void set_initialized();
- // ¹½ÃۺѤߤʤ顢¹½ÃÛ¤µ¤ì¤¿¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¢¥É¥ì¥¹¤ò¼èÆÀ¤¹¤ë
+ // 構築済みなら、構築されたオブジェクトのアドレスを取得する
T* get();
const T* get() const;
- // ¥¢¥í¡¼±é»»
+ // アロー演算
T* operator->();
const T* operator->() const;
- // »²¾È³°¤·
+ // 参照外し
T& operator*();
const T& operator*() const;
}; // optional_storage<T>
- µ¡Ç½¡§
- ͽ¤á¥á¥â¥êÎΰè¤ò³ÎÊݤ·¤Æ±¾¡¹¡¢¤È¤¤¤¦¡¢¾¯¤·±ø¤¤½èÍý¤ò¹Ô¤¤¤¿¤¤¾ì¹ç¤Ã¤Æ¤Î¤¬»þ¡¹¤¢¤ê¤Þ¤¹¡£
- ¤½¤¦¤¤¤¦¤È¤¤Ë¡¢¤¢¤ëÄøÅٰ¿´¤·¤Æ½èÍý¤ò¹Ô¤¨¤ë¤è¤¦¤Ë¤¹¤ë°Ù¤Î¥¯¥é¥¹¥Æ¥ó¥×¥ì¡¼¥È¤Ç¤¹¡£
- ͽ¤á¥á¥â¥êÎΰè¤ò³ÎÊݤ·¤Æ²¿¤«¤·¤é¤Î½èÍý¤ò¤·¤Æ¤«¤é¡¢ address() ¤Ç̤½é´ü²½¥á¥â¥ê¤Î¥¢¥É¥ì¥¹¤ò¼èÆÀ¡£
- ¤½¤Î¥¢¥É¥ì¥¹¤Ë placement new ¤Ç¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤Ã¤¿¤é set_initialized() ¤ò¸Æ¤Ö¡£
- ¤³¤Î°ìÏ¢¤ÎÆ°ºî¤µ¤¨¹Ô¤¨¤Ð¡¢¸å¤ÎÇË´þ¤ä²¿¤ä¤é¤Ï¡¢Á´¤Æ optional_storage<T> ¤¬¤ä¤Ã¤Æ¤¯¤ì¤Þ¤¹¡£
- boost::optional<T> ¤Ç¤â»÷¤¿¤è¤¦¤Ê¤³¤È¤Ï½ÐÍè¤Þ¤¹¤¬¡¢Ì¤½é´ü²½¥¢¥É¥ì¥¹¤òľÀÜÆÀ¤é¤ì¤Þ¤»¤ó¡£
-
- ¤Þ¤¿¡¢optional_storage<T> ¤ò»È¤Ã¤Æ¹½ÃۺѤߥª¥Ö¥¸¥§¥¯¥È¤òÇË´þ¤¹¤ë¾ì¹ç¤Ë¤Ï¡¢
- ÉáÄ̤Υǥ¹¥È¥é¥¯¥¿¤À¤±¤Ç¤Ê¤¯¡¢¥«¥¹¥¿¥à¥Ç¥¹¥È¥é¥¯¥¿¤ò»ØÄꤹ¤ë¤³¤È¤â¤Ç¤¤Þ¤¹¡£
- ¤½¤¦¤¤¤¦¾ì¹ç¤ÏÌÀ¼¨Åª¤Ë destory ¤ò¸Æ¤Ó½Ð¤·¡¢¤½¤Î°ú¿ô¤Ë¥«¥¹¥¿¥à¥Ç¥¹¥È¥é¥¯¥¿¤òÅϤ·¤Þ¤·¤ç¤¦¡£
+ 機能:
+ 予めメモリ領域を確保して云々、という、少し汚い処理を行いたい場合ってのが時々あります。
+ そういうときに、ある程度安心して処理を行えるようにする為のクラステンプレートです。
+ 予めメモリ領域を確保して何かしらの処理をしてから、 address() で未初期化メモリのアドレスを取得。
+ そのアドレスに placement new でオブジェクトを作ったら set_initialized() を呼ぶ。
+ この一連の動作さえ行えば、後の破棄や何やらは、全て optional_storage<T> がやってくれます。
+ boost::optional<T> でも似たようなことは出来ますが、未初期化アドレスを直接得られません。
+
+ また、optional_storage<T> を使って構築済みオブジェクトを破棄する場合には、
+ 普通のデストラクタだけでなく、カスタムデストラクタを指定することもできます。
+ そういう場合は明示的に destory を呼び出し、その引数にカスタムデストラクタを渡しましょう。
- »ÈÍÑÎ㡧
- // ¤È¤ê¤¢¤¨¤ºÎΰè¤À¤±³ÎÊݤ·¤Æ
+ 使用例:
+ // とりあえず領域だけ確保して
gintenlib::optional_storage<hoge> storage;
- // storage ¤¬É¬Íפʲ¿¤«¤·¤é¤Î½èÍý
+ // storage が必要な何かしらの処理
- // placement new ¤Ç¹½ÃÛ
+ // placement new で構築
::new ( storage.address() ) hoge( args );
- // ¹½ÃÛ¤·¤¿¤è¥Þ¡¼¥¯¤ò¤Ä¤±¤ë
+ // 構築したよマークをつける
storage.set_initialized();
- // ¤á¤ó¤É¤¤¤Î¤Ç»²¾ÈÊÑ¿ô¤Ç°Ê¹ß¤Î¥¢¥¯¥»¥¹¤ò´Êά²½
+ // めんどいので参照変数で以降のアクセスを簡略化
hoge& h = *storage;
- // °Ê¹ß¡¢ h ¤ÏÉáÄ̤Πhoge ¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ°·¤¨¤ë
- // storage ¤Î͸ú´ü¸Â¤¬ÀÚ¤ì¤ë¤È¡¢¼«Æ°¤Ç¥Ç¥¹¥È¥é¥¯¥È¤µ¤ì¤ë¤Î¤Ç°Â¿´
+ // 以降、 h は普通の hoge オブジェクトとして扱える
+ // storage の有効期限が切れると、自動でデストラクトされるので安心
- Ê䡧
- ¡¦placement new ¤ò¸Æ¤ó¤À¤é¡¢Â¨ set_initialized() ¤ò¸Æ¤Ó½Ð¤·¤Þ¤·¤ç¤¦¡£
- ¡¦¤½¤ì¤µ¤¨¼é¤ì¤Ð¡¢Èó¾ï¤Ë°ÂÁ´À¤Ï¹â¤¤È¦¤Ç¤¹¡£
+ 補足:
+ ・placement new を呼んだら、即 set_initialized() を呼び出しましょう。
+ ・それさえ守れば、非常に安全性は高い筈です。
*/
namespace gintenlib
{
- // ¤Á¤ç¤Ã¤È°ÂÁ´À¤ÎÄ㤤 boost::optional
+ // ちょっと安全性の低い boost::optional
template<typename T>
struct optional_storage
: private boost::noncopyable
typedef T& reference;
typedef const T& const_reference;
- // ¹½ÃÛ¡¿ÇË´þ
+ // 構築/破棄
optional_storage()
: initialized_( false ) {}
destory();
}
- // Ãæ¤Î¥Ç¡¼¥¿¤òÇË´þ¤¹¤ë
+ // 中のデータを破棄する
void destory()
{
destory( destructor() );
}
- // ¥«¥¹¥¿¥à¥Ç¥¹¥È¥é¥¯¥¿¤ò»È¤Ã¤Æ¥Ç¡¼¥¿¤òÇË´þ¤¹¤ë
+ // カスタムデストラクタを使ってデータを破棄する
template<typename Destructor>
void destory( Destructor d )
{
}
}
- // storage ¤ÎÀ¸¥¢¥É¥ì¥¹¤òÆÀ¤ë
+ // storage の生アドレスを得る
void* address(){ return storage_.address(); }
const void* address() const { return storage_.address(); }
- // ½é´ü²½¤º¤ß¤«Èݤ«
+ // 初期化ずみか否か
bool initialized() const { return initialized_; }
- // ½é´ü²½¤º¤ß¥Þ¡¼¥¯¤ò¤Ä¤±¤ë
+ // 初期化ずみマークをつける
void set_initialized() { initialized_ = true; }
- // ¹½ÃۺѤߤʤ顢¹½ÃÛ¤µ¤ì¤¿¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¢¥É¥ì¥¹¤ò¼èÆÀ¤¹¤ë
+ // 構築済みなら、構築されたオブジェクトのアドレスを取得する
T* get(){ return initialized() ? static_cast<T*>( address() ) : 0; }
const T* get() const { return initialized() ? static_cast<const T*>( address() ) : 0; }
- // ¥¢¥í¡¼±é»»
+ // アロー演算
T* operator->()
{
using namespace std;
assert( initialized() );
return get();
}
- // »²¾È³°¤·
+ // 参照外し
T& operator*()
{
using namespace std;
/*
<gintenlib/options.hpp>
- options ¡§ getopt Ū¥×¥í¥°¥é¥à¥ª¥×¥·¥ç¥ó²òÀÏ
+ options : getopt 的プログラムオプション解析
- ¾Ü¤·¤¯¤Ï <gintenlib/options/options.hpp> ¤ò»²¾È¡£
+ 詳しくは <gintenlib/options/options.hpp> を参照。
*/
/*
<gintenlib/options/exceptions.hpp>
- ¥ª¥×¥·¥ç¥ó²òÀϥ饤¥Ö¥é¥êÍÑÎã³°¥¯¥é¥¹
+ ã\82ªã\83\97ã\82·ã\83§ã\83³è§£æ\9e\90ã\83©ã\82¤ã\83\96ã\83©ã\83ªç\94¨ä¾\8bå¤\96ã\82¯ã\83©ã\82¹
- Àë¸À¡§
- // Îã³°´ðËÜ¥¯¥é¥¹
+ 宣言:
+ // ä¾\8bå¤\96å\9fºæ\9c¬ã\82¯ã\83©ã\82¹
struct option_error : std::runtime_error;
- // ¥ª¥×¥·¥ç¥ó»ØÄêʸ»úÎ󤬤ª¤«¤·¤¤
+ // オプション指定文字列がおかしい
struct invalid_option_string : option_error;
- // »ØÄꤵ¤ì¤Ê¤¤¥ª¥×¥·¥ç¥ó¤¬ÅϤµ¤ì¤¿
+ // 指定されないオプションが渡された
struct unknown_option : option_error;
- // °ú¿ô¤¬É¬ÍפʤΤËÅϤµ¤ì¤Ê¤«¤Ã¤¿
+ // 引数が必要なのに渡されなかった
struct option_requires_argument : option_error;
- µ¡Ç½¡§
- Îã³°ÍÑ¥¯¥é¥¹¤Ç¤¹¡£°Ê¾å¡£
+ 機能:
+ 例外用クラスです。以上。
*/
namespace gintenlib
{
- // Îã³°´ðËÜ¥¯¥é¥¹
+ // ä¾\8bå¤\96å\9fºæ\9c¬ã\82¯ã\83©ã\82¹
struct option_error : std::runtime_error
{
explicit option_error( const std::string& what_ )
: std::runtime_error( what_ ) {}
};
- // ¥ª¥×¥·¥ç¥ó»ØÄêʸ»úÎ󤬤ª¤«¤·¤¤
+ // オプション指定文字列がおかしい
struct invalid_option_string : option_error
{
explicit invalid_option_string( const std::string& optstr )
: option_error( "invalid option format string: " + optstr ) {}
};
- // »ØÄꤵ¤ì¤Ê¤¤¥ª¥×¥·¥ç¥ó¤¬ÅϤµ¤ì¤¿
+ // 指定されないオプションが渡された
struct unknown_option : option_error
{
explicit unknown_option( const std::string& opt )
: option_error( "unknown option: " + opt ) {}
};
- // °ú¿ô¤¬É¬ÍפʤΤËÅϤµ¤ì¤Ê¤«¤Ã¤¿
+ // 引数が必要なのに渡されなかった
struct option_requires_argument : option_error
{
explicit option_requires_argument( const std::string& opt )
/*
<gintenlib/options/options.hpp>
- options ¡§ getopt Ū¥×¥í¥°¥é¥à¥ª¥×¥·¥ç¥ó²òÀÏ
+ options : getopt 的プログラムオプション解析
- Àë¸À¡§
+ 宣言:
struct options
{
- // »ØÄꤵ¤ì¤¿Ê¸»úÎó¤Ç¥ª¥×¥·¥ç¥ó²òÀÏ¥ª¥Ö¥¸¥§¥¯¥È¤òºî¤ë
- // ʸ»úÎó¤Ï´ðËÜŪ¤Ë getopt ¸ß´¹¡¢ËÁƬ¤Î : ¤È - ¤ÎÆ°ºî¤Î¤ß°ã¤¦
+ // 指定された文字列でオプション解析オブジェクトを作る
+ // 文字列は基本的に getopt 互換、冒頭の : と - の動作のみ違う
explicit options( const std::string& optstr, int argc, char* argv[] );
- // ¼ÂºÝ¤Ë¥ª¥×¥·¥ç¥ó¤ò²òÀϤ¹¤ë
+ // 実際にオプションを解析する
typedef int result_type;
result_type operator()();
- // ¼¡¤Ë½èÍý¤¹¤ë°ú¿ô¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹
+ // 次ã\81«å\87¦ç\90\86ã\81\99ã\82\8bå¼\95æ\95°ã\81®ã\82¤ã\83³ã\83\87ã\83\83ã\82¯ã\82¹
int optind() const;
- // ¼¡¤Ë½èÍý¤¹¤ë°ú¿ô¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤òÀßÄꤹ¤ë
+ // 次に処理する引数のインデックスを設定する
void set_optind( int new_index = 1 );
- // °ú¿ô
+ // 引数
const std::string& optarg() const;
- // ¥¨¥é¡¼»þ¤ËÆɤó¤Ç¤¤¤¿Ê¸»ú
+ // エラー時に読んでいた文字
int optopt() const;
}; // struct options
- µ¡Ç½¡§
- ¥³¥ó¥¹¥È¥é¥¯¥¿¤ÇÍ¿¤¨¤é¤ì¤¿¥Õ¥©¡¼¥Þ¥Ã¥È¤ò¸µ¤Ë¡¢¥×¥í¥°¥é¥à¥ª¥×¥·¥ç¥ó¤ò²òÀϤ·¤Þ¤¹¡£
- ¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï´ðËÜŪ¤Ë£Ç£Î£Õ¤Î getopt ¸ß´¹¤Ç¤¹¤¬¡¢¼ã´³¤Î°ã¤¤¤¬¤¢¤ê¡¢
- ¤Þ¤ºÌ¤ÃΤΥª¥×¥·¥ç¥ó¤¬Í¿¤¨¤é¤ì¤¿¾ì¹ç¡¢'?'¤òÊÖ¤µ¤ºÎã³°¤òÅꤲ¤ëÅÀ¡£
- ¤³¤ì¤Ï ':' ¤ò¥Õ¥©¡¼¥Þ¥Ã¥È¤ÎƬ¤ËÃÖ¤¯¤³¤È¤Ç¡¢Îã³°¤òÅꤲ¤º '?' ¤òÊÖ¤¹¤è¤¦¤ËÊѹ¹¤Ç¤¤Þ¤¹¡£
- ¤³¤Î¤È¤¡¢°ú¿ô¤¬Â¤ê¤Ê¤¤¾ì¹ç¤Ï ':' ¤òÊÖ¤·¤Þ¤¹¡Ê¤³¤³¤Ï getopt ¤ÎÆ°ºî¤ÈƱ¤¸¡Ë¡£
- ¤Þ¤¿¥ª¥×¥·¥ç¥óʸ»úÎó¤ÎƬ¤Ë '-' ¤ò»ØÄꤹ¤ë¤³¤È¤Ï½ÐÍè¤Þ¤»¤ó¡Ê£Ç£Î£Õ¤Î»ÅÍͤ¬Îɤ¯Ê¬¤«¤é¤Ê¤«¤Ã¤¿¤Î¤Ç¡Ë¡£
- ¤Þ¤¿´Ä¶ÊÑ¿ô POSIXLY_CORRECT ¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤Æ¤âÆ°ºî¤Ï¤Ê¤Ë¤âÊѤï¤ê¤Þ¤»¤ó¡£
- '+' ¤Ç»Ï¤Þ¤ëʸ»úÎó¤òÅϤ¹¤³¤È¤ÇÂн褷¤Æ¤¯¤À¤µ¤¤¡£
+ 機能:
+ コンストラクタで与えられたフォーマットを元に、プログラムオプションを解析します。
+ フォーマットは基本的にGNUの getopt 互換ですが、若干の違いがあり、
+ まず未知のオプションが与えられた場合、'?'を返さず例外を投げる点。
+ これは ':' をフォーマットの頭に置くことで、例外を投げず '?' を返すように変更できます。
+ このとき、引数が足りない場合は ':' を返します(ここは getopt の動作と同じ)。
+ またオプション文字列の頭に '-' を指定することは出来ません(GNUの仕様が良く分からなかったので)。
+ また環境変数 POSIXLY_CORRECT が定義されていても動作はなにも変わりません。
+ '+' で始まる文字列を渡すことで対処してください。
- ¶ñÂÎŪ¤Ê¥Õ¥©¡¼¥Þ¥Ã¥È¤ÎÍ¿¤¨Êý¤Ï°Ê²¼¤ÎÄ̤ꡧ
- ñÆȤÎʸ»ú¤Ï¡¢°ú¿ô¤ò¼è¤é¤Ê¤¤¥ª¥×¥·¥ç¥ó¤ò¼¨¤¹¡£
- ʸ»ú¤Î¸å¤Ë ':' ¤¬Â³¤¤¤Æ¤¤¤ë¾ì¹ç¡¢¤½¤Î¥ª¥×¥·¥ç¥ó¤Ï°ú¿ô¤ò¼è¤ë¡£
- ʸ»ú¤Î¸å¤ËÆó¤Ä¤Î ':' ¤¬Â³¤¤¤Æ¤¤¤ë¾ì¹ç¡¢¤½¤Î¥ª¥×¥·¥ç¥ó¤Ï°ú¿ô¤ò¼è¤ê¤¦¤ë¡£
- Î㡧
- "ab:c::d" ¤ÈÅϤµ¤ì¤¿¤é¡¢a ¤È d ¤Ï°ú¿ô¤Ê¤·¡¢ b ¤Ï°ú¿ô¤¢¤ê¡¢ c ¤Ï°ú¿ô¤Ï¤¢¤Ã¤Æ¤â¤Ê¤¯¤Æ¤â¤¤¤¤
-
- »ÈÍÑÎ㡧
- // usage: ¥³¥Þ¥ó¥É̾ ¥ª¥×¥·¥ç¥óʸ»úÎó ²òÀϤµ¤»¤¿¤¤°ú¿ô
- // ¤³¤¦µ¯Æ°¤¹¤ë¤³¤È¤Ë¤è¤ê¡¢ options ¤Î¤Û¤ÜÁ´µ¡Ç½¤ò¥Æ¥¹¥È¤Ç¤¤ëÎã¤Ç¤¹
+ 具体的なフォーマットの与え方は以下の通り:
+ 単独の文字は、引数を取らないオプションを示す。
+ 文字の後に ':' が続いている場合、そのオプションは引数を取る。
+ 文字の後に二つの ':' が続いている場合、そのオプションは引数を取りうる。
+ 例:
+ "ab:c::d" と渡されたら、a と d は引数なし、 b は引数あり、 c は引数はあってもなくてもいい
+
+ 使用例:
+ // usage: コマンド名 オプション文字列 解析させたい引数
+ // こう起動することにより、 options のほぼ全機能をテストできる例です
#include <gintenlib/options.hpp>
#include <gintenlib/cast.hpp>
int main( int argc, char* argv[] )
{
- // °ÅÌÛ¥¥ã¥¹¥È
+ // 暗黙キャスト
using gintenlib::cast;
try
{
if( argc < 2 ){ throw gintenlib::option_error("missing 'OPTSTR'"); }
- // argv[1] ¤ÏÆÃÊ̤ʰú¿ô
+ // argv[1] は特別な引数
gintenlib::options opt( argv[1], argc, argv );
- // ¤Ê¤Î¤Ç²òÀϤµ¤»¤Ê¤¤
+ // なので解析させない
opt.set_optind( 2 );
for(;;)
{
- // ²òÀϤµ¤»¤ë¡£ ch ¤Ë¤Ï¥ª¥×¥·¥ç¥ó¤Îʸ»ú¤¬Æþ¤ë
+ // 解析させる。 ch にはオプションの文字が入る
int ch = opt();
- if( ch == -1 ){ break; } // -1: ²òÀϽª¤ï¤ê
+ if( ch == -1 ){ break; } // -1: 解析終わり
switch(ch)
{
case '?':
- // ':' ¤Ç»Ï¤Þ¤ë¥ª¥×¥·¥ç¥óʸ»úÎó¤Ø¤ÎÂбþ
+ // ':' で始まるオプション文字列への対応
cout << "unknown option '" << cast<char>( opt.optopt() ) << "' is given. continue...\n";
break;
case ':':
- // Ʊ¤¸¤¯ ':' ¤Ç»Ï¤Þ¤ë¥ª¥×¥·¥ç¥óʸ»úÎó¤Ø¤ÎÂбþ
+ // 同じく ':' で始まるオプション文字列への対応
cout << "option '" << cast<char>( opt.optopt() ) << "'requires argument. continue...\n";
break;
default:
- // ¥ª¥×¥·¥ç¥ó°ìÈÌ
+ // オプション一般
cout << "option '" << cast<char>( ch ) << "' is given.\n";
- // °ú¿ô¤Ï optarg() ¤Ç³ÍÆÀ
- // °ú¿ô¤¬Ìµ¤¤¾ì¹ç¤Ï string() ¤¬Æþ¤ë
+ // 引数は optarg() で獲得
+ // 引数が無い場合は string() が入る
if( !opt.optarg().empty() )
{
cout << " argument: " << opt.optarg() << endl;
}
}
- // ²òÀϽªÎ»¡£Í¾¤Ã¤¿¥ª¥×¥·¥ç¥ó¤Ï argv[opt.optind()] ¡Á argv[argc-1] ¤Ë½¸¤á¤é¤ì¤ë
- // ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï¡¢¥ª¥×¥·¥ç¥ó°ú¿ô¤¬È󥪥ץ·¥ç¥ó°ú¿ô¤Î¸å¤Ë¤¢¤ë¾ì¹ç¡¢ argv ¤Î½ç½ø¤òÆþ¤ìÂؤ¨¤ë
- // ¤³¤ÎÆ°ºî¤òÈò¤±¤¿¤¤¾ì¹ç¤Ï¡¢¥³¥ó¥¹¥È¥é¥¯¥¿¤Î°ú¿ô¤ò '+' ¤Ç»Ï¤á¤ì¤Ð¤è¤¤
+ // 解析終了。余ったオプションは argv[opt.optind()] 〜 argv[argc-1] に集められる
+ // デフォルトでは、オプション引数が非オプション引数の後にある場合、 argv の順序を入れ替える
+ // この動作を避けたい場合は、コンストラクタの引数を '+' で始めればよい
cout << "\nextra options are:\n";
for( int i = opt.optind(); i < argc; ++i )
{
}
catch( gintenlib::option_error& e )
{
- // ¥ª¥×¥·¥ç¥ó²òÀϤ˼ºÇÔ¤·¤ÆÎã³°¤¬Åꤲ¤é¤ì¤¿¾ì¹ç¤Ï¤³¤Á¤é¤ËÈô¤Ö
+ // オプション解析に失敗して例外が投げられた場合はこちらに飛ぶ
cerr << e.what() << endl;
cerr << "usage: " << argv[0] << " OPTSTR [OPTIONS]\n";
}
catch( std::exception& e )
{
- // ¤½¤Î¤Û¤«¤ÎÎã³°
+ // そのほかの例外
cerr << e.what() << endl;
return 1;
}
} // main( argc, argv )
- Ê䡧
- ¡¦¼ç¤Ë <unistd.h> ¤¬¥¤¥ó¥¯¥ë¡¼¥É¤Ç¤¤Ê¤¤½èÍý·Ï¸þ¤±¤Î¥é¥¤¥Ö¥é¥ê¤Ç¤¹¡£
- ¡¦¤¢¤È¡¢¤â¤í¤â¤í¤Î»ö¾ð¤Ç <unistd.h> ¤ò¥¤¥ó¥¯¥ë¡¼¥É¤·¤¿¤¯¤Ê¤¤¾ì¹ç¤È¤«¤Ë¤â¡£
- ¡¦¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤ò»È¤ï¤Ê¤¤¡¢¼ºÇÔ»þ¤ÏÎã³°¤òÅꤲ¤Æ¤¯¤ì¤ë¡¢¤È¤¤¤¦¤Î¤â¥á¥ê¥Ã¥È¤Ç¤¹¡£
- ¡¦¾åµ¤Î¤è¤¦¤ÊÍýͳ¤¬Ìµ¤¤¤Ê¤é¡¢ÁÇľ¤Ë getopt ¤ò»È¤Ã¤¿¤Û¤¦¤¬¤è¤¤¤È»×¤¤¤Þ¤¹¡£
- ¡¦ÂåÂؼêÃʤȤ·¤Æ¤Ï boost ¤Î progtam_options ¤Ã¤Æ¤Î¤â¤¢¤ë¤±¤É¡¢¥ê¥ó¥¯¤·¤Ê¤¤ã¤¤¤±¤Ê¤¤¤Î¤¬ÌÌÅÝ¡£
- ¡¦¤¢¤È¡¢¤¤¤í¤¤¤í¥ª¡¼¥Ð¡¼¥¹¥Ú¥Ã¥¯²á¤®¤ëµ¤¤¬¤·¤Æµ¤·Ú¤Ë¤Ï»È¤¤¤Ë¤¯¤¤¤Ç¤¹¡£¸Ä¿ÍŪ¤Ë¡£
- ¡¦¤Þ¡¼Â礷¤¿½èÍý¤ò¤·¤Ê¤¤¤Ê¤é¡¢¤³¤ì¤ò»È¤Ã¤È¤±¡£¥Ø¥Ã¥À¤Î¥¤¥ó¥¯¥ë¡¼¥É¤Î¤ß¤ÇºÑ¤à¤·¤Í¡£
- ¡¦¥Æ¥ó¥×¥ì¡¼¥È¡© ¤Ê¤Ë¤½¤ìÈþÌ£¤·¤¤¤Î¡©
+ 補足:
+ ・主に <unistd.h> がインクルードできない処理系向けのライブラリです。
+ ・あと、もろもろの事情で <unistd.h> をインクルードしたくない場合とかにも。
+ ・グローバル変数を使わない、失敗時は例外を投げてくれる、というのもメリットです。
+ ・上記のような理由が無いなら、素直に getopt を使ったほうがよいと思います。
+ ・代替手段としては boost の progtam_options ってのもあるけど、リンクしなきゃいけないのが面倒。
+ ・あと、いろいろオーバースペック過ぎる気がして気軽には使いにくいです。個人的に。
+ ・まー大した処理をしないなら、これを使っとけ。ヘッダのインクルードのみで済むしね。
+ ・テンプレート? なにそれ美味しいの?
*/
namespace gintenlib
{
- // ¥ª¥×¥·¥ç¥ó²òÀϵ¡
+ // オプション解析機
struct options
{
- // optstr ¤Ç¼¨¤µ¤ì¤ë¥Õ¥©¡¼¥Þ¥Ã¥È¤Î¥ª¥×¥·¥ç¥ó¤ò²òÀϤ¹¤ë
+ // optstr で示されるフォーマットのオプションを解析する
explicit options( const std::string& optstr, int argc_, char* argv_[] )
: argc(argc_), argv(argv_), index(1), index_max(argc), next_char(0), opt('?'),
posixly_correct(false), throws_on_error(true)
if( ch == ':' )
{
- // ¥³¥í¥óµ¹æ¤ÏľÁ°¤Ë²òÀϤ·¤¿Ê¸»ú¤Ë¤è¤Ã¤ÆÆ°ºî¤òÀÚ¤êÂؤ¨¤ë
+ // コロン記号は直前に解析した文字によって動作を切り替える
if( prev == 0 )
{
- // ʸƬ¤Î¥³¥í¥ó¤Ï¡ÖÎã³°¤òÅꤲ¤Ê¤¤¡×»ØÄê¤È¤¤¤¦¤³¤È¤Ë¤¹¤ë
+ // 文頭のコロンは「例外を投げない」指定ということにする
throws_on_error = false;
}
else
{
- // ľÁ°¤Îʸ»ú¤ò¸¡º÷¤¹¤ë
+ // 直前の文字を検索する
map_type::iterator pos = m.find( prev );
- // ¸«¤Ä¤«¤é¤Ê¤¤¤³¤È¤ÏͤêÆÀ¤Ê¤¤
+ // 見つからないことは有り得ない
assert( pos != m.end() );
tribool& has_arg = (*pos).second;
if( !has_arg )
{
- // °ì²óÌܤΠ: ¤Î»þ¤Ï¡¢°ú¿ôɬ¿Ü
+ // 一回目の : の時は、引数必須
has_arg = true;
}
else
{
- // Æó²óÌܰʹߤϡ¢°ú¿ôǤ°Õ
+ // 二回目以降は、引数任意
has_arg = indeterminate;
}
}
{
if( prev != 0 )
{
- // + »ØÄê¤ÏËÁƬ¤Ë¤Î¤ßÃÖ¤±¤ë
+ // + 指定は冒頭にのみ置ける
throw invalid_option_string( optstr );
}
- // ¤³¤Î»ØÄ꤬¤¢¤Ã¤¿¾ì¹ç¡¢°ú¿ô¤Î½çÈÖ¤ÏÆþ¤ìÂؤ¨¤Ê¤¤
+ // この指定があった場合、引数の順番は入れ替えない
posixly_correct = true;
}
else if( ch == '-' )
{
- // - µ¹æ¤ÏGNU³ÈÄ¥¤Ë¸ºß¤¹¤ë¤¬¡¢¤è¤¯Ê¬¤«¤é¤Ê¤¤¤Î¤Ç¾ï¤ËÉÔÀµ¤È¤¤¤¦¤³¤È¤Ë¤¹¤ë¡ÊÍ×½¤Àµ¡Ë
+ // - 記号はGNU拡張に存在するが、よく分からないので常に不正ということにする(要修正)
throw invalid_option_string( optstr );
}
else if( ch == '?' )
{
- // ? µ¹æ¤Ï¥ª¥×¥·¥ç¥óʸ»ú¤È¤·¤Æ¤Ï»È¤¨¤Ê¤¤¤Î¤ÇÉÔÀµ
+ // ? 記号はオプション文字としては使えないので不正
throw invalid_option_string( optstr );
}
else
{
- // ¾°ìÈÌ
- // ':' '+' '-' '\0' °Ê³°¤Ê¤é¤É¤ó¤Êʸ»ú¤Ç¤â¤¤¤¤
+ // 他一般
+ // ':' '+' '-' '\0' 以外ならどんな文字でもいい
if( m.count( ch ) != 0 )
{
- // Ʊ¤¸¥ª¥×¥·¥ç¥óʸ»ú¤òÆó²óÄêµÁ¤·¤Á¤ã¥À¥á
+ // 同じオプション文字を二回定義しちゃダメ
throw invalid_option_string( optstr );
}
- // ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï°ú¿ô¤Ê¤·
+ // デフォルトでは引数なし
m[ch] = false;
- // : »ØÄꤵ¤ì¤¿¤È¤¤Î¤¿¤á¤Ë¡¢Ê¸»ú¤òÊݸ¤¹¤ë
+ // : 指定されたときのために、文字を保存する
prev = ch;
}
} // for
} // constructor
- // ¼ÂºÝ¤Î²òÀϤϤ³¤Á¤é¤Ç
+ // 実際の解析はこちらで
typedef int result_type;
result_type operator()()
{
using namespace std; // for assert
- // ¤Þ¤º¥¤¥ó¥Ç¥Ã¥¯¥¹¤Î¥Á¥§¥Ã¥¯
+ // ã\81¾ã\81\9aã\82¤ã\83³ã\83\87ã\83\83ã\82¯ã\82¹ã\81®ã\83\81ã\82§ã\83\83ã\82¯
if( index_max <= index ){ return -1; }
- // °ú¿ôʸ»úÎó¤Î½é´ü²½
+ // 引数文字列の初期化
arg = string();
- // ¼¡¤Ë½èÍý¤¹¤ëʸ»ú¤¬»ØÄꤵ¤ì¤Æ̵¤¤¾ì¹ç¡ÊÉáÄ̤Ϥ½¤¦¡Ë¤Ï
- // argv[index] ¤Ë¿Ê¤à
+ // 次に処理する文字が指定されて無い場合(普通はそう)は
+ // argv[index] に進む
if( !next_char )
{
next_char = argv[index];
assert( next_char != 0 );
- // ¥ª¥×¥·¥ç¥óʸ»úÎó¤À¤«¤é¡¢'-' ¤Ç¤Ï¤¸¤Þ¤ë¤Ï¤º
+ // オプション文字列だから、'-' ではじまるはず
char ch = *next_char;
if( ch == '-' )
{
- // OK¡£¤½¤Î¼¡¤Ë¶½Ì£¤¬¤¢¤ë
+ // OK。その次に興味がある
++next_char;
}
else
{
- // ¥ª¥×¥·¥ç¥óʸ»úÎó¤Ç¤Ï¤Ê¤«¤Ã¤¿
+ // オプション文字列ではなかった
- // ¤È¤ê¤¢¤¨¤º¥Ý¥¤¥ó¥¿¤Ï¥ê¥»¥Ã¥È
+ // とりあえずポインタはリセット
next_char = 0;
if( posixly_correct )
{
- // POSIX Ū¤Ë¤Ï¡¢°ì²ó¼ºÇÔ¤¹¤ë¤È¤½¤ì¤Ç½ª¤ï¤ê
+ // POSIX 的には、一回失敗するとそれで終わり
return -1;
}
else
{
- // GNU ³ÈÄ¥¤À¤È¡¢°ú¿ô¤Î½ç½ø¤òÆþ¤ìÂؤ¨¤Æ¥Þ¥Ã¥Á¥ó¥°¤ò³¤±¤ë
+ // GNU 拡張だと、引数の順序を入れ替えてマッチングを続ける
for( int i = index + 1; i < index_max; ++i )
{
char* p = argv[i];
}
}
- // ¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿
- // ʤӽç¤òÉü¸µ¤¹¤ë
+ // 見つからなかった
+ // 並び順を復元する
rotate( &argv[index], &argv[index_max], &argv[argc] );
index_max = index;
}
}
- // ¤³¤Î»þÅÀ¤Ç¡¢next_char ¤Ï¥ª¥×¥·¥ç¥óʸ»ú¤ò»Ø¤·¤Æ¤¤¤ëȦ
+ // この時点で、next_char はオプション文字を指している筈
char ch = *next_char;
if( ch == 0 )
{
- // - ¤Î¤ß¤Î°ú¿ô¤¬ÅϤµ¤ì¤¿
- // ¤³¤ì¤ÏÈ󥪥ץ·¥ç¥óʸ»úÎó¤È¤·¤Æ°·¤¦
+ // - のみの引数が渡された
+ // これは非オプション文字列として扱う
next_char = 0;
return -1;
}
else if( ch == '-' )
{
- // '--' ¤ÏŤ¤¥ª¥×¥·¥ç¥ó¤«¡¢¥ª¥×¥·¥ç¥ó¤Î½ªÎ»¤òɽ¤¹
+ // '--' は長いオプションか、オプションの終了を表す
++next_char;
if( *next_char != 0 )
{
- // Ť¤¥ª¥×¥·¥ç¥ó¤Ë¤ÏÈóÂбþ
+ // 長いオプションには非対応
throw unknown_option( "--" + to_str(next_char) );
}
- // Ť¤¥ª¥×¥·¥ç¥ó¤Ç¤Ï¤Ê¤¤¤Î¤Ç¥ª¥×¥·¥ç¥ó¤Î½ªÎ»¤òɽ¤¹
- // ½ªÎ»½èÍý¤ò¤·¤Æ
+ // 長いオプションではないのでオプションの終了を表す
+ // 終了処理をして
terminate_analysis_();
- // ¤ª¤·¤Þ¤¤
+ // おしまい
return -1;
}
- // ch ¤ò¥Þ¥Ã¥×¤«¤é¸¡º÷¤¹¤ë
+ // ch をマップから検索する
map_type::const_iterator ite = m.find( ch );
if( ite == m.end() )
{
- // ¸ºß¤·¤Ê¤¤¤è¤¦¤Ê¤é¡¢¤½¤Î¥ª¥×¥·¥ç¥ó¤ò optopt ¤Ë³ÊǼ¤·
+ // 存在しないようなら、そのオプションを optopt に格納し
opt = ch;
- // °ì±þ¡¢Ê¸»ú¤ò¼¡¤Ë¿Ê¤á¤Æ
+ // 一応、文字を次に進めて
advance_next_char_();
- // Îã³°¤òÅꤲ¤ë
+ // 例外を投げる
if( throws_on_error )
{
throw unknown_option( "-" + to_str( cast<char>(ch) ) );
}
- // Åꤲ¤Ê¤¤¾ì¹ç¤Ï '?' ¤òÊÖ¤¹
+ // 投げない場合は '?' を返す
return '?';
}
- // °ú¿ô¤Ï¤¢¤ë¡©
+ // 引数はある?
tribool has_arg = (*ite).second;
if( !has_arg )
{
- // °ú¿ô¤Î¤Ê¤¤¾ì¹ç
- // ¤È¤ê¤¢¤¨¤º¼¡¤Îʸ»ú¤Ë¿Ê¤á¤ë
+ // 引数のない場合
+ // とりあえず次の文字に進める
advance_next_char_();
- // ¤½¤Îʸ»ú¤òÊÖ¤¹
+ // その文字を返す
return ch;
}
- // ¤³¤Î»þÅÀ¤Ç¡¢°ú¿ô¤Ï¡Ö¤¢¤ë¡×¤«¡ÖǤ°Õ¡×¤«¤Î¤É¤Á¤é¤«
+ // この時点で、引数は「ある」か「任意」かのどちらか
++next_char;
if( *next_char != 0 )
{
- // ³¤¤¬¤¢¤ë¤Ê¤é¡¢¤½¤¤¤Ä¤¬°ú¿ôʸ»úÎó
+ // 続きがあるなら、そいつが引数文字列
arg = string( next_char );
advance_index_();
return ch;
}
- // °ú¿ôɬ¿Ü¤«Èݤ«
+ // 引数必須か否か
if( has_arg )
{
- // ɬ¿Ü¤Ê¤é¡¢¼¡¤Î argv ¤ò°ú¿ô¤È¤ß¤Ê¤¹
+ // 必須なら、次の argv を引数とみなす
advance_index_();
if( index_max <= index )
return missing_argument_found_( ch );
}
- // ¼¡¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ï¡¢¤Þ¤ë¤Þ¤ë°ú¿ô¤È¸«¤Ê¤¹
+ // 次のインデックスは、まるまる引数と見なす
arg = argv[index];
- // ¤¿¤À¤· argv[index] ¤¬ "--" ¤Î¤È¤¤ÏÎã³°
+ // ただし argv[index] が "--" のときは例外
if( arg == "--" )
{
arg = string();
return missing_argument_found_( ch );
}
- // ¤µ¤é¤Ë²òÀϹԤò¿Ê¤á¤ë
+ // さらに解析行を進める
advance_index_();
return ch;
}
else
{
- // °ú¿ô¤¬¾Êά²Äǽ¤Ç¡¢¥ª¥×¥·¥ç¥óʸ»ú¤ÈƱ»þ¤Ë°ú¿ô¤¬ÅϤµ¤ì¤Æ¤¤¤Ê¤¤¤Ê¤é
- // °ú¿ô¤ò¶õʸ»úÎó¤Ë¤·¤Æ ch ¤òÊÖ¤¹
+ // 引数が省略可能で、オプション文字と同時に引数が渡されていないなら
+ // 引数を空文字列にして ch を返す
advance_index_();
return ch;
}
return '?';
}
- // ¼¡¤Ë½èÍý¤¹¤ë°ú¿ô¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹
+ // 次ã\81«å\87¦ç\90\86ã\81\99ã\82\8bå¼\95æ\95°ã\81®ã\82¤ã\83³ã\83\87ã\83\83ã\82¯ã\82¹
int optind() const { return index; }
- // ¼¡¤Ë½èÍý¤¹¤ë°ú¿ô¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤òÀßÄꤹ¤ë
+ // 次に処理する引数のインデックスを設定する
void set_optind( int new_index = 1 )
{
if( new_index < 1 ){ new_index = 1; }
arg = std::string(); opt = '?';
}
- // °ú¿ô
+ // 引数
const std::string& optarg() const { return arg; }
- // ¥¨¥é¡¼»þ¤ËÆɤó¤Ç¤¤¤¿Ê¸»ú
+ // エラー時に読んでいた文字
int optopt() const { return opt; }
private:
int opt;
bool posixly_correct, throws_on_error;
- // ÆâÉô´Ø¿ô
- // ²òÀϤ¹¤ë¹Ô¤ò°ì¤Ä¿Ê¤á¤ë
+ // 内部関数
+ // 解析する行を一つ進める
void advance_index_()
{
++index;
next_char = 0;
}
- // ʸ»ú¤ò°ìʸ»ú¿Ê¤á¤ë
+ // 文字を一文字進める
void advance_next_char_()
{
- // ¤È¤ê¤¢¤¨¤º¼¡¤Îʸ»ú¤Ë¿Ê¤á¤ë
+ // とりあえず次の文字に進める
++next_char;
if( *next_char == 0 )
{
- // ¼¡¤Îʸ»ú¤¬Â¸ºß¤·¤Ê¤¤¤Ê¤é¡¢²òÀϤΥ¤¥ó¥Ç¥Ã¥¯¥¹¤ò¿Ê¤á¤ë
+ // 次の文字が存在しないなら、解析のインデックスを進める
++index;
next_char = 0;
}
}
- // °ú¿ô¤¬Â¤ê¤Ê¤¤
+ // 引数が足りない
int missing_argument_found_( int ch )
{
- // °ú¿ôÉÔÂ
+ // 引数不足
opt = ch;
- // Îã³°¤òÅꤲ¤ë
+ // 例外を投げる
if( throws_on_error )
{
throw option_requires_argument( "-" + to_str( cast<char>(ch) ) );
return ':';
}
- // '--' ¤ËÁø¶ø¤·¤¿
+ // '--' に遭遇した
void terminate_analysis_()
{
- // ¥¤¥ó¥Ç¥Ã¥¯¥¹¤ò¿Ê¤á¤Æ
+ // インデックスを進めて
advance_index_();
- // ʤÓÂؤ¨¤ÎÅÓÃæ¤Ê¤éʤӽç¤òÉü¸µ¤¹¤ë
+ // 並び替えの途中なら並び順を復元する
if( argc != index_max )
{
std::rotate( &argv[index], &argv[index_max], &argv[argc] );
}
- // ¤³¤ì°Ê¾å¤Ï²òÀϤ·¤Ê¤¤¤è
+ // これ以上は解析しないよ
index_max = index - 1;
}
<gintenlib/plane/angle.hpp>
- angle ¡§ Ê¿Ì̳Ñ
+ angle : 平面角
- µ¡Ç½¡§
- Ê¿Ì̳Ѥò°·¤¦¥¯¥é¥¹¡£
- £Ã¡Ü¡Ü¤Ë¤ª¤¤¤Æ³ÑÅÙ¤Ï radian ¤Ç°·¤¤¤Þ¤¹¤¬¡¢¤¿¤Þ¤Ë degree ¤â»È¤¤¤¿¤¯¤Ê¤ë¤Ç¤·¤ç¤¦¡£
- ¤½¤¦¤¤¤¦¤È¤¤Ë¡¢Æó¤Ä¤Îɽ¤·Êý¤òº®Æ±¤·¤Ê¤¤¤è¤¦¤Ë°·¤¨¤ë¥¯¥é¥¹¤Ç¤¹¡£
- ¤¢¡¢¤½¤ì¤«¤é³ÑÅÙ¤ÎÀµµ¬²½¡Ê-¦Ð¤«¤é¦Ð¤Î´Ö¤Ë¤Ê¤ë¤è¤¦Ä´À᤹¤ë¡Ë¤â¤Ç¤¤Þ¤¹¡£¤Ä¤¤¤Ç¤Ë¡£
+ 機能:
+ 平面角を扱うクラス。
+ C++において角度は radian で扱いますが、たまに degree も使いたくなるでしょう。
+ そういうときに、二つの表し方を混同しないように扱えるクラスです。
+ あ、それから角度の正規化(-πからπの間になるよう調節する)もできます。ついでに。
- ¼ç¤ËÃÆËë¤òºî¤ë¤È¤¤Ë»È¤¦ÄøÅ٤Υ¯¥é¥¹¤Ç¤¹¡£
+ 主に弾幕を作るときに使う程度のクラスです。
- »ÈÍÑÎ㡧
- angle x, y = degree(60); // x ¤Ï 0, y ¤Ï 60¡ë
- // »°³Ñ´Ø¿ô
+ 使用例:
+ angle x, y = degree(60); // x は 0, y は 60°
+ // 三角関数
cout << sin(x) << ", " << sin(y) << endl;
- // µÕ»°³Ñ´Ø¿ô
+ // 逆三角関数
angle z = angle::asin(0.5);
- // ¿ôÃͤËÊÑ´¹
- cout << "z ¤Ï " << to_rad(z) << " ¥é¥¸¥¢¥ó¡¢ " << to_deg(z) << " Å٤Ǥ¹¡£";
+ // 数値に変換
+ cout << "z は " << to_rad(z) << " ラジアン、 " << to_deg(z) << " 度です。";
*/
{
namespace plane
{
- // angle : Ê¿Ì̳Ñ
+ // angle : 平面角
template<typename Real>
struct basic_angle
: private boost::totally_ordered< basic_angle<Real> >,
basic_angle( const basic_angle<T>& src )
: theta( src.theta ) {}
- // ¼Â¿ôÃͤ«¤éÀ¸À®¡¢Ã±°Ì¤Ï rad
+ // 実数値から生成、単位は rad
explicit basic_angle( real_type theta_ )
: theta(theta_) {}
- // theta ¤ÎÃͤòÆÀ¤ë
+ // theta の値を得る
real_type to_deg() const
{
return theta * 180 / M_PI;
}
// operator overloads
- // Èæ³Ó
+ // 比較
friend bool operator==( const basic_angle& lhs, const basic_angle& rhs )
{
return lhs.theta == rhs.theta;
{
return lhs.theta < rhs.theta;
}
- // ²Ã¸º»»
+ // 加減算
basic_angle& operator+=( const basic_angle& rhs )
{
theta += rhs.theta;
theta -= rhs.theta;
return *this;
}
- // Éä¹æȿž
+ // 符号反転
basic_angle operator-() const
{
return basic_angle( -theta );
}
- // ³Ý¤±»»¡¢³ä¤ê»»
+ // 掛け算、割り算
basic_angle& operator*=( const real_type& rhs )
{
theta *= rhs;
theta /= rhs;
return *this;
}
- // Èæ¤Î»»½Ð
+ // 比の算出
real_type operator/( const basic_angle& rhs ) const
{
return theta / rhs.theta;
}
- // ¾ê;±é»»
- // std::fmod ¤ò¸Æ¤Ó½Ð¤¹¤À¤±
+ // 剰余演算
+ // std::fmod を呼び出すだけ
basic_angle& operator%=( const basic_angle& rhs )
{
using std::fmod;
return *this;
}
- // ¥Ù¥¯¥È¥ë¤ËÂФ·¤Æ³Ý¤±»»¤¹¤ë¤È²óžÁàºî
- // ¤¿¤À¤·¡¢º¸¤«¤é³Ý¤±¤¿»þ¤Î¤ß
+ // ベクトルに対して掛け算すると回転操作
+ // ただし、左から掛けた時のみ
basic_vector<Real> operator*( const basic_vector<Real>& target ) const
{
return rotate( target, *this );
}
- // [ -¦Ð, ¦Ð ] ¤ÎÈϰϤËÊäÀµ
+ // [ -π, π ] の範囲に補正
basic_angle& normalize()
{
using std::fmod;
if( theta > M_PI )
{
- // ¦Ð¤À¤±¤º¤é¤·¤Æ¸µ¤ËÌ᤹
+ // πだけずらして元に戻す
theta = fmod( theta + M_PI, M_PI * 2 ) - M_PI;
}
else if( theta < -M_PI )
{
- // ¤Á¤ç¤Ã¤È¤ä¤ä¤³¤·¤¤¤±¤Éʬ¤«¤ë¤Ï¤º¡Ê¤¿¤Ö¤ó¡Ë
+ // ちょっとややこしいけど分かるはず(たぶん)
theta = -fmod( -theta + M_PI, M_PI * 2 ) + M_PI;
}
- // °ì±þ³Î¤«¤á¤Æ¤ª¤¯¤è¡©
+ // 一応確かめておくよ?
assert( -M_PI <= theta && theta <= M_PI );
return *this;
basic_angle temp = target;
return temp.normalize();
}
- // [ 0, 2¦Ð ) ¤ÎÈϰϤËÊäÀµ
+ // [ 0, 2π ) の範囲に補正
basic_angle& unique()
{
using std::fmod;
theta = M_PI * 2 - fmod( -theta, M_PI * 2 );
}
- // °ì±þ³Î¤«¤á¤Æ¤ª¤¯¤è¡©
+ // 一応確かめておくよ?
assert( 0 <= theta && theta < M_PI * 2 );
return *this;
return temp.unique();
}
- // »°³Ñ´Ø¿ô
+ // 三角関数
#define GINTENLIB_PLANE_ANGLE_GEN_FUNCTION( func ) \
real_type func() const \
{ \
return x.func(); \
}
- // ¼ÂºÝ¤ËÀ¸À®
+ // 実際に生成
GINTENLIB_PLANE_ANGLE_GEN_FUNCTION( sin )
GINTENLIB_PLANE_ANGLE_GEN_FUNCTION( cos )
GINTENLIB_PLANE_ANGLE_GEN_FUNCTION( tan )
#undef GINTENLIB_PLANE_ANGLE_GEN_FUNCTION
- // µÕ»°³Ñ´Ø¿ô
+ // 逆三角関数
static basic_angle asin( real_type x )
{
using std::asin;
};
typedef basic_angle<double> angle;
- // ¥é¥¸¥¢¥ó <--> ÅÙ ´¹»»
+ // ラジアン <--> 度 換算
template<typename Real>
Real degree( const basic_angle<Real>& x )
{
{
return basic_angle<Real>( rad );
}
- // û½Ì̾
+ // 短縮名
template<typename Real>
basic_angle<Real> deg( Real deg_ )
{
<gintenlib/plane/fwd.hpp>
- ¤¤¤í¤¤¤í¤ÈÀè¹ÔÀë¸À¤¹¤ë¥Ø¥Ã¥À¤Ç¤¹¡£
+ いろいろと先行宣言するヘッダです。
*/
<gintenlib/plane/point.hpp>
- point ¡§ Æ󼡸µ°ÌÃÖ¥Ù¥¯¥È¥ë
+ point : 二次元位置ベクトル
- µ¡Ç½¡§
- Æ󼡸µ¤Î°ÌÃÖ¥Ù¥¯¥È¥ë¤òɽ¤¹¥¯¥é¥¹¡£
- °ÌÃÖ¥Ù¥¯¥È¥ë¤Ê¤Î¤Ç²Ã»»¤Ç¤¤Þ¤»¤ó¡£¼Â¿ôÇܤâ½ÐÍè¤Þ¤»¤ó¡£
- ¤Ç¤âÁêÂÐ¥Ù¥¯¥È¥ë¡Êvector¡Ë¤ò²Ã»»¤·¤¿¤ê¤¹¤ë¤³¤È¤Ï½ÐÍè¤Þ¤¹¡£
- ¤Á¤Ê¤ß¤Ëº¹¤ò¼è¤ë¤³¤È¤Ï²Äǽ¤Ç¡¢¤½¤¦¤¹¤ë¤ÈÁêÂÐ¥Ù¥¯¥È¥ë¤ËÊѲ½¤·¤Þ¤¹¡£
- °ÌÃÖ¥Ù¥¯¥È¥ë¤ÈÁêÂÐ¥Ù¥¯¥È¥ë¤òº®Æ±¤¹¤ë¤È¥Ð¥°¤Î¸µ¤Ë¤Ê¤ë¤Î¤Ç¡¢¤½¤ì¤òËɤ°¤¿¤á¤À¤±¤Î¥¯¥é¥¹¡£
+ 機能:
+ 二次元の位置ベクトルを表すクラス。
+ 位置ベクトルなので加算できません。実数倍も出来ません。
+ でも相対ベクトル(vector)を加算したりすることは出来ます。
+ ちなみに差を取ることは可能で、そうすると相対ベクトルに変化します。
+ 位置ベクトルと相対ベクトルを混同するとバグの元になるので、それを防ぐためだけのクラス。
*/
{
namespace plane
{
- // point : °ÌÃÖ¥Ù¥¯¥È¥ë
+ // point : 位置ベクトル
template<typename Real>
struct basic_point : private boost::additive< basic_point<Real>, basic_vector<Real> >
, private boost::equality_comparable< basic_point<Real> >
x -= rhs.x; y -= rhs.y;
return *this;
}
- // ¸å¡¢°ÌÃÖ¥Ù¥¯¥È¥ëƱ»Î¤Îº¹Ê¬
+ // 後、位置ベクトル同士の差分
basic_vector<Real> operator-( const basic_point& rhs ) const
{
return basic_vector<Real>( x - rhs.x, y - rhs.y );
}
- // ÅùÃÍÈæ³Ó
+ // 等値比較
bool operator==( const basic_point& rhs ) const
{
return ( x == rhs.x ) && ( y == rhs.y );
}
- // vector ¤ËÊÑ´¹
+ // vector に変換
basic_vector<Real> to_vector() const
{
return basic_vector<Real>( x, y );
};
typedef basic_point<double> point;
- // ÃæÅÀ¤òµá¤á¤ë
+ // 中点を求める
template<typename T>
basic_point<T> midpoint( const basic_point<T>& p1, const basic_point<T>& p2 )
{
<gintenlib/plane/quadrangle.hpp>
- quadrangle ¡§ Æ󼡸µ¶õ´Ö¾å¤Î»Í³Ñ·Á
+ quadrangle : 二次元空間上の四角形
- Àë¸À¡§
- // quadrangle : »Í³Ñ·Á
+ 宣言:
+ // quadrangle : 四角形
template<typename Real>
struct basic_quadrangle
{
typedef basic_point<Real> pos_type;
typedef basic_vector<Real> vec_type;
- // Ãæ¿´ºÂɸ
+ // 中心座標
pos_type pos;
- // ³ÆĺÅÀ¤ÎÃæ¿´ºÂɸ¤«¤é¤Î°ÌÃÖ¥Ù¥¯¥È¥ë
+ // 各頂点の中心座標からの位置ベクトル
vec_type a1, a2, a3, a4;
basic_quadrangle();
- // ¸¶ÅÀ¤òÃæ¿´¤È¤·¤¿»Í³Ñ·Á¤òÀ½ºî¤¹¤ë
+ // 原点を中心とした四角形を製作する
basic_quadrangle( const vec_type& a1_, const vec_type& a2_,
const vec_type& a3_, const vec_type& a4_ );
- // °ÌÃÖ¥Ù¥¯¥È¥ë£´¤Ä¤«¤é»Í³Ñ·Á¤òÀ½ºî¤¹¤ë¡£
- // Ãæ¿´¤Ï£´ÅÀ¤ÎÊ¿¶Ñ¡¢¤¹¤Ê¤ï¤Á½Å¿´
+ // 位置ベクトル4つから四角形を製作する。
+ // 中心は4点の平均、すなわち重心
basic_quadrangle( const pos_type& a1_, const pos_type& a2_,
const pos_type& a3_, const pos_type& a4_ );
- // Á´Í×ÁǤò»ØÄꤷ¤Æ¹½ÃÛ
+ // 全要素を指定して構築
basic_quadrangle( const pos_type& pos_, const vec_type& a1_, const vec_type& a2_,
const vec_type& a3_, const vec_type& a4_ );
- // Á´Í×ÁǤò°ÌÃÖ¥Ù¥¯¥È¥ë¤Ç»ØÄꤷ¤Æ¹½ÃÛ
+ // 全要素を位置ベクトルで指定して構築
basic_quadrangle( const pos_type& pos_, const pos_type& a1_, const pos_type& a2_,
const pos_type& a3_, const pos_type& a4_ );
basic_quadrangle( const basic_quadrangle<T>& src );
- // ³ÆĺÅÀ¤Î°ÌÃÖ¥Ù¥¯¥È¥ë¤ò»»½Ð
+ // 各頂点の位置ベクトルを算出
pos_type vertex1() const { return pos + a1; }
pos_type vertex2() const { return pos + a2; }
pos_type vertex3() const { return pos + a3; }
pos_type vertex4() const { return pos + a4; }
// operator[]
- // ¥¤¥ó¥Æ¥Ã¥¯¥¹¤ËÂбþ¤¹¤ëĺÅÀºÂɸ¤ò»»½Ð
+ // インテックスに対応する頂点座標を算出
pos_type operator[]( std::size_t index ) const;
pos_type at( std::size_t index ) const;
static std::size_t size()
return 4;
}
- // °ÌÃ֤Υ·¥Õ¥È
- // ¥á¥ó¥ÐÈǤϼ«¿È¤òÊѹ¹¡¢ friend ÈǤϷë²Ì¤ò½ÐÎÏ¡£
+ // 位置のシフト
+ // メンバ版は自身を変更、 friend 版は結果を出力。
basic_quadrangle& shift( const vec_type& d );
friend basic_quadrangle shift( const basic_quadrangle& target, const vec_type& d );
- // ĺÅÀ¤Î°ÌÃÖ¤òÊѤ¨¤º¡¢Ãæ¿´¤òÊѹ¹
- // friend ÈǤϤ¢¤ê¤Þ¤»¤ó¡£
+ // 頂点の位置を変えず、中心を変更
+ // friend 版はありません。
basic_quadrangle& move_center( const pos_type& center );
basic_quadrangle& move_center( const vec_type& d );
- // °ú¿ô¤Ê¤·¤À¤È½Å¿´¤Ë»ý¤Ã¤Æ¤¤¤¯
+ // 引数なしだと重心に持っていく
basic_quadrangle& move_center();
- // ²óž
- // rect, vector ¤È¤«¤È¤Þ¤Ã¤¿¤¯Æ±¤¸¡£
- // Ãæ¿´ºÂɸ¤ò¤ï¤¶¤ï¤¶¸ÄÊ̤ËÀßÄꤷ¤Æ¤¤¤ë¤Î¤Ï¡¢¤³¤Î¤È¤¤Î²óž¼´¤ò·è¤á¤ë¤¿¤á¡£
+ // 回転
+ // rect, vector とかとまったく同じ。
+ // 中心座標をわざわざ個別に設定しているのは、このときの回転軸を決めるため。
template<typename Angle>
basic_quadrangle& rotate( const Angle& theta );
basic_quadrangle& rotate( real_type s, real_type c );
};
typedef basic_quadrangle<double> quadrangle;
- µ¡Ç½¡§
- Æ󼡸µ¶õ´Ö¾å¤Î¡¢ÄºÅÀ¤Î°ÌÃÖ¤ÈÃæ¿´¤Î³ÎÄꤷ¤¿¤ò»Í³Ñ·Á¤òɽ¤¹¥¯¥é¥¹¡£
- Ê¿¹Ô°ÜÆ°¡¢²óž¤Ê¤É¤¬¹Ô¤¨¤Þ¤¹¡£¤Ä¡¼¤«Ì¾Á°Ä¹¤¤¤è¡£
+ 機能:
+ 二次元空間上の、頂点の位置と中心の確定したを四角形を表すクラス。
+ 平行移動、回転などが行えます。つーか名前長いよ。
*/
namespace plane
{
- // quadrangle : »Í³Ñ·Á
+ // quadrangle : 四角形
template<typename Real>
struct basic_quadrangle
{
typedef basic_point<Real> pos_type;
typedef basic_vector<Real> vec_type;
- // Ãæ¿´ºÂɸ
+ // 中心座標
pos_type pos;
- // ³ÆĺÅÀ¤ÎÃæ¿´ºÂɸ¤«¤é¤Î°ÌÃÖ¥Ù¥¯¥È¥ë
+ // 各頂点の中心座標からの位置ベクトル
vec_type a1, a2, a3, a4;
basic_quadrangle()
: pos(), a1(), a2(), a3(), a4() {}
- // ¸¶ÅÀ¤òÃæ¿´¤È¤·¤¿»Í³Ñ·Á¤òÀ½ºî¤¹¤ë
+ // 原点を中心とした四角形を製作する
basic_quadrangle( const vec_type& a1_, const vec_type& a2_,
const vec_type& a3_, const vec_type& a4_ )
: pos(), a1(a1_), a2(a2_), a3(a3_), a4(a4_) {}
- // °ÌÃÖ¥Ù¥¯¥È¥ë£´¤Ä¤«¤é»Í³Ñ·Á¤òÀ½ºî¤¹¤ë¡£
- // Ãæ¿´¤Ï£´ÅÀ¤ÎÊ¿¶Ñ¡¢¤¹¤Ê¤ï¤Á½Å¿´
+ // 位置ベクトル4つから四角形を製作する。
+ // 中心は4点の平均、すなわち重心
basic_quadrangle( const pos_type& a1_, const pos_type& a2_,
const pos_type& a3_, const pos_type& a4_ )
{
a4 = a4_ - pos;
}
- // Á´Í×ÁǤò»ØÄꤷ¤Æ¹½ÃÛ
+ // 全要素を指定して構築
basic_quadrangle( const pos_type& pos_, const vec_type& a1_, const vec_type& a2_,
const vec_type& a3_, const vec_type& a4_ )
: pos(pos_), a1(a1_), a2(a2_), a3(a3_), a4(a4_) {}
- // Á´Í×ÁǤò°ÌÃÖ¥Ù¥¯¥È¥ë¤Ç»ØÄꤷ¤Æ¹½ÃÛ
+ // 全要素を位置ベクトルで指定して構築
basic_quadrangle( const pos_type& pos_, const pos_type& a1_, const pos_type& a2_,
const pos_type& a3_, const pos_type& a4_ )
: pos(pos_), a1( a1_ - pos ), a2( a2_ - pos ), a3( a3_ - pos ), a4( a4_ - pos ) {}
: pos(src.pos), a1(src.a1), a2(src.a2), a3(src.a3), a4(src.a4) {}
- // ³ÆĺÅÀ¤Î°ÌÃÖ¥Ù¥¯¥È¥ë¤ò»»½Ð
+ // 各頂点の位置ベクトルを算出
pos_type vertex1() const { return pos + a1; }
pos_type vertex2() const { return pos + a2; }
pos_type vertex3() const { return pos + a3; }
return 4;
}
- // °ÌÃ֤Υ·¥Õ¥È
+ // 位置のシフト
basic_quadrangle& shift( const vec_type& d )
{
pos += d;
return temp.shift(d);
}
- // ĺÅÀ¤Î°ÌÃÖ¤òÊѤ¨¤º¡¢Ãæ¿´¤òÊѹ¹
+ // 頂点の位置を変えず、中心を変更
basic_quadrangle& move_center( const pos_type& center )
{
vec_type d = pos - center;
return *this;
}
- // °ú¿ô¤Ê¤·¤À¤È½Å¿´¤Ë»ý¤Ã¤Æ¤¤¤¯
+ // 引数なしだと重心に持っていく
basic_quadrangle& move_center()
{
basic_quadrangle temp( vertex1(), vertex2(), vertex3(), vertex4() );
return *this;
}
- // ²óž
+ // 回転
template<typename Angle>
basic_quadrangle& rotate( const Angle& theta )
{
<gintenlib/plane/rect.hpp>
- rect ¡§ Æ󼡸µ¶õ´Ö¾å¤Î¶ë·Á
+ rect : 二次元空間上の矩形
- Àë¸À¡§
- // rect : ¶ë·Á
+ 宣言:
+ // rect : 矩形
template<typename Real>
struct basic_rect
{
basic_rect( const basic_rect<T>& src );
// operator[]
- // ĺÅÀ¤ÎºÂɸ¤òÊÖ¤·¤Þ¤¹¡£
+ // 頂点の座標を返します。
pos_type operator[]( std::size_t index ) const;
pos_type at( std::size_t index ) const;
return 4;
}
- // °ÌÃ֤Υ·¥Õ¥È
- // ¤³¤Î¶ë·Á¼«¿È¤ò¥·¥Õ¥È¤µ¤»¤Þ¤¹¡£
+ // 位置のシフト
+ // この矩形自身をシフトさせます。
basic_rect& shift( const vec_type& d );
- // friend ÈǤϥ³¥Ô¡¼¤·¤Æ¤«¤é¥·¥Õ¥È¤·¤Þ¤¹¡£
+ // friend 版はコピーしてからシフトします。
friend basic_rect shift( const basic_rect& target, const vec_type& d );
- // ²óž
- // ¤³¤Î¶ë·Á¼«¿È¤ò²óž¤µ¤»¤¿¤¤¤¬¡¢¤½¤¦¤¹¤ë¤È¶ë·Á¤Ç¤Ê¤¯¤Ê¤Ã¤Æ¤·¤Þ¤¦¤Î¤Ç¡¢
- // ¤ä¤à¤Ê¤¯»Í³Ñ·Á¤È¤·¤Æ¥³¥Ô¡¼¤·¤Æ¤«¤é²óž¤µ¤»¤Þ¤¹¡£
- // Angle ÈǤϳÑÅÙ¤«¤é¥µ¥¤¥ó¥³¥µ¥¤¥ó¤òµá¤á¤Æ²óž¡¢
- // s, c ÈǤϥµ¥¤¥ó¥³¥µ¥¤¥óÃͤ«¤éľÀܲ󞤵¤»¤Þ¤¹¡£
+ // 回転
+ // この矩形自身を回転させたいが、そうすると矩形でなくなってしまうので、
+ // やむなく四角形としてコピーしてから回転させます。
+ // Angle 版は角度からサインコサインを求めて回転、
+ // s, c 版はサインコサイン値から直接回転させます。
template<typename Angle>
basic_quadrangle<Real> rotate( const Angle& theta ) const;
basic_quadrangle<Real> rotate( real_type s, real_type c ) const;
};
typedef basic_rect<double> rect;
- µ¡Ç½¡§
- Æ󼡸µ¶õ´Ö¾å¤Î¡¢°ÌÃ֤γÎÄꤷ¤¿¶ë·Á¤òɽ¤¹¥¯¥é¥¹¡£
- ²óž¤µ¤»¤ë¤È»Í³Ñ·Á¤ËÊѲ½¤¹¤ë°Ê³°¤ÏÉáÄ̤«¤È¡£
+ 機能:
+ 二次元空間上の、位置の確定した矩形を表すクラス。
+ 回転させると四角形に変化する以外は普通かと。
*/
{
namespace plane
{
- // rect : ¶ë·Á
+ // rect : 矩形
template<typename Real>
struct basic_rect
{
return 4;
}
- // °ÌÃ֤Υ·¥Õ¥È
+ // 位置のシフト
basic_rect& shift( const vec_type& d )
{
x1 += d.x;
return temp.shift(d);
}
- // ²óž
+ // 回転
template<typename Angle>
basic_quadrangle<Real> rotate( const Angle& theta ) const
{
<gintenlib/plane/vector.hpp>
- vector ¡§ Æ󼡸µ¥Ù¥¯¥È¥ë
+ vector : 二次元ベクトル
- Àë¸À¡§
+ 宣言:
template< typename Real >
struct basic_vector
: private boost::equality_comparable< basic_vector<Real> >,
template<typename T>
basic_vector( const std::pair<T, T>& src );
- // ±é»»»Ò¿½ÅÄêµÁ
- // ¤½¤ì¤¾¤ì¸«¤¿¤Þ¤ó¤Þ¤Ç¤¹¡£operator+ ¤È¤«¤Ï boost:: operators ¤Ë¤è¤Ã¤Æ³Æ¼ï¼«Æ°ÄêµÁ¤µ¤ì¤Þ¤¹¡£
+ // 演算子多重定義
+ // それぞれ見たまんまです。operator+ とかは boost:: operators によって各種自動定義されます。
basic_vector& operator+=( const basic_vector& rhs );
basic_vector& operator-=( const basic_vector& rhs );
basic_vector operator-() const;
real_type norm() const;
friend real_type norm( const basic_vector& target );
- // ÀäÂÐÃÍ
+ // 絶対値
real_type absolute() const;
friend real_type absolute( const basic_vector& target );
- // Àµµ¬²½
- // Àµµ¬²½¤·¤¿·ë²Ì¤òÊÖ¤¹¤Î¤Ç¤Ï¤Ê¤¯¡¢¤³¤Î¥Ù¥¯¥È¥ë¼«ÂΤòÀµµ¬²½¤·¤Þ¤¹¡£
+ // 正規化
+ // 正規化した結果を返すのではなく、このベクトル自体を正規化します。
basic_vector& normalize();
- // friend ÈǤϥ³¥Ô¡¼¤·¤Æ¤«¤éÀµµ¬²½¤·¤Þ¤¹¡£
+ // friend 版はコピーしてから正規化します。
friend basic_vector normalized( const basic_vector& x );
- // ÊгÑ
+ // 偏角
real_type argument() const;
friend real_type argument( const basic_vector& x );
- // ÆâÀÑ
+ // 内積
real_type dot( const basic_vector& rhs ) const;
friend real_type dot( const basic_vector& lhs, const basic_vector& rhs );
friend real_type operator*( const basic_vector& lhs, const basic_vector& rhs );
- // ¥í¡¼¥Æ¡¼¥È¡£²óž¤µ¤»¤¿·ë²Ì¤òÊÖ¤¹¤Î¤Ç¤Ï¤Ê¤¯¡¢¤³¤Î¥Ù¥¯¥È¥ë¼«ÂΤò²ó¤·¤Þ¤¹¡£
- // ³ÑÅÙ»ØÄê¥Ð¡¼¥¸¥ç¥ó¡£¥Æ¥ó¥×¥ì¡¼¥È¤Ê¤Î¤Ï¡¢gintenlib::plane::angle ¤âÅϤ»¤ë¤è¤¦¤Ë¡¢¤Ç¤¹¡£
+ // ローテート。回転させた結果を返すのではなく、このベクトル自体を回します。
+ // 角度指定バージョン。テンプレートなのは、gintenlib::plane::angle も渡せるように、です。
template< typename Angle >
basic_vector& rotate( const Angle& angle );
- // ¥µ¥¤¥ó¤È¥³¥µ¥¤¥ó¤ò»ØÄꤷ¤¿¥Ð¡¼¥¸¥ç¥ó¡£¹â®¤Ç¤¹¡£
+ // サインとコサインを指定したバージョン。高速です。
basic_vector& rotate( real_type s, real_type c );
- // ¾åÆó¤Ä¤Î friend ÈÇ¡£¥³¥Ô¡¼¤·¤Æ¤«¤é²ó¤·¤Þ¤¹¡£
+ // 上二つの friend 版。コピーしてから回します。
template< typename Angle >
friend basic_vector rotate( const basic_vector& target, const Angle& angle );
friend basic_vector rotate( const basic_vector& target, real_type s, real_type c );
};
typedef basic_vector<double> vector;
- µ¡Ç½¡§
- Æ󼡸µ¤ÎÁêÂÐ¥Ù¥¯¥È¥ë¤òɽ¤¹¥¯¥é¥¹¡£
- ÀäÂÐÃÍ·×»»¡¢Êгѷ׻»¡¢Àµµ¬²½¡¢²óž¤Ê¤É¡¢¤È¤ê¤¢¤¨¤º°ìÄ̤êɬÍפ½¤¦¤Ê¤â¤Î¤Ï·¤¨¤Æ¤¤¤Þ¤¹¡£
+ 機能:
+ 二次元の相対ベクトルを表すクラス。
+ 絶対値計算、偏角計算、正規化、回転など、とりあえず一通り必要そうなものは揃えています。
*/
basic_vector( const std::pair<T, T>& src )
: x(src.first), y(src.second) {}
- // ±é»»»Ò¿½ÅÄêµÁ
+ // 演算子多重定義
basic_vector& operator+=( const basic_vector& rhs )
{
x += rhs.x;
return target.norm();
}
- // ÀäÂÐÃÍ
+ // 絶対値
real_type absolute() const
{
return std::sqrt( x * x + y * y );
return target.absolute();
}
- // Àµµ¬²½
+ // 正規化
basic_vector& normalize()
{
real_type r = absolute();
return temp;
}
- // ÊгÑ
+ // 偏角
real_type argument() const
{
if( x == 0 && y == 0 )
return x.argument();
}
- // ÆâÀÑ
+ // 内積
real_type dot( const basic_vector& rhs ) const
{
return x * rhs.x + y * rhs.y;
return lhs.dot(rhs);
}
- // ¥í¡¼¥Æ¡¼¥È
+ // ローテート
template< typename Angle >
basic_vector& rotate( const Angle& angle )
{
<gintenlib/pointer_facade.hpp>
- pointer_facade ¡§ ´Ê°×¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿À½ºî
+ pointer_facade : 簡易スマートポインタ製作
- Àë¸À¡§
+ 宣言:
template< class Derived, typename T, typename Category = Derived >
struct pointer_facade
{
typedef T* pointer;
typedef T& reference;
- // »²¾È³°¤·¤È¥Ý¥¤¥ó¥¿¼èÆÀ
+ // 参照外しとポインタ取得
reference operator*() const;
pointer operator->() const;
friend pointer get_pointer( const Derived& target );
- // bool Èæ³Ó
+ // bool 比較
operator unspecified_bool_type() const;
bool operator!() const;
};
- // ¥Æ¥ó¥×¥ì¡¼¥ÈÈÇÁê¸ßÈæ³Ó
- // ¥«¥Æ¥´¥ê¤¬Æ±¤¸¤â¤Î¤Ê¤éÁê¸ßÈæ³Ó£Ï£Ë
+ // テンプレート版相互比較
+ // カテゴリが同じものなら相互比較OK
template<typename T, typename U, typename D1, typename D2, typename C>
inline bool operator==
( const pointer_facade<D1, T, C>& lhs, const pointer_facade<D2, U, C>& rhs );
inline bool operator<
( const pointer_facade<D1, T, C>& lhs, const pointer_facade<D2, U, C>& rhs );
- µ¡Ç½¡§
- get() ¤µ¤¨¼ÂÁõ¤¹¤ì¤Ð¡¢¤½¤ì¤ò¸µ¤Ë¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤È¤·¤ÆɬÍפʤâ¤Î¤òÀ¸À®¤¹¤ë¥¯¥é¥¹¤Ç¤¹¡£
- ¼ÂÁõ¤·¤Æ¤¯¤ì¤ë¤â¤Î¤Ï°Ê²¼¤ÎÄ̤ꡧ
- ¡¡¡¦element_type, value_type, pointer, reference ¤Î·¿ÄêµÁ
- ¡¡¡¦operator*, operator->, get_pointer() ¤Ë¤è¤ë¥Ý¥¤¥ó¥¿¼èÆÀ
- ¡¡¡¦boolÃͤȤÎÈæ³Ó¡¢¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿Æ±»Î¤ÎÈæ³Ó
- ¡¡¡¦°Û¤Ê¤ë·¿¤ò¼¨¤¹¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿Æ±»Î¤ÎÈæ³Ó¡ÊƱ¤¸¥«¥Æ¥´¥ê¤Ë°¤¹¤ë¤â¤Î¤Î¤ß¡Ë
+ 機能:
+ get() さえ実装すれば、それを元にスマートポインタとして必要なものを生成するクラスです。
+ 実装してくれるものは以下の通り:
+ ・element_type, value_type, pointer, reference の型定義
+ ・operator*, operator->, get_pointer() によるポインタ取得
+ ・bool値との比較、スマートポインタ同士の比較
+ ・異なる型を示すスマートポインタ同士の比較(同じカテゴリに属するもののみ)
- »È¤¤Êý¤Ï bool_comparable ¤ÈƱ¤¸¡¢¡Ö¥Æ¥ó¥×¥ì¡¼¥È¤Ë¼«Ê¬¼«¿È¤Î·¿Ì¾¤òÆþ¤ì¤Æ·Ñ¾µ¡×¡£
- ÂèÆó°ú¿ô¤Ï¥Ý¥¤¥ó¥¿¤ò³ÊǼ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤Î·¿¤ò¼¨¤·¤Þ¤¹¡£
- ¾Êά²Äǽ¤ÊÂè»°°ú¿ô¤Ï¥Ý¥¤¥ó¥¿¤Î¥«¥Æ¥´¥ê¡¢Âè»°°ú¿ô¤¬Æ±¤¸¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿Æ±»Î¤ÏÁê¸ßÈæ³Ó¤Ç¤¤Þ¤¹¡£
- ¾Êά¤·¤¿¾ì¹ç¡¢Â¾¤Î¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤È¤ÏÈæ³Ó¤¬½ÐÍè¤Þ¤»¤ó¡Ê¤Ç¤âÄ̾ï¤ÏÈæ³Ó¤Ç¤¤¿Êý¤¬Îɤ¤¤Ç¤¹¤è¡©¡Ë¡£
- ¤µ¤é¤Ë¾Ü¤·¤¯¤Ï¡¢²¼¤ÎÍó¤ä¡¢¶äÅ·¥é¥¤¥Ö¥é¥ê¤ÇÄêµÁ¤µ¤ì¤¿¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤Î¼ÂÁõ¤ò¤´Í÷¤¯¤À¤µ¤¤¡£
+ 使い方は bool_comparable と同じ、「テンプレートに自分自身の型名を入れて継承」。
+ 第二引数はポインタを格納するオブジェクトの型を示します。
+ 省略可能な第三引数はポインタのカテゴリ、第三引数が同じスマートポインタ同士は相互比較できます。
+ 省略した場合、他のスマートポインタとは比較が出来ません(でも通常は比較できた方が良いですよ?)。
+ さらに詳しくは、下の欄や、銀天ライブラリで定義されたスマートポインタの実装をご覧ください。
- »È¤¤Êý¡§
- // ñ½ã¤Ê¥Ý¥¤¥ó¥¿¤Ø¤Î¥é¥Ã¥Ñ
+ 使い方:
+ // 単純なポインタへのラッパ
- // ¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤òºî¤ë¾ì¹ç¡¢¤Þ¤º¥«¥Æ¥´¥ê¥¯¥é¥¹¤òÄêµÁ¤¹¤ë¡£
- // Ʊ¤¸¼ïÎà¤Î¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤Ç¡¢Æ±¤¸¥«¥Æ¥´¥ê¤ò¶¦Í¤¹¤ë¤³¤È¤Ç¡¢
- // ¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿Æ±»Î¤ÎÁê¸ßÈæ³Ó¤¬¡ÊƱ¤¸¼ïÎà¤Î¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤Ë¸Â¤ê¡Ë²Äǽ¤Ë¤Ê¤ë¡£
- struct trivial_ptr_category {}; // ¥«¥Æ¥´¥ê¥¯¥é¥¹¤Ï¥¿¥°¤Ê¤Î¤ÇŬÅö¤Ë
+ // スマートポインタを作る場合、まずカテゴリクラスを定義する。
+ // 同じ種類のスマートポインタで、同じカテゴリを共有することで、
+ // スマートポインタ同士の相互比較が(同じ種類のスマートポインタに限り)可能になる。
+ struct trivial_ptr_category {}; // カテゴリクラスはタグなので適当に
- // ËÜÂÎ
+ // 本体
template<typename T>
class trivial_ptr :
- public gintenlib::pointer_facade< trivial_ptr<T>, T, trivial_ptr_category > // ¤³¤¦»È¤¦
+ public gintenlib::pointer_facade< trivial_ptr<T>, T, trivial_ptr_category > // こう使う
{
public:
trivial_ptr() : p(0) {}
explicit trivial_ptr( T* ptr ) : p( ptr ) {}
- // ²òÊü½èÍý¤È¤«¹Ô¤ï¤Ê¤¤
+ // 解放処理とか行わない
// ~trivial_ptr() throw () {}
- // get() ¤µ¤¨¤¢¤ì¤ÐOK
+ // get() さえあればOK
T* get() const { return p; }
- // reset ¤È¤« swap ¤â¤¢¤ë¤ÈÎɤ¤¤±¤É¡¢´ðËܤϤ³¤ì¤Ç½ªÎ»¡ª
+ // reset とか swap もあると良いけど、基本はこれで終了!
private:
T* p;
{
trivial_ptr<int> p1( new int() );
- // ¿§¡¹¤È¼«Æ°ÄêµÁ¤·¤Æ¤¯¤ì¤ë¤Î¤Ç
- // ¤³¤ó¤Ê´¶¤¸¤Ë½ñ¤±¤ë
+ // 色々と自動定義してくれるので
+ // こんな感じに書ける
if( p1 ) // OK
{
cout << *p1 << endl; // OK
trivial_ptr<vector<int> > p2( new vector<int>() );
cout << p2->size() << endl; // OK
- trivial_ptr<void> p0; // void ¤Ø¤Î¥Ý¥¤¥ó¥¿¤âŬÀڤ˿¶¤êʬ¤±¤Æ¤¯¤ì¤ë
- assert( p0 != p1 ); // ¤â¤Á¤í¤óÈæ³Ó¤Ç¤¤ë
+ trivial_ptr<void> p0; // void へのポインタも適切に振り分けてくれる
+ assert( p0 != p1 ); // もちろん比較できる
// todo: delete
}
- Ãí°Õ»ö¹à¡§
- ¥Ý¥¤¥ó¥¿¤ËɬÍפʵ¡Ç½¤Ï¤¢¤é¤«¤¿ÍÑ°Õ¤·¤Æ¤¯¤ì¤ëÊØÍø¥¯¥é¥¹¤Ç¤¹¤¬¡¢
- static_pointer_cast ¤ä¤é swap ¤ä¤é reset ¤ä¤é¤ÏÄêµÁ¤·¤Æ¤¯¤ì¤Þ¤»¤ó¡£Ëº¤ì¤Ê¤¤¤è¤¦¤Ë¡£
- ¤Ê¤ª¡¢ friend ´Ø¿ô¤Î get_pointer ¤ä operator== ¤Ê¤ó¤«¤Ï¡¢gintenlib ̾Á°¶õ´ÖÆâ¤ËÄêµÁ¤µ¤ì¤Þ¤¹¡£
- Ä̾ï¤Ï ADL ¤Ë¤è¤Ã¤Æ°Õ¼±¤¹¤ëɬÍפϤ¢¤ê¤Þ¤»¤ó¤¬¡¢¸Å¤¤¥³¥ó¥Ñ¥¤¥é¤Ç¤Ï°ú¤Ã¤«¤«¤ë¤«¤â¡£
+ 注意事項:
+ ポインタに必要な機能はあらかた用意してくれる便利クラスですが、
+ static_pointer_cast やら swap やら reset やらは定義してくれません。忘れないように。
+ なお、 friend 関数の get_pointer や operator== なんかは、gintenlib 名前空間内に定義されます。
+ 通常は ADL によって意識する必要はありませんが、古いコンパイラでは引っかかるかも。
*/
struct pointer_facade
: bool_comparable< pointer_facade< Derived, T, Category > >
{
- // ¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤È¤·¤ÆɬÍפʤ¢¤ì¤³¤ì
+ // スマートポインタとして必要なあれこれ
typedef T element_type;
typedef T value_type;
typedef T* pointer;
- // reference ¤Ï void ·¿¤Ø¤ÎÂбþ¤Î¤¿¤áÆüì
+ // reference は void 型への対応のため特殊
typedef typename boost::add_reference<T>::type reference;
- // »²¾È³°¤·¤È¥Ý¥¤¥ó¥¿¼èÆÀ
+ // 参照外しとポインタ取得
reference operator*() const
{
using namespace std;
return target.get();
}
- // bool ¤È¤ÎÈæ³Ó
+ // bool との比較
bool operator!() const
{
return !get_();
}
- // operator safe_bool ¤Ï bool_comparable ¤Î´É³í
+ // operator safe_bool は bool_comparable の管轄
- // ÅùÃÍÈæ³Ó¤Ê¤É¤Ï³°Éô¤Î¥Æ¥ó¥×¥ì¡¼¥È¤Ç¼ÂÁõ
+ // 等値比較などは外部のテンプレートで実装
private:
template<typename D, typename U, typename C>
friend class pointer_facade;
- // ÇÉÀ¸¥¯¥é¥¹¤Î get() ¤ò¸Æ¤Ó½Ð¤¹
+ // 派生クラスの get() を呼び出す
pointer get_() const
{
return static_cast<const Derived*>(this)->get();
}; // pointer_facade<Derived, T, Category>
- // ¥Æ¥ó¥×¥ì¡¼¥ÈÈÇÁê¸ßÈæ³Ó
- // ¥«¥Æ¥´¥ê¤¬Æ±¤¸¤â¤Î¤Ê¤éÁê¸ßÈæ³Ó£Ï£Ë
+ // テンプレート版相互比較
+ // カテゴリが同じものなら相互比較OK
template<typename T, typename U, typename D1, typename D2, typename C>
inline bool operator==( const pointer_facade<D1, T, C>& lhs, const pointer_facade<D2, U, C>& rhs )
{
template<typename T, typename U, typename D1, typename D2, typename C>
inline bool operator< ( const pointer_facade<D1, T, C>& lhs, const pointer_facade<D2, U, C>& rhs )
{
- // °Û¤Ê¤ë¥Ý¥¤¥ó¥¿Æ±»Î¤ÎÈæ³Ó¤Ï¡¢
- // boost::shared_ptr ¤Ç < ¤ò»È¤Ã¤Æ¤ë¤Î¤Ç¡¢¤³¤³¤Ç¤â < ¤ÇÈæ³Ó¤¹¤ë
+ // 異なるポインタ同士の比較は、
+ // boost::shared_ptr で < を使ってるので、ここでも < で比較する
return static_cast<const D1&>(lhs).get() < static_cast<const D2&>(rhs).get();
}
<gintenlib/preprocessor/dequote.hpp>
- dequote ¡§ ¥Þ¥¯¥í¤Î°ú¿ô¤Ë¥Æ¥ó¥×¥ì¡¼¥È¤ò»È¤¦¾ì¹ç¤Î¥æ¡¼¥Æ¥£¥ê¥Æ¥£
+ dequote ï¼\9a ã\83\9eã\82¯ã\83ã\81®å¼\95æ\95°ã\81«ã\83\86ã\83³ã\83\97ã\83¬ã\83¼ã\83\88ã\82\92使ã\81\86å ´å\90\88ã\81®ã\83¦ã\83¼ã\83\86ã\82£ã\83ªã\83\86ã\82£
- Àë¸À¡§
+ 宣言:
namespace gintenlib
{
namespace detail_
#define GINTENLIB_DEQUOTE( QUOTED_TYPE ) \
::gintenlib::detail_::dequote_helper<void (*)QUOTED_TYPE>::type
- »ÈÍÑÎ㡧
- // Îã¤È¤·¤Æ¡¢Í¿¤¨¤é¤ì¤¿·¿¤Ë¤¿¤¤¤·¡¢¤½¤Î·¿Æó¤Ä¤Î¥Ú¥¢¤Î·¿¤òÊÖ¤¹¥Þ¥¯¥í¤òÄêµÁ¤·¤Æ¤ß¤ë
- // ¥Æ¥ó¥×¥ì¡¼¥È¤Ø¤ÎÊÌ̾ÉÕ¤±¤¬ C++ ɸ½à¤Ç¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤ì¤ÐÉÔÍפǤ¹¤¬¡¢¸½¾õ̵Íý¤Ê¤Î¤Ç
+ 使用例:
+ // 例として、与えられた型にたいし、その型二つのペアの型を返すマクロを定義してみる
+ // テンプレートへの別名付けが C++ 標準でサポートされていれば不要ですが、現状無理なので
- // ¤Þ¤º¥À¥á¤ÊÎã
+ // まずダメな例
// #define PAIR_OF( type ) std::pair<type, type>
- // ¤³¤ì¤À¤È¡¢ PAIR_OF( std::pair<int, double> ) ¤Î¤è¤¦¤Ê
- // Ê£¿ô¤Î°ú¿ô¤ò»ý¤Ä¥Æ¥ó¥×¥ì¡¼¥È·¿¤ò¡¢¥Þ¥¯¥í¤Î°ú¿ô¤È¤·¤ÆÅϤ¹¤³¤È¤¬½ÐÍè¤Ê¤¤
- // ¡Ê¥×¥ê¥×¥í¥»¥Ã¥µ¤Ï¥Æ¥ó¥×¥ì¡¼¥È¤Î»°³Ñ³ç¸Ì¤ò̵»ë¤¹¤ë¤¿¤á¡¢Æó°ú¿ô¥Þ¥¯¥í¤È´ª°ã¤¤¤µ¤ì¤ë¡Ë
+ // これだと、 PAIR_OF( std::pair<int, double> ) のような
+ // 複数の引数を持つテンプレート型を、マクロの引数として渡すことが出来ない
+ // (プリプロセッサはテンプレートの三角括弧を無視するため、二引数マクロと勘違いされる)
- // ¤½¤³¤Ç¡¢¤³¤¦½ñ¤¯
+ // そこで、こう書く
#define PAIR_OF( quoted_type ) \
std::pair< \
typename GINTENLIB_DEQUOTE( quoted_type ), \
typename GINTENLIB_DEQUOTE( quoted_type ) \
>
- // GINTENLIB_DEQUOTE ¤Ï ¤Ê¤ó¤¿¤é::type ¤È¤¤¤¦¤Õ¤¦¤ËŸ³«¤µ¤ì¤ë¤Î¤Ç
- // ɬÍפ˱þ¤¸¤Æ typename ¥¡¼¥ï¡¼¥É¤òÉÕ¤±¤Ê¤±¤ì¤Ð¤¤¤±¤Ê¤¤
- // ÂçÂΤξì¹ç¤Ï¤È¤ê¤¢¤¨¤º typename ¤òÉÕ¤±¤ì¤Ð£Ï£Ë
+ // GINTENLIB_DEQUOTE は なんたら::type というふうに展開されるので
+ // 必要に応じて typename キーワードを付けなければいけない
+ // 大体の場合はとりあえず typename を付ければOK
- // »ÈÍѤ¹¤ë¤È¤¤Ï¡¢
+ // 使用するときは、
PAIR_OF(( std::pair<int, double> )) hoge;
- // ¤³¤Î¤è¤¦¤Ë·¿Ì¾¤òÆó½Å³ç¸Ì¤Ç¤¯¤ë¤à
+ // このように型名を二重括弧でくるむ
- ²òÀ⡧
- ¤³¤Î¥Þ¥¯¥í¤¬²¿¤ò¤·¤Æ¤¤¤ë¤«¤Ï¡¢Îã¤ò¸«¤ì¤Ðʬ¤«¤ë¤È»×¤¦¤Î¤Ç¡¢Ê¬¤«¤Ã¤Æ¤¯¤À¤µ¤¤¡£
- ´Êñ¤Ë¸À¤¨¤Ð¡¢¡Ö ( ·¿Ì¾ ) ¡×¤È¤¤¤¦¥·¥ó¥Ü¥ëÎó¤ò¼õ¤±¼è¤ê¡¢³ç¸Ì¤ò³°¤¹¥Þ¥¯¥í¤Ç¤¹¡£
- ¼ÂÁõÊýË¡¤Ç¤¹¤¬¡¢¼Â¤Ï¡Ö ( ¤Ê¤ó¤¿¤é ) ¡×¤Î³ç¸Ì¤òľÀܳ°¤¹ÊýË¡¤Ï¡ÊÃΤꤨ¤ëÈϰϤǤϡ˸ºß¤·¤Ê¤¤¤Î¤Ç¡¢
- ¡Ö void (*)( ·¿Ì¾ ) ¡×¤È¤¤¤¦É½¸½¤Ëľ¤·¤Æ¡¢´Ø¿ô¤Î°ú¿ô¡¢¤È¤¤¤¦·Á¤Ç·¿Ì¾¤òʬΥ¤·¤Æ¤¤¤Þ¤¹¡£
- ¤½¤¦¤¤¤¦¼ÂÁõ¤ÎÅÔ¹ç¾å¡¢´Ø¿ô·¿¤ò¥Æ¥ó¥×¥ì¡¼¥È¤Î°ú¿ô¤È¤·¤ÆÆü첽¤Ç¤¤ë¥³¥ó¥Ñ¥¤¥é¤Ç¤·¤«Æ°ºî¤·¤Þ¤»¤ó¡£
- ¤Þ¤¿¡¢·¿Ì¾¼«¿È¤ËŸ³«¤µ¤ì¤ë¤ï¤±¤Ç¤â¤Ê¤¤¤Î¤Ç¡¢É¬Íפ˱þ¤¸¤Æ typename ½¤¾þ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£
+ 解説:
+ このマクロが何をしているかは、例を見れば分かると思うので、分かってください。
+ 簡単に言えば、「 ( 型名 ) 」というシンボル列を受け取り、括弧を外すマクロです。
+ 実装方法ですが、実は「 ( なんたら ) 」の括弧を直接外す方法は(知りえる範囲では)存在しないので、
+ 「 void (*)( 型名 ) 」という表現に直して、関数の引数、という形で型名を分離しています。
+ そういう実装の都合上、関数型をテンプレートの引数として特殊化できるコンパイラでしか動作しません。
+ また、型名自身に展開されるわけでもないので、必要に応じて typename 修飾する必要があります。
*/
typedef Arg type;
};
- // ËÜÂÎ
- // QUOTED_TYPE ¤Ï ( DEQUOTED_TYPE ) ¤Î·Á¤Ç»ØÄꤵ¤ì¤ë
- // dequote_helper<void (*)( DEQUOTED_TYPE )>::type ¤Ï DEQUOTED_TYPE ·¿¤È¤Ê¤ë
+ // 本体
+ // QUOTED_TYPE は ( DEQUOTED_TYPE ) の形で指定される
+ // dequote_helper<void (*)( DEQUOTED_TYPE )>::type は DEQUOTED_TYPE 型となる
#define GINTENLIB_DEQUOTE( QUOTED_TYPE ) \
::gintenlib::detail_::dequote_helper<void (*)QUOTED_TYPE>::type
<gintenlib/preprocessor/enable_if.hpp>
- preprocessor.enable_if ¡§ ¤é¤¯¤Á¤ó enable_if
+ preprocessor.enable_if : らくちん enable_if
- Àë¸À¡§
- #define GINTENLIB_ENABLE_IF (( condition )) ¡Á
- #define GINTENLIB_DISABLE_IF(( condition )) ¡Á
+ 宣言:
+ #define GINTENLIB_ENABLE_IF (( condition )) 〜
+ #define GINTENLIB_DISABLE_IF(( condition )) 〜
- »ÈÍÑÎ㡧
- // d_enable_if.hpp ¤ÎÎã¤ò¤ä¤Ã¤Ä¤±¤ë
- // using namespace gintenlib; // ¤³¤ó¤Ê¤ÎɬÍפʤ¤
+ 使用例:
+ // d_enable_if.hpp の例をやっつける
+ // using namespace gintenlib; // こんなの必要ない
- // °ú¿ô¤ò Target ·¿¤Ø°ÅÌÛÊÑ´¹¤¹¤ë
- // Ä̾ïÈÇ¡¢Target ¤¬»²¾È·¿¤Ç¤Ê¤±¤ì¤Ð¤³¤Ã¤Á¤¬¸Æ¤Ð¤ì¤ë
- // ÂèÆó°ú¿ô¤ËÃíÌÜ¡£¤Á¤Ê¤ß¤Ë¤³¤Î°ú¿ô¤Ï¥À¥ß¡¼¤Ê¤Î¤Ç̵»ë¤·¤Æ£Ï£Ë
+ // 引数を Target 型へ暗黙変換する
+ // 通常版、Target が参照型でなければこっちが呼ばれる
+ // 第二引数に注目。ちなみにこの引数はダミーなので無視してOK
template< typename Target, typename Source >
inline Target cast( const Source& src,
GINTENLIB_DISABLE_IF(( boost::is_reference<Target> )) )
return src;
}
- // »²¾ÈÈÇ
+ // 参照版
template< typename Target, typename Source >
inline Target cast( Source& src,
GINTENLIB_ENABLE_IF(( boost::is_reference<Target> )) )
return src;
}
- // c.f.) d_enable_if.hpp ¤ÎÎã
+ // c.f.) d_enable_if.hpp の例
//
- // // »²¾ÈÈÇ
+ // // 参照版
// template< typename Target, typename Source >
// inline Target cast( Source& src,
// typename d_enable_if< boost::is_reference<Target> >::type = dummy_arg_t() )
// return src;
// }
//
- // Èæ³Ó¤·¤Æ¤ß¤ë¤È¡¢¤É¤ì¤À¤±³Ú¤«Ê¬¤«¤ë¤Ï¤º
+ // 比較してみると、どれだけ楽か分かるはず
- ²òÀ⡧
- ´Ø¿ô¥ª¡¼¥Ð¡¼¥í¡¼¥ÉÍѤΠenable_if ¤ò¤é¤¯¤Á¤ó¤Ë¤¹¤ë¤¿¤á¤Î¥Þ¥¯¥í¤Ç¤¹¡£
- ¼ÂºÝ¤Ë¤É¤Î¤è¤¦¤ËŸ³«¤µ¤ì¤Æ¤¤¤ë¤«¤Ï²¼¤ÎÎã¤ò¤´Í÷¤¯¤À¤µ¤¤¡£
- ¤Þ¡¼¿¿ÌÌÌܤ˽ñ¤¤¤Æ¤âÎɤ¤¤Î¤Ç¤¹¤¬¡¢
- typename gintenlib::d_enable_if< ¤Ê¤ó¤¿¤é, gintenlib::dummy_arg_t >::type
+ 解説:
+ 関数オーバーロード用の enable_if をらくちんにするためのマクロです。
+ 実際にどのように展開されているかは下の例をご覧ください。
+ まー真面目に書いても良いのですが、
+ typename gintenlib::d_enable_if< なんたら, gintenlib::dummy_arg_t >::type
= gintenlib::dummy_arg_t()
- ÀµÄ¾¤³¤ó¤ÊŤ¤¥½¡¼¥¹¥³¡¼¥É¤Ê¤ó¤Æ½ñ¤¤¤Æ¤é¤ì¤Þ¤»¤ó¤«¤é¤Í¡£
- d_enable_if ¤È dummy_arg_t ¤Î¸ºß°ÕµÁ¤Ï <gintenlib/d_enable_if.hpp> ¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡£
+ 正直こんな長いソースコードなんて書いてられませんからね。
+ d_enable_if と dummy_arg_t の存在意義は <gintenlib/d_enable_if.hpp> を参照してください。
- »È¤¤Êý¤Ï¡¢¾å¤ÎÎã¤ÎÄ̤ꡢenable_if ¤Î <> ¤ÎÃæ¤Îµ½Ò¤ò¡ÖÆó½Å³ç¸Ì¤Ç¤¯¤¯¤Ã¤Æ¡×¥Þ¥¯¥í¤ËÅϤ·¤Æ¡¢
- ´Ø¿ô¤Î°ú¿ô¥ê¥¹¥È¤ÎºÇ¸å¤ËÃÖ¤¤¤Æ¤ª¤¯¤À¤±¡£´Êñ¤Ç¤¹¡£
- ÉáÄÌ¡¢¤³¤¦¤¤¤¦¡Ö¥á¥¿´Ø¿ô¤ò°ú¿ô¤Ë¼è¤ë¡×¥Þ¥¯¥í¤Ã¤Æ¤Î¤Ï¡¢¥Æ¥ó¥×¥ì¡¼¥È°ú¿ô¥ê¥¹¥È¤Î¥«¥ó¥Þ¤¬¼ÙËâ¤ò¤·¤Æ
- Àµ¾ï¤Ë¥Þ¥¯¥íŸ³«¤µ¤ì¤Ê¤«¤Ã¤¿¤ê¤¹¤ë¤Î¤Ç¤¹¤¬¡¢¤³¤ì¤Ë´Ø¤·¤Æ¤Ïµ¤¤Ë¤¹¤ëɬÍפϤ¢¤ê¤Þ¤»¤ó¡£
- ¥æ¡¼¥¶Â¦¤ÇÃí°Õ¤¹¤Ù¤¤Ï°ìÅÀ¤Î¤ß¡¢¥Þ¥¯¥í¤Î°ú¿ô¤Ïɬ¤ºÆó½Å³ç¸Ì¤Ç¤¯¤ë¤à¤³¤È¡£
- ¤½¤³¤Ë¤µ¤¨µ¤¤ò¤Ä¤±¤ì¤Ð´Êñ¤Ë´Ø¿ô¸Æ¤Ó½Ð¤·¤ÎÀÚ¤êÂؤ¨¤¬½ÐÍè¤Þ¤¹¡£ÊØÍø¤Ç¤¹¡£
+ 使い方は、上の例の通り、enable_if の <> の中の記述を「二重括弧でくくって」マクロに渡して、
+ 関数の引数リストの最後に置いておくだけ。簡単です。
+ 普通、こういう「メタ関数を引数に取る」マクロってのは、テンプレート引数リストのカンマが邪魔をして
+ 正常にマクロ展開されなかったりするのですが、これに関しては気にする必要はありません。
+ ユーザ側で注意すべきは一点のみ、マクロの引数は必ず二重括弧でくるむこと。
+ そこにさえ気をつければ簡単に関数呼び出しの切り替えが出来ます。便利です。
*/
namespace gintenlib
{
- // GINTENLIB_DEQUOTE(( TYPE )) ¤Ï¡¢ ¤Ê¤ó¤È¤«<¡Á>::type ¤È¤¤¤¦·Á¤ÇŸ³«¤µ¤ì¤ë
- // ¤³¤Î type ¤¬ TYPE ·¿¤ËÄêµÁ¤µ¤ì¤ë¤è¤¦¤Ê»Å³Ý¤±¤È¤Ê¤Ã¤Æ¤¤¤ë
- // ¤è¤Ã¤Æ GINTENLIB_DEQUOTE Á°¤Î typename ¤Ïɬ¿Ü
+ // GINTENLIB_DEQUOTE(( TYPE )) は、 なんとか<〜>::type という形で展開される
+ // この type が TYPE 型に定義されるような仕掛けとなっている
+ // よって GINTENLIB_DEQUOTE 前の typename は必須
#define GINTENLIB_ENABLE_IF( quoted_type ) \
typename ::gintenlib::d_enable_if< \
typename GINTENLIB_DEQUOTE( quoted_type ) \
<gintenlib/reference_counter.hpp>
- reference_counter ¡§ boost::intrusive_ptr ÍÑ¥ª¥Ö¥¸¥§¥¯¥ÈÀ¸À®
+ reference_counter : boost::intrusive_ptr 用オブジェクト生成
- Àë¸À¡§
+ 宣言:
template<typename Derived, bool multiplely_successable = false >
class reference_counter
{
public:
- // »²¾È¤òÁý¤ä¤¹
+ // 参照を増やす
void AddRef() const;
- // »²¾È¤ò¸º¤é¤¹¡£¥¼¥í¤Ë¤Ê¤Ã¤¿¤é¼«Æ°²òÊü
+ // 参照を減らす。ゼロになったら自動解放
void Release() const;
protected:
- // ½é´ü¥«¥¦¥ó¥È¤ò»ØÄꤷ¤Æ½é´ü²½
+ // 初期カウントを指定して初期化
reference_counter( int initial_count = 0 );
- // ¥³¥Ô¡¼¤Ï°ì±þ²Äǽ¤Ë¤¹¤ë
- // ¥«¥¦¥ó¥È¤ÏÆ°¤«¤Ê¤¤
+ // コピーは一応可能にする
+ // カウントは動かない
reference_counter( const reference_counter& );
- // ²òÊü
+ // 解放
~reference_counter();
private:
- // ÂåÆþ¤Ï½ÐÍè¤Ê¤¤
+ // 代入は出来ない
void operator=( const reference_counter& );
};
template< typename T, bool b >
inline void intrusive_ptr_release( const reference_counter<T, b>* ptr );
- »ÈÍÑË¡¡§
+ 使用法:
class hoge : public gintenlib::reference_counter<hoge>
{
- // ŬÅö¤ËÃæ¿È¤òµ½Ò
+ // 適当に中身を記述
};
boost::intrusive_ptr<hoge> p = new hoge;
// or gintenlib::com_ptr<hoge> p( new hoge );
- // ¿½Å·Ñ¾µ¤â½ÐÍè¤Þ¤¹¡£¤½¤Î¾ì¹ç¤Ï¥Æ¥ó¥×¥ì¡¼¥ÈÂèÆó°ú¿ô¤Ë true ¤òÅϤ·¤Æ¤¯¤À¤µ¤¤
+ // 多重継承も出来ます。その場合はテンプレート第二引数に true を渡してください
struct base1 : gintenlib::reference_counter<base1, true>
{
- // Ãæ¿È
+ // 中身
};
struct base2 : gintenlib::reference_counter<base2, true>
{
- // Ãæ¿È
+ // 中身
};
struct derived : base1, base2
{
- // Ãæ¿È
+ // 中身
};
- µ¡Ç½¡§
- »ÈÍÑË¡¤ò¸«¤ì¤Ð°ìÌÜÎÆÁ³¤Ç¤·¤ç¤¦¡£¥Æ¥ó¥×¥ì¡¼¥È°ú¿ô¤Ë¼«¿È¤òÅϤ·¤Æ·Ñ¾µ¤¹¤ì¤ÐOK¤Ç¤¹¡£
- ÂèÆó¥Æ¥ó¥×¥ì¡¼¥È°ú¿ô¤Ï¡¢Â¿½Å·Ñ¾µ¤¬½ÐÍè¤ë¤«Èݤ«¡£true¤òÅϤ»¤Ð¿½Å·Ñ¾µ¤Ç¤¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£
- ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï false ¤Ç¤¹¡£¤³¤Î¾ì¹ç¡¢²¾ÁÛ´Ø¿ô¥Æ¡¼¥Ö¥ë¤Ï»ÈÍѤ·¤Æ¤¤¤Þ¤»¤ó¡£
- ¤è¤Ã¤Æ¡¢Èó¿½Å·Ñ¾µÈǤǷѾµ¤ò¤·¤¿¤¤¾ì¹ç¡¢¥Ç¥¹¥È¥é¥¯¥¿¤ò virtual »ØÄꤹ¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£
- ¿½Å·Ñ¾µÈǤǤϡ¢¤½¤¦¤¤¤Ã¤¿µ¤¸¯¤¤¤ò¤¹¤ëɬÍפϤ¢¤ê¤Þ¤»¤ó¡£¤¬¡¢¤½¤Îʬ¥³¥¹¥È¤¬¹â¤¤¤Ç¤¹¡£
+ 機能:
+ 使用法を見れば一目瞭然でしょう。テンプレート引数に自身を渡して継承すればOKです。
+ 第二テンプレート引数は、多重継承が出来るか否か。trueを渡せば多重継承できるようになります。
+ デフォルトでは false です。この場合、仮想関数テーブルは使用していません。
+ よって、非多重継承版で継承をしたい場合、デストラクタを virtual 指定する必要があります。
+ 多重継承版では、そういった気遣いをする必要はありません。が、その分コストが高いです。
- È÷¹Í¡§
- ¤³¤Î¥¯¥é¥¹¤Ï¡¢Åö½é¤Ï noncopyable ¤È¤·¤ÆÀ½ºî¤µ¤ì¤Æ¤¤¤Þ¤·¤¿¡£
- ¤·¤«¤·¡¢ÇÉÀ¸Àè¤Ç¥³¥Ô¡¼¥³¥ó¥¹¥È¥é¥¯¥¿¤ò¼«Æ°À¸À®¤·¤Æ¤¯¤ì¤Ê¤¤¤Î¤ÏÌÌÅݤʤΤǡ¢¥³¥Ô¡¼¤Ë¸Â¤ê²Äǽ¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£
- ¤³¤ÎºÝ¡¢»²¾È¥«¥¦¥ó¥È¤Ë´Ø¤·¤Æ¤Ï¡¢¥³¥Ô¡¼¸µ¤Ë¤Ï̵´Ø·¸¤Ë 0 ¤Ë½é´ü²½¤µ¤ì¤Þ¤¹¡£
- ¤Þ¤¿ÂåÆþ±é»»¤Ï¡Ö copy ¤·¤Æ swap ¡×¤È¤¤¤¦Îã³°°ÂÁ´¤ÊÊýË¡¤¬¤¢¤ë¤Î¤Ç¡¢¤½¤Á¤é¤ò¿ä¾©¤¹¤ë°ÕÌ£¤Ç¶Ø»ß¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£
+ 備考:
+ このクラスは、当初は noncopyable として製作されていました。
+ しかし、派生先でコピーコンストラクタを自動生成してくれないのは面倒なので、コピーに限り可能になっています。
+ この際、参照カウントに関しては、コピー元には無関係に 0 に初期化されます。
+ また代入演算は「 copy して swap 」という例外安全な方法があるので、そちらを推奨する意味で禁止になっています。
*/
namespace gintenlib
{
- // Èó²¾ÁۥС¼¥¸¥ç¥ó¡£¥µ¥¤¥º¤ä®ÅÙ¤ÎÌ̤ǺÇŬ²½¤µ¤ì¤Þ¤¹¤¬¡¢Â¿½Å·Ñ¾µ¤Ï½ÐÍè¤Þ¤»¤ó
+ // 非仮想バージョン。サイズや速度の面で最適化されますが、多重継承は出来ません
template<typename Derived, bool multiplely_successable = false >
struct reference_counter
{
}
}
- // »²¾È¥«¥¦¥ó¥È¤ò¼èÆÀ
+ // 参照カウントを取得
int use_count() const { return count; }
protected:
assert( count == 0 );
}
- // ¥³¥Ô¡¼¤Ï°ì±þ²Äǽ¤Ë¤¹¤ë
+ // コピーは一応可能にする
reference_counter( const reference_counter& ) : count(0) {}
private:
mutable int count;
- // ÂåÆþ¤Ï½ÐÍè¤Ê¤¤
+ // 代入は出来ない
void operator=( const reference_counter& );
};
- // boost::intrusive_ptr ÍѤΥ¤¥ó¥¿¡¼¥Õ¥§¥¤¥¹
- // reference_counter<T> ¤Ï reference_counter<T, false> ¤Î°ÕÌ£¤Ê¤Î¤Ç
- // ²¾Á۷ѾµÈǤȤ϶¥¹ç¤·¤Þ¤»¤ó
+ // boost::intrusive_ptr ç\94¨ã\81®ã\82¤ã\83³ã\82¿ã\83¼ã\83\95ã\82§ã\82¤ã\82¹
+ // reference_counter<T> は reference_counter<T, false> の意味なので
+ // 仮想継承版とは競合しません
template< typename T >
inline void intrusive_ptr_add_ref( const reference_counter<T>* ptr )
{
}
- // ²¾Á۷ѾµÈǤΥ١¼¥¹¥¯¥é¥¹
+ // ä»®æ\83³ç¶\99æ\89¿ç\89\88ã\81®ã\83\99ã\83¼ã\82¹ã\82¯ã\83©ã\82¹
struct reference_counter_base
{
void AddRef() const
delete this;
}
}
- // »²¾È¥«¥¦¥ó¥È¤ò¼èÆÀ
+ // 参照カウントを取得
int use_count() const { return count; }
protected:
assert( count == 0 );
}
- // ¥³¥Ô¡¼¤Ï°ì±þ²Äǽ¤Ë¤¹¤ë
+ // コピーは一応可能にする
reference_counter_base( const reference_counter_base& ) : count(0) {}
private:
mutable int count;
- // ÂåÆþ¤Ï½ÐÍè¤Ê¤¤
+ // 代入は出来ない
void operator=( const reference_counter_base& );
};
- // ²¾Á۷ѾµÈÇËÜÂΡ£¥³¥¹¥È¤Ï¹â¤¤¤Ç¤¹¤¬¥À¥¤¥¢¥â¥ó¥É·Ñ¾µ¤Ç¤¤Þ¤¹
+ // 仮想継承版本体。コストは高いですがダイアモンド継承できます
template<typename Derived>
struct reference_counter<Derived, true>
: virtual reference_counter_base
};
- // ²¾Á۷ѾµÈÇ¤Ç¤Ï reference_counter_base ¤ËÂФ· add_ref/release ¤òÄêµÁ¤¹¤ë¤³¤È¤Ç
- // ¾×Æͤ¬µ¯¤³¤é¤Ê¤¤¤è¤¦¤Ë¹©Éפµ¤ì¤Æ¤¤¤Þ¤¹
+ // 仮想継承版では reference_counter_base に対し add_ref/release を定義することで
+ // 衝突が起こらないように工夫されています
inline void intrusive_ptr_add_ref( const reference_counter_base* ptr )
{
ptr->AddRef();
<gintenlib/shared_ptr.hpp>
- shared_ptr ¡§ boost::shared_ptr ¤Î using Àë¸À
+ shared_ptr : boost::shared_ptr の using 宣言
- Àë¸À¡§
+ 宣言:
using boost::shared_ptr;
- µ¡Ç½¡§
- ñ½ã¤Ë gintenlib Æâ¤Ç boost::shared_ptr ¤ò»È¤¦µ¡²ñ¤Ï¿¤¤¤Î¤Ç¡¢
- ͽ¤á using Àë¸À¤·¤Æ¤ª¤±¤Ð¡¢¤¤¤Á¤¤¤Á boost:: ¤È»ØÄꤷ¤Æ¤ä¤ëɬÍפ¬Ìµ¤¯¤Æ³Ú¡¢¤À¤±¤Î¥Ø¥Ã¥À¤Ç¤¹¡£
- ¤¢¤È¤Ï TR1 ¤Ø¤ÎÂбþ¤ò¤·¤ä¤¹¤¤¤è¤¦¤Ë¡¢¤È¤¤¤¦°ÕµÁ¤â¤¢¤ê¤Þ¤¹¡£
- ¤½¤Î¾ì¹ç¤Ï¸ß´¹À¤¬¼º¤ï¤ì¤ë²ÄǽÀ¤â¤¢¤ë¤Î¤Ç¡¢¤ä¤ë¤È¤¹¤ì¤Ð¥á¥¸¥ã¡¼¥Ð¡¼¥¸¥ç¥ó¥¢¥Ã¥×»þ¤Ç¤·¤ç¤¦¤¬¡£
+ 機能:
+ 単純に gintenlib 内で boost::shared_ptr を使う機会は多いので、
+ 予め using 宣言しておけば、いちいち boost:: と指定してやる必要が無くて楽、だけのヘッダです。
+ あとは TR1 への対応をしやすいように、という意義もあります。
+ その場合は互換性が失われる可能性もあるので、やるとすればメジャーバージョンアップ時でしょうが。
*/
<gintenlib/storage.hpp>
- storage ¡§ ¥á¥â¥êÎΰè³ÎÊÝÍÑ¥¯¥é¥¹
+ storage ï¼\9a ã\83¡ã\83¢ã\83ªé \98å\9f\9f確ä¿\9dç\94¨ã\82¯ã\83©ã\82¹
- Àë¸À¡§
+ 宣言:
template< typename T >
struct storage
: boost::aligned_storage< sizeof(T), boost::alignment_of<T>::value > {};
- µ¡Ç½¡§
- T ·¿¤Î¥¯¥é¥¹¤ò³ÊǼ¤Ç¤¤ë¤À¤±¤Î¥á¥â¥êÎΰè¤ò³ÎÊݤ·¤¿¤¤¾ì¹ç¡¢
- °Âľ¤Ë char[sizeof(T)] ¤ò»È¤¦¤È¡¢¥¢¥é¥¤¥á¥ó¥È¤ÎÌäÂ꤬ȯÀ¸¤·¤Þ¤¹¡Ê¾Ü¤·¤¯¤ÏÄ´¤Ù¤Æ¤¯¤À¤µ¤¤¡Ë¡£
- ¤½¤ì¤òÈò¤±¤ë°Ù¤ÎÉôÉʤ¬¡¢ boost ¤Ë¤¢¤ë alignment_storage ¥¯¥é¥¹¤Ç¤¢¤ê¡¢
+ 機能:
+ T 型のクラスを格納できるだけのメモリ領域を確保したい場合、
+ 安直に char[sizeof(T)] を使うと、アライメントの問題が発生します(詳しくは調べてください)。
+ それを避ける為の部品が、 boost にある alignment_storage クラスであり、
boost::aligned_storage< sizeof(T), boost::alignment_of<T>::value >
- ¤È¤¤¤¦·¿¤ò»È¤¦¤³¤È¤Ç¡¢ T ·¿¤Î¥¯¥é¥¹¤ò³ÊǼ¤Ç¤¤ë¥á¥â¥êÎΰè¤ò³ÎÊݤ¹¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡£
- ¤·¤«¤·¤³¤ì¤Ë¤Ï¼åÅÀ¤¬¤¢¤ê¤Þ¤¹¡£¤³¤Îɽ¸½¤Ç¤Ïľ´¶Åª¤Ë¡Ö T ·¿¤òÆþ¤ì¤ë¤¿¤á¤Î¾ì½ê¡×¤Èʬ¤«¤ê¤Þ¤»¤ó¡£
- ¤½¤³¤Ç¡¢¤â¤Ã¤Èľ´¶Åª¤Êɽ¸½¤È¤·¤ÆÍÑ°Õ¤µ¤ì¤¿¤Î¤¬ gintenlib::storage<T> ¤Ç¤¹¡£
- °ÕÌ£¤Ï¤½¤Î¤Þ¤Þ¡Ö T ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤ò³ÊǼ¤Ç¤¤ë¥á¥â¥êÎΰè¡×¡£
- ¤½¤ÎÎΰè¤Î¥¢¥É¥ì¥¹¤ò¼èÆÀ¤·¤¿¤¤¾ì¹ç¤Ï address() ´Ø¿ô¤ò¸Æ¤Ó½Ð¤¹¤³¤È¤Ç»È¤¨¤Þ¤¹¡£
+ という型を使うことで、 T 型のクラスを格納できるメモリ領域を確保することが出来ます。
+ しかしこれには弱点があります。この表現では直感的に「 T 型を入れるための場所」と分かりません。
+ そこで、もっと直感的な表現として用意されたのが gintenlib::storage<T> です。
+ 意味はそのまま「 T 型のオブジェクトを格納できるメモリ領域」。
+ その領域のアドレスを取得したい場合は address() 関数を呼び出すことで使えます。
*/
namespace gintenlib
{
- // T ·¿¤ò¼ý¤á¤é¤ì¤ë¥á¥â¥êÎΰè
+ // T 型を収められるメモリ領域
template<typename T>
struct storage
: boost::aligned_storage< sizeof(T), boost::alignment_of<T>::value > {};
<gintenlib/to_shared.hpp>
- to_shared ¡§ Ǥ°Õ¤Î¥Ý¥¤¥ó¥¿¤ò shared_ptr ¤ËÊÑ´¹
+ to_shared : 任意のポインタを shared_ptr に変換
- Àë¸À¡§
- // Ǥ°Õ´Ø¿ô
+ 宣言:
+ // 任意関数
template<typename P>
shared_ptr<typename P::element_type> to_shared( const P& pt );
template<typename T>
shared_ptr<T> to_shared( std::auto_ptr<T> p );
- // trivial ¤Ç¤¹¤¬ shared_ptr ¤«¤é¤â
+ // trivial ですが shared_ptr からも
template<typename T>
shared_ptr<T> to_shared( const shared_ptr<T>& p );
- // ¤³¤ì¤Ï intrusive_to_shared.hpp Æâ¤ÇÄêµÁ
+ // これは intrusive_to_shared.hpp 内で定義
template<typename T>
shared_ptr<T> to_shared( const boost::intrusive_ptr<T>& p );
- // ¤½¤Î¤Û¤«¡¢¶äÅ·¥é¥¤¥Ö¥é¥ê¤Î³Æ¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤ËÂФ·Å¬ÀÚ¤Ê to_shared ¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ë
+ // そのほか、銀天ライブラリの各スマートポインタに対し適切な to_shared が定義されている
- µ¡Ç½¡§
- ³Æ¼ï¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤ò shared_ptr ¤ËÊÑ´¹¤·¤Þ¤¹¡£
- ÈÆÍÑÈǤÏÂçÉôʬ¤Î¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤òÊÑ´¹¤·¤Æ¤¯¤ì¤ë¤Ï¤º¤Ç¤¹¤¬¡¢º£¤Î¤È¤³¤íÆ°ºîÊݾã¤Ï¤Ç¤¤Þ¤»¤ó¡£
- Æ°ºîÊݾã¤Î½ÐÍè¤Ê¤¤ÈÆÍÑÈǤò¤ï¤¶¤ï¤¶»Ä¤·¤Æ¤¤¤ëÍýͳ¤Ï¡¢Ì¾Á°¶õ´Ö¤Î¼«Æ°¾È²ñ¤ò¹Ô¤¨¤ë¤è¤¦¤Ë¤Ç¤¹¡£
- Boost.Swap ( http://www.boost.org/doc/libs/1_41_0/libs/utility/swap.html ) ¤ÈƱ¤¸¤è¤¦¤Ë¡¢
- gintenlib::to_shared( pt ) ¤Èµ½Ò¤µ¤ì¤¿¾ì¹ç¡¢ gintenlib ̾Á°¶õ´Ö¤À¤±¤Ç¤Ê¤¯¡¢
- pt ¤Î¥¯¥é¥¹¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ë̾Á°¶õ´Ö¤«¤é¤â to_shared ´Ø¿ô¤òõ¤·¤Æ¤¯¤ì¤Þ¤¹¡£
+ 機能:
+ 各種スマートポインタを shared_ptr に変換します。
+ 汎用版は大部分のスマートポインタを変換してくれるはずですが、今のところ動作保障はできません。
+ 動作保障の出来ない汎用版をわざわざ残している理由は、名前空間の自動照会を行えるようにです。
+ Boost.Swap ( http://www.boost.org/doc/libs/1_41_0/libs/utility/swap.html ) と同じように、
+ gintenlib::to_shared( pt ) と記述された場合、 gintenlib 名前空間だけでなく、
+ pt のクラスが定義されている名前空間からも to_shared 関数を探してくれます。
*/
#include <cassert>
#include <memory>
-// friend ´Ø¿ô¤ò»È¤¤¤ä¤¹¤¤¤è¤¦¤Ë
-// ËÜÂΤÏÊ̤Î̾Á°¶õ´Ö¤ò»È¤¦
+// friend 関数を使いやすいように
+// 本体は別の名前空間を使う
namespace gintenlib_to_shared_impl_
{
- // ¤¤¤ï¤æ¤ë¡Ö¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¡×¤òÊÝ»ý¤¹¤ë¥Û¥ë¥À
- // shared_ptr ¤Î¥³¥ó¥¹¥È¥é¥¯¥¿¤ÎÂèÆó°ú¿ô¤È¤·¤ÆÅϤ¹ºï½ü»Ò¤È¤·¤Æ»È¤¨¤ë
+ // いわゆる「スマートポインタ」を保持するホルダ
+ // shared_ptr のコンストラクタの第二引数として渡す削除子として使える
template<typename Pointer>
struct to_shared_holder
{
typedef typename Pointer::element_type T;
typedef boost::shared_ptr<T> shared_t;
- // ¹½ÃÛ
+ // 構築
to_shared_holder()
: pt() {}
to_shared_holder( const Pointer& pt_ )
: pt( pt_ ) {}
- // shared_ptr ¤Ë¤¹¤ë
+ // shared_ptr にする
static shared_t to_shared( const Pointer& pt_ )
{
- // ¤Þ¤º null pointer ¤ËÂФ¹¤ëºÇŬ²½
+ // まず null pointer に対する最適化
T* p = pt_.get();
if( !p ){ return shared_t(); }
- // ËÜÂΤÏžÁ÷
+ // 本体は転送
return to_shared_holder(pt_).to_shared();
}
- // ËÜÂÎ
- // ¤³¤ì¤ò¼Â¹Ô¤¹¤ë¤È¡¢¤³¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ï NULL ¤ËºÆÀßÄꤵ¤ì¤ë
+ // 本体
+ // これを実行すると、このオブジェクトは NULL に再設定される
shared_t to_shared()
{
using namespace std; // for assert()
T* p = pt.get();
- // ¤¤¤Ã¤¿¤ó²¾¤Î to_shared_holder ¤ò»È¤Ã¤Æ shared_ptr ¤òºî¤ë
- // ¤³¤³¤ÇÎã³°¤¬Åꤲ¤é¤ì¤¿¾ì¹ç¡¢²¿¤â¹Ô¤ï¤ì¤ºÈ´¤±¤ë¤Î¤Ç°ÂÁ´
+ // いったん仮の to_shared_holder を使って shared_ptr を作る
+ // ここで例外が投げられた場合、何も行われず抜けるので安全
shared_t temp( p, to_shared_holder() );
- // ºî¤é¤ì¤¿ shared_ptr ¤ÎÃæ¿È¤ò¤¤¤¸¤ë
- // ¥Ý¥¤¥ó¥È¤Ï¡¢¤³¤³¤«¤é²¾¤Î to_shared_holder ¤¬Àµ¤·¤¯ÀßÄꤵ¤ì¤ë¤Þ¤Ç¡¢Îã³°¤¬Åꤲ¤é¤ì¤Ê¤¤¤³¤È
+ // 作られた shared_ptr の中身をいじる
+ // ポイントは、ここから仮の to_shared_holder が正しく設定されるまで、例外が投げられないこと
- // ¤³¤ì¤ÏÎã³°¤òÅꤲ¤Ê¤¤
+ // これは例外を投げない
to_shared_holder* holder = boost::get_deleter< to_shared_holder >( temp );
- // ºî¤Ã¤¿¤Ð¤«¤ê¤Î holder ¤Î·¿¤¬ÉÔ°ìÃפʤ櫓¤Ê¤¤
+ // 作ったばかりの holder の型が不一致なわけない
assert( holder != 0 );
- // ¤³¤ì¤âÂç¾æÉ×
+ // これも大丈夫
Pointer& pt_ = holder->pt;
- // ¤³¤ì¤¬°ìÈ֤λ³¾ì¡£ÉáÄÌ¤Ï swap ¤Ï nothrow ¤È¿®¤¸¤ë
+ // これが一番の山場。普通は swap は nothrow と信じる
swap( pt, pt_ );
- // ¤³¤ì¤Ç to_shared_pointer ¤ÎÃæ¿È¤¬Àµ¤·¤¯ÀßÄꤵ¤ì¤¿
+ // これで to_shared_pointer の中身が正しく設定された
- // °ì±þ³Îǧ¤¹¤ë
+ // 一応確認する
assert( pt.get() == 0 && pt_.get() == p );
- // ²¿¸Î¤³¤ó¤ÊÌÌÅݤʤ³¤È¤ò¤·¤Æ¤¤¤ë¤«¤È¤¤¤¦¤È¡¢
- // ¿¼¤¤¥³¥Ô¡¼¤ò¹Ô¤¦¥¿¥¤¥×¤Î¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤âÌäÂê¤Ê¤¯ÊÝ»ý¤Ç¤¤ë¤è¤¦¤Ë¤·¤¿¤¤¤¿¤á¡£
- // Pointer p2 = p1; ¤Î½èÍý¤ò¤·¤¿¸å¤Ë¡¢ p1.get() == p2.get() ¤Ç¤¢¤ëÊݾڤϤʤ¤¤Î¤Ç¤¹
+ // 何故こんな面倒なことをしているかというと、
+ // 深いコピーを行うタイプのスマートポインタも問題なく保持できるようにしたいため。
+ // Pointer p2 = p1; の処理をした後に、 p1.get() == p2.get() である保証はないのです
- // ´°À®¤·¤¿ shared_ptr ¤òÊÖ¤¹
+ // 完成した shared_ptr を返す
return temp;
}
- // °ìÈÖÂç»ö¤Ê¤Ï¤º¤Îºï½ü´Ø¿ô¡¦¡¦¡¦¤À¤¬
- // ¤ä¤Ã¤Æ¤ë¤³¤È¤ÏÆäË̵¤·
+ // 一番大事なはずの削除関数・・・だが
+ // やってることは特に無し
typedef void result_type;
void operator()( T* target ) throw ()
{
- // °ì±þ¡¢Àµ¤·¤¤¥¿¡¼¥²¥Ã¥È¤òºï½ü¤·¤Æ¤¤¤ë¤«¤É¤¦¤«¡¢¥Á¥§¥Ã¥¯¤¹¤ë
+ // 一応、正しいターゲットを削除しているかどうか、チェックする
using namespace std;
assert( !pt.get() || pt.get() == target );
- // ¤³¤ì¤¬¸Æ¤Ð¤ì¤¿¸å¤Ë shared_ptr ¤ÎƯ¤¤Ç¤³¤Î¥ª¥Ö¥¸¥§¥¯¥È¤¬ÇË´þ¤µ¤ì¡¢
- // Ʊ»þ¤Ë pt ¤Î͸ú´ü¸Â¤âÀÚ¤ì¤ë¤Î¤Ç¡¢¤³¤³¤Ç¤Ï²¿¤â¤·¤Ê¤¤
+ // これが呼ばれた後に shared_ptr の働きでこのオブジェクトが破棄され、
+ // 同時に pt の有効期限も切れるので、ここでは何もしない
}
private:
- // ¥á¥ó¥Ð¤È¤·¤Æ Pointer ¤òÊÝ»ý¤¹¤ë¤Î¤Ç
- // ¤³¤ì¤¬Â¸ºß¤¹¤ë¸Â¤ê¡¢
+ // メンバとして Pointer を保持するので
+ // これが存在する限り、
Pointer pt;
}; // to_shared_holder<Pointer>
- // ¡ÖǤ°Õ¥Ý¥¤¥ó¥¿¤ÎÊÑ´¹¡×ËÜÂÎ
+ // 「任意ポインタの変換」本体
template<typename P>
inline boost::shared_ptr<typename P::element_type> to_shared( const P& pt )
{
} // namespace gintenlib_to_shared_impl_
-// žÁ÷
+// 転送
namespace gintenlib_to_shared_impl
{
- // ¤³¤ì¤âÇö¤¤¥é¥Ã¥Ñ
+ // これも薄いラッパ
template<typename P>
inline boost::shared_ptr<typename P::element_type> to_shared_impl( const P& pt )
{
namespace gintenlib
{
- // ËÜÂΤÏñ¤Ê¤ë¥é¥Ã¥Ñ
+ // 本体は単なるラッパ
template<typename P>
inline shared_ptr<typename P::element_type> to_shared( const P& pt )
{
<gintenlib/to_string.hpp>
- to_string ¡§ ʸ»úÎóÊÑ´¹
+ to_string : 文字列変換
- Àë¸À¡§
+ 宣言:
template<typename T>
std::string to_str( const T& src );
template<typename T>
std::string to_string( const T& src );
- µ¡Ç½¡§
- ʸ»úÎó¤ËÊÑ´¹¤¹¤ë¡£
- lexical_cast¤è¤ê¡Ê¤¿¤Ö¤ó¡Ë¹â®
+ 機能:
+ 文字列に変換する。
+ lexical_castより(たぶん)高速
*/
template<typename T>
inline std::string to_string( const T& src )
{
- // ½èÍý¤â¸«¤¿¤Þ¤Þ¤Ç¤¢¤ë
+ // 処理も見たままである
std::ostringstream oss;
oss << src;
template<typename T>
inline std::string to_str( const T& src )
{
- // ¤µ¤é¤Ë̾Á°¤òû½Ì¤¹¤ë
+ // さらに名前を短縮する
std::ostringstream oss;
oss << src;
<gintenlib/tribool.hpp>
- tribool ¡§ boost::logic::tribool ¤Ø¤Î using Àë¸À
+ tribool : boost::logic::tribool への using 宣言
- ¥³¥á¥ó¥È¡§
- ¡¦¥²¡¼¥à¥é¥¤¥Ö¥é¥ê¤Ç°ì¡¹ boost::logic::tribool ¤È¤¹¤ë¤Î¤¬ÌÌÅÝ¤Ê¤Î¤Ç using Àë¸À¡£
+ コメント:
+ ・ゲームライブラリで一々 boost::logic::tribool とするのが面倒なので using 宣言。
*/
<gintenlib/type.hpp>
- type ¡§ boost::type ¤Î using Àë¸À
+ type : boost::type の using 宣言
- Àë¸À¡§
+ 宣言:
using boost::type;
- µ¡Ç½¡§
- boost::type ¤Ø¤Î typedef ¤Ç¤¹¡£¼ç¤Ë¡Ö·¿¤Ø¤Î¥·¥ó¥Ü¥ë¡×¤È¤·¤Æµ¡Ç½¤·¤Þ¤¹¡£
- ¥Æ¥ó¥×¥ì¡¼¥È¤Ç¤Á¤ç¤Ã¤ÈÊ£»¨¤Ê¤³¤È¤ä¤í¤¦¤È¤¹¤ë¤ÈɬÍס£¤è¤¯»È¤¦¤Î¤Ç boost:: ¤ò»È¤ï¤º¤ËºÑ¤à¤è¤¦¡£
+ 機能:
+ boost::type への typedef です。主に「型へのシンボル」として機能します。
+ テンプレートでちょっと複雑なことやろうとすると必要。よく使うので boost:: を使わずに済むよう。
*/
<gintenlib/typed_saver.hpp>
- typed_saver ¡§ ¥Ç¥¹¥È¥é¥¯¥¿¤Ç¤ÎÃͤÎÉüµ¢¡Ê¥Æ¥ó¥×¥ì¡¼¥ÈÈÇ¡Ë
+ typed_saver : デストラクタでの値の復帰(テンプレート版)
- Àë¸À¡§
+ 宣言:
template< typename T >
class typed_saver : boost::noncopyable
{
public:
- // ÉáÄ̤Υ³¥ó¥¹¥È¥é¥¯¥¿
+ // æ\99®é\80\9aã\81®ã\82³ã\83³ã\82¹ã\83\88ã\83©ã\82¯ã\82¿
explicit typed_saver( T& t );
- // t ¤ÎÃͤòÂàÈò¤·¤Æ¤«¤é t1 ¤Ë½ñ¤´¹¤¨¤ë
+ // t の値を退避してから t1 に書き換える
typed_saver( T& t, const T& t1 );
~typed_saver();
- // ¤³¤ì¤ò¸Æ¤Ö¤È¡¢¥Ç¥¹¥È¥é¥¯¥¿¤ÇÃͤ¬Ìᤵ¤ì¤ë¤³¤È¤Ï¤Ê¤¯¤Ê¤ë
+ // これを呼ぶと、デストラクタで値が戻されることはなくなる
void release();
- // ÌÀ¼¨Åª¤ÊÉüµ¢¡ÊÄ̾ï¤Ï¥Ç¥¹¥È¥é¥¯¥¿¤ÇÉüµ¢¤µ¤ì¤ë¤Î¤Ç½ñ¤¯É¬Íפʤ·¡Ë
+ // 明示的な復帰(通常はデストラクタで復帰されるので書く必要なし)
void restore();
};
- µ¡Ç½¡§
- ¥³¥ó¥¹¥È¥é¥¯¥¿¤Ç¼õ¤±¼è¤Ã¤¿ÊÑ¿ô¤ÎÃͤòµÏ¿¤·¡¢¥Ç¥¹¥È¥é¥¯¥¿¤Ç½ñ¤Ìᤷ¤Þ¤¹¡£
- value_saver ¤È°ã¤¤ÊÑ¿ô¤Î·¿¤ò»ØÄꤹ¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¤¬¡¢¤½¤Îʬ¹â®¤ËÆ°ºî¤·¤Þ¤¹¡£
+ 機能:
+ コンストラクタで受け取った変数の値を記録し、デストラクタで書き戻します。
+ value_saver と違い変数の型を指定する必要がありますが、その分高速に動作します。
- ¥Ç¥¹¥È¥é¥¯¥¿Á°¤Ç¤â restore() ´Ø¿ô¤ò¸Æ¤Ó½Ð¤»¤Ð¡¢¶¯À©Åª¤Ë½ñ¤Ì᤹¤³¤È¤¬²Äǽ¤Ç¤¹¡£
- ¤½¤Î»þ¤Ï¥Ç¥¹¥È¥é¥¯¥¿¤Ç¤ÎÃͤνñ¤Ìᤷ¤Ï¹Ô¤ï¤ì¤Þ¤»¤ó¤Î¤ÇÃí°Õ¤·¤Æ¤¯¤À¤µ¤¤¡£
- ¤Þ¤¿¥Ç¥¹¥È¥é¥¯¥¿¤Ç¤Î½ñ¤Ìᤷ¤òÍÞÀ©¤·¤¿¤¤¤È¤¤Ï¡¢ release() ´Ø¿ô¤ò¸Æ¤Ó½Ð¤»¤Ð OK ¤Ç¤¹¡£
+ デストラクタ前でも restore() 関数を呼び出せば、強制的に書き戻すことが可能です。
+ その時はデストラクタでの値の書き戻しは行われませんので注意してください。
+ またデストラクタでの書き戻しを抑制したいときは、 release() 関数を呼び出せば OK です。
- Êä»ö¹à¡§
- typed_saver, value_saver ¤òÍøÍѤǤ¤ë¥ª¥Ö¥¸¥§¥¯¥È¤Î¾ò·ï¤Ï¡¢
- ¡Ö¥³¥Ô¡¼¥³¥ó¥¹¥È¥é¥¯¥¿¤«½ê͸¢°ÜÆ°¥³¥ó¥¹¥È¥é¥¯¥¿¤ò»ý¤Ã¤Æ¤¤¤ë¡×¡Ö swap ²Äǽ¡×¤ÎÆóÅÀ¤Ç¤¹¡£
- ¤Ê¤Î¤Ç¡¢¤Á¤ã¤ó¤È¤·¤¿ swap ¤µ¤¨¼ÂÁõ¤¹¤ì¤Ð std::auto_ptr Åù¤ÎÊѧ¥¯¥é¥¹¤Ç¤âÍøÍѤǤ¤Þ¤¹¡£
+ 補足事項:
+ typed_saver, value_saver を利用できるオブジェクトの条件は、
+ 「コピーコンストラクタか所有権移動コンストラクタを持っている」「 swap 可能」の二点です。
+ なので、ちゃんとした swap さえ実装すれば std::auto_ptr 等の変則クラスでも利用できます。
*/
namespace gintenlib
{
- // ¥³¥ó¥¹¥È¥é¥¯¥¿¤Î»þ¤ÎÃͤˡ¢¥Ç¥¹¥È¥é¥¯¥¿¤Ç¶¯À©Éüµ¢¤µ¤»¤ë¥ª¥Ö¥¸¥§¥¯¥È
+ // コンストラクタの時の値に、デストラクタで強制復帰させるオブジェクト
template< typename T >
class typed_saver
: boost::noncopyable
{
public:
- // t ¤ÎÃͤòµÏ¿¤·¡¢¥Ç¥¹¥È¥é¥¯¥¿¤Ç´¬¤Ì᤹
+ // t の値を記録し、デストラクタで巻き戻す
explicit typed_saver( T& t )
: target_( boost::addressof(t) ), saver_(t) {}
- // t ¤ÎÃͤòµÏ¿¤·¤Æ¤«¤é¡¢t1 ¤ËÊѹ¹¡¢¥Ç¥¹¥È¥é¥¯¥¿¤ÇÌ᤹
+ // t の値を記録してから、t1 に変更、デストラクタで戻す
typed_saver( T& t, const T& t1 )
: target_( boost::addressof(t) ), saver_(t)
{
}
- // Éüµ¢
+ // 復帰
~typed_saver()
{
restore();
}
- // Éüµ¢½èÍý¤ÎÍÞÀ©
+ // 復帰処理の抑制
void release()
{
target_ = 0;
}
- // ÌÀ¼¨Åª¤ÊÉüµ¢¡ÊÄ̾ï¤Ï¥Ç¥¹¥È¥é¥¯¥¿¤ÇÉüµ¢¤µ¤ì¤ë¤Î¤Ç½ñ¤¯É¬Íפʤ·¡Ë
+ // 明示的な復帰(通常はデストラクタで復帰されるので書く必要なし)
void restore()
{
if( target_ )
<gintenlib/value_saver.hpp>
- value_saver ¡§ ¥Ç¥¹¥È¥é¥¯¥¿¤Ç¤ÎÃͤÎÉüµ¢
+ value_saver : デストラクタでの値の復帰
- Àë¸À¡§
+ 宣言:
class value_saver : boost::noncopyable
{
public:
template< typename T > explicit value_saver( T& t );
- // t ¤ÎÃͤòÂàÈò¤·¤Æ¤«¤é t1 ¤Ë½ñ¤´¹¤¨¤ë
+ // t の値を退避してから t1 に書き換える
template< typename T > value_saver( T& t, const T& t1 );
~value_saver();
- // ¤È¤â¤Ë typed_saver ¤ÈƱ¤¸
+ // ともに typed_saver と同じ
void release();
void restore();
};
- µ¡Ç½¡§
- ¥³¥ó¥¹¥È¥é¥¯¥¿¤Ç¼õ¤±¼è¤Ã¤¿ÊÑ¿ô¤ÎÃͤòµÏ¿¤·¡¢¥Ç¥¹¥È¥é¥¯¥¿¤Ç½ñ¤Ìᤷ¤Þ¤¹¡£
- typed_saver ¤ÏÊÑ¿ô¤Î·¿¤ò»ØÄꤹ¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¤¬¹â®¤ËÆ°ºî¤·¡¢
- value_saver ¤ÏÊÑ¿ô¤Î·¿¤Ë°Í¤é¤Ê¤¤Æ°ºî¤ò¤·¤Þ¤¹¤¬Èæ³ÓŪÄ㮤Ǥ¹¡£
+ 機能:
+ コンストラクタで受け取った変数の値を記録し、デストラクタで書き戻します。
+ typed_saver は変数の型を指定する必要がありますが高速に動作し、
+ value_saver は変数の型に依らない動作をしますが比較的低速です。
- ¤É¤Á¤é¤â¡¢release() ´Ø¿ô¤ò¸Æ¤Ó½Ð¤¹¤³¤È¤Ç¥Ç¥¹¥È¥é¥¯¥¿¤Ç¤Î½ñ¤Ìᤷ¤òÍÞÀ©¤Ç¤¤Þ¤¹¡£
- ¤Þ¤¿¡¢¥Ç¥¹¥È¥é¥¯¥¿Á°¤Ç¤â restore() ´Ø¿ô¤Ë¤è¤ê¶¯À©Åª¤Ë½ñ¤Ì᤹¤³¤È¤¬²Äǽ¤Ç¤¹¡£
+ どちらも、release() 関数を呼び出すことでデストラクタでの書き戻しを抑制できます。
+ また、デストラクタ前でも restore() 関数により強制的に書き戻すことが可能です。
- Êä»ö¹à¡§
- typed_saver, value_saver ¤òÍøÍѤǤ¤ë¥ª¥Ö¥¸¥§¥¯¥È¤Î¾ò·ï¤Ï¡¢
- ¡Ö¥³¥Ô¡¼¥³¥ó¥¹¥È¥é¥¯¥¿¤«½ê͸¢°ÜÆ°¥³¥ó¥¹¥È¥é¥¯¥¿¤ò»ý¤Ã¤Æ¤¤¤ë¡×¡Ö swap ²Äǽ¡×¤ÎÆóÅÀ¤Ç¤¹¡£
- ¤Ê¤Î¤Ç¡¢¤Á¤ã¤ó¤È¤·¤¿ swap ¤µ¤¨¼ÂÁõ¤¹¤ì¤Ð std::auto_ptr Åù¤ÎÊѧ¥¯¥é¥¹¤Ç¤âÍøÍѤǤ¤Þ¤¹¡£
+ 補足事項:
+ typed_saver, value_saver を利用できるオブジェクトの条件は、
+ 「コピーコンストラクタか所有権移動コンストラクタを持っている」「 swap 可能」の二点です。
+ なので、ちゃんとした swap さえ実装すれば std::auto_ptr 等の変則クラスでも利用できます。
*/
namespace gintenlib
{
- // Ëüǽ¥»¡¼¥Ð
+ // 万能セーバ
class value_saver
: boost::noncopyable
{
public:
- // t ¤ÎÃͤòµÏ¿¤·¡¢¥Ç¥¹¥È¥é¥¯¥¿¤Ç´¬¤Ì᤹
+ // t の値を記録し、デストラクタで巻き戻す
template< typename T >
explicit value_saver( T& t )
: p( new holder<T>(t) ) {}
- // t ¤ÎÃͤòµÏ¿¤·¤Æ¤«¤é¡¢t1 ¤ËÊѹ¹¡¢¥Ç¥¹¥È¥é¥¯¥¿¤ÇÌ᤹
+ // t の値を記録してから、t1 に変更、デストラクタで戻す
template< typename T >
value_saver( T& t, const T& t1 )
: p( new holder<T>(t) )
}
- // Éüµ¢
+ // 復帰
~value_saver()
{
restore();
p.reset();
}
- // ÌÀ¼¨Åª¤ÊÉüµ¢¡ÊÄ̾ï¤Ï¥Ç¥¹¥È¥é¥¯¥¿¤ÇÉüµ¢¤µ¤ì¤ë¤Î¤Ç½ñ¤¯É¬Íפʤ·¡Ë
+ // 明示的な復帰(通常はデストラクタで復帰されるので書く必要なし)
void restore()
{
if(p)