From 80d9e8e4c1942fe810de1e772e6ca7aea680388e Mon Sep 17 00:00:00 2001 From: Joel de Guzman Date: Mon, 7 Jul 2003 14:20:34 +0000 Subject: [PATCH] Move from boost-sandbox [SVN r18959] --- doc/access.png | Bin 0 -> 11127 bytes doc/access2old.png | Bin 0 -> 42175 bytes doc/default.css | 188 ++ doc/facade-and-adaptor.rst | 1598 +++++++++++++++++ doc/iterator-categories.html | 822 +++++++++ doc/new-iter-concepts.rst | 731 ++++++++ doc/oldeqnew.png | Bin 0 -> 33786 bytes doc/traversal.png | Bin 0 -> 9112 bytes example/Jamfile | 1 + example/reverse_iterator.cpp | 16 + include/boost/iterator/detail/categories.hpp | 338 ++++ include/boost/iterator/detail/config_def.hpp | 104 ++ .../boost/iterator/detail/config_undef.hpp | 26 + include/boost/iterator/detail/enable_if.hpp | 88 + 14 files changed, 3912 insertions(+) create mode 100644 doc/access.png create mode 100644 doc/access2old.png create mode 100644 doc/default.css create mode 100644 doc/facade-and-adaptor.rst create mode 100644 doc/iterator-categories.html create mode 100644 doc/new-iter-concepts.rst create mode 100644 doc/oldeqnew.png create mode 100644 doc/traversal.png create mode 100644 example/Jamfile create mode 100644 example/reverse_iterator.cpp create mode 100644 include/boost/iterator/detail/categories.hpp create mode 100644 include/boost/iterator/detail/config_def.hpp create mode 100644 include/boost/iterator/detail/config_undef.hpp create mode 100644 include/boost/iterator/detail/enable_if.hpp diff --git a/doc/access.png b/doc/access.png new file mode 100644 index 0000000000000000000000000000000000000000..80011dcc7c82a35cbc173b314a9e247db0bf3f8c GIT binary patch literal 11127 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 literal 0 HcmV?d00001 diff --git a/doc/access2old.png b/doc/access2old.png new file mode 100644 index 0000000000000000000000000000000000000000..8a87b84fa565e7b2469926163a668804afd7d65e GIT binary patch literal 42175 zcmc$`c{G-78#j89ka;L`2uU&%GAAKqXfS6=QVEGdhRjJq%1|UzD51enrcfa%G$@(p zq0BO5*uT5?d%tged#%0K_s3pq-)p_^)AMw@-Pd`Y=W+a|-LJlWwJAIJLeHfANCBIrvHim>agMeE z`X$LpjW?1Pr(zZtWviEy4s~5;o*Lofm32GaJ+h#7@uN@kU$H4cO5!yW#eSwNv;GVQ zVm}kbGT8%{Ab#p#Ki>Cj)WQ4>BkBK#|Jq!GFAx{TF!`PT9NaKOA z$T8951_t?jf(MyQG=GqDjyE_yyK`q-d}D?GUwN@~V-YqsHjZ#r-}!5ej%!!zI}U8Q2AGE`I*ZnY`RwDOp*3(z|!> zSXfxxxsDz^df~zan_CSZKZdU{Qg8|wmuQ5)!25@XhAb>CSt8&3cz!w}EKD_U-P+cc zFQ$HOk+;E7#_zCjyttUy*|TTAyOiLidr~JhAne&@nXI9qp=h3cM^2pBUMCe8xS^jY zk)4xM_vUq)I14N5At9Eix4z4>J0rFFcjC7xk$#)p`t9DqK{We)*cV)@n3&k??CdoyfeL<_|6WvEZ`{r$O9O*nBWZz7QXEBZ+S)wcUf+hb{B&QH zd!I+v!-v9>hj9Dp_B)LJ5ujMU9Ue}3>eMN3i><+Q7euVEEBMnQ0_1jtkP*F;UFA83 zsgLsWe@#yE%Da3ovab^o67mkj`%_a>OI^D<+T&WrJQXkVFhtb#t@vJ|ZgVs4A?H;2 z?sCb~bH2Os%EZKkPo1|Nhp>diP*QGKtGC@H>fB*cRC?y;m z988~BzU7v2#CPlO??0Mj*j0Xc>ISFmia36@iuALQD=RD93a(l@I{JEgH~G}nl$7q) z_0jREt@gi-iei_X9I@k7^&RZ*Z~O6MOHar5@2fNQeArCRTQvvk!wMc83~=#OTALke zdhXQR*53Z9xmneF+D=ig;GpO52hQ!=Q|lra73Adnyi}+K^oacd8YfPizyexUct5SEsCfK%BAQzv$v}9O zJzASv&9AJaDix9U@Dk~S5_#>RF}&23K{ICW|$*CbPlPWjR=4uW4<`Dc5(nTg4T z_0{FZ#>TF$t{xWN;CWe3A)4hlg1E2Z!?Jz*c6RpDc6PmEV=ujD95!#>yncoO7yj$V z^NIGtfte+@!{KPEHFm zvyp*;=V!k@dU~=xKtF}LO}!;fWUwAzZaQsaRp;o@iv#bX2kK)!H8tt$>svi{IvjIs zW@bQV%a+JDZ{D~WY%>s+m6vC$E5geyPshR{*+BSSQc~wDFWQ8L_wR9&oKBzaDZdr>D)U{Fbv0#rr1T zuj}(mEaxe(seBc%wsP|(1NK;WcsTFAv7YhC$(uKC+Pw70?yY|H>Q(>1fS{ltEe%bA zq-~Y&!gx3LHU5lX98IR;7cW-V7JFJ-Tiv=VEXv%|6B84Qi@gGEj2+LOr75g=J211$ z=>GiN+{DB_(__a{)C1Ssvh}qDTHD*(ySmo6%XO${{ZU5g_~|GGckkYCaw2#(WUVi?EmKLV_VZ-i<@w<#ZHZ@J8SzJ_1QNBE>rKP3fzv4O5|F){C z%E`%TP4*nc*!K5q*G4ZWrl7oP>*(}U`TxWzXlgo#`~B?MvyAJzq@<>oW(Fw8gPMk( zndcW26uf``K0uBAgsp8LK8coHg0!y7%RW9n{sXO26wBJ9VhRF!TWLZ9bDVC4NXn;eEm8! zF;VU@^gd2d=TD$YgK_w?&253>6B8#-p3Kb5?5Vs`>ezS-`gVdS;*=#ZZjx zaYhDtT@k(*Ru-?_M;~4j72UZryZN31?kqN)j+WNw*x2EF^3Cn-m%rs(IA>X91wNQ# z(@o3#Jho-a7HolIqF?dCQop;wIc-`@h7R<;p}~&h&tPLb>dR?I$JZW8sfPSaT3j6) z^?^}6I7EJael6kwy0+X8ti)ufi_FCo6(b%#baHU$zq|JwD&ggs{)0L?^X`Ez^0iO1>b7iI?=lVwkv z9zVWQNJz}`g|4Ng<(Jkq+MWsRYPC~#cJAX}@;W*!-Q1>dvQT~~C@4^VB9$Z@nKVbl zW2c1G)zy`hRyvB$32NV%o}GQ))Wogo`yw}F#aCUcr_J zc~Gs`y*wNEgI3rYN*_IXL_hn$v@NT<` zcM&eP{^s_XnVFOCZdjnWp}1;oXP4nXxADtPNJuCulCrY0Vu?I<^e8JYuMJAqXiNHj z*$=HTN#guG3?u#h9w_Uq*AD;@)y{askUji8v%D>u=7u&J3Iw3gh3PQF06N zV`hk$>#YeH9UaZe5<;Dllq_@$y!wWy?{lY|Ew-{XG%)y3Lwb>Q_m|q&QF=!4&2FQt zdv|qyw@h-yna>YRGPT#%|4t1L5AWQ$6SwU|iOY{(!)@PV{Dj7j_KF9f#+nsaqX4vi z{%lobSA(5jW?hhb;6MO@=32XroqYpao>kaj`p+Lz6O+adA3nT)-%)lU^ZNDcxd$e8 zg-BXWn_F6HYiob|^5p~W`^Neju43(XY0sm_j}KxwACMLz2K5p(|qS9*|+i~wwbL3$i({JtJgdh+fJB?8ijOpcfbL*aVxql z$B!QmTwl%sY(Q%X4Slorck$xIi=}QoH;){Y4EHYSZEb1!UU@}fLp)%QX}(7368-+s zWwrygwPCbhzkE?qRRs!CYM3mWR6ZtJ{PgJsz}gH3N4qm;&P3w2-Mndd`0&Bh8#^|i zq6NwxoI_*$_fM=gV7HoEuTxazmBp2{cC7MA2ZyRxqVo4D(MgTgF8?e!Pft(3x>Js; zxu>UE@@DIn=+H(-VIiTVr6t_`5&TbFT%02u?a8I%#TbfzZ4%bXTi*-FH8L{NMgDJ3 ziGv->D~`WM0}FI3Q84wiv?%=OiSN%&=^r`5;-{bUxjolFE-!pH9Y z(gulC@YhN=&OLV4Hie#zE3&ZA4RtZ&V3fRDx8KnFZG3!ubakY%_T@`e#jxa!WfXIx z`zk^DcXWj)DJgxgT-j*SrZd)LKUqCCvMuj2J~=NhZ`uoY+}+*X(vr*X3c6NjXD3eQ zjFC}h>#<|U?%ut-b?eqw<>g`Dk`oey6=RRNxVZ408bZA*DUn~lg?FPPi0XGn0bAfslJ}e`bA%a&(Oizl(x=hm=&TnaAQ}7YgmttBQ&g17X%kE$l$^ zTBql`x9WL$72}nVz$WImICej_CH1;1ir!H=_5Lf@v^`nbafsVFV1*Z z;3^1IODc5c*M07)cURZf{(?UoJoxs-ix&V1uZNab7R~{d;wa&J`l4M{to>R%5mzN? zVPUZp!cI)r^96eQ`qqx{1IYCD_TpH7c7D;{?{MNo7a#Mn*`AViR?>h1*AX~Jn!P-&CMTUcODfFMP80eTvGDWhYtp3 zX6%N^_wHF)SYSo;h2t;(?s#jvB}`LVL1Aj>xueWJb@iTa-`Ely9UYUBlTSH0VULK4 zivBTQ$6n9Q&PG-CUR`>cp5FH+k~K}m2Xt%VANitA7iURv0~hr0corV6?eAat>Xk2A znXm6FRJh{ey&tF?WtP9>9YqyZ3uUxiITSD#7$mRJs}oS>kt>OJl8Hk5K(WRy?9~$%(3y|;d|5G zem*|?2!1s+n?r{H^>LR^SXn6x2#^y+Zar%H`c3FF<6~nubz}s?cBQQB>{G6;larHR zR=ljNn+W#{7f`BLlq3U!iw|mP8KfwZc9@Ng4M-E#eeIZ#3ScJ6ChE51Q}fj!Lqo&% zLR+_U=j!_0vFbLZuBq6yk00+L9)L|ZG&t7;Zw63B8^W)!<$WF*xg~{;XzA)Y@8B?- zw{s5r!ry-llc=GHScWg|2)Td65(-$iqi5h!9HR^(~soahwz zPS3HA_U(Ha8cIQ2#owWt#Ke56@R>Vy{P@p~4z-0Jg*I_j_Vm=%)05$#6OP|^@*N#F_dSc}PKWgM)vx@yq0W(Bj51Iob_xZ*egHR~j6i|p z;^K1W;UW*h#Vk$COiy2pG8{ckTC`KA7El)V?B3l~d4>HQXwB&}XMX(nvAb+lP(a|C zR>qSjzdK)EB(cNcVfnyyzmq2i_FWt%h|m&U_bPS?>)5zB3ji{dCm>qj=5n7oCw6vr z$Pt7FcvDu^;O*TgV9H&iBPoJ(&$jdvUt^E$?3g?fKKpn3D zh9O?}^z?lAaKkWX6M^fqtG(#q5q!vSlrpTYui!*EB|)n3qN1P?oSd8hXyH)`Qc_HY z)lSWKpIDX7QVE)KTUXleh^VWP%CD+gM?J+MlKL@){sU5_%C*>wk)mt7bL+C+sr5Egdu z(j|G~YNI16?CDdd{3lAg7b!>ML}ZeG4Gf%gbPTmOzj#qL*&tldVX~tb*urCB{40=2 zX(?(3PhHWWc;TVJK{1;Oh!^sE_B4I}z670t^yRl70ajMwb+fZ0)ra%vE5W?MDLOl? zzkk{p-^j?Ta#eOG6SX2w!NZ5)%}(deos$I3ako)H{R}QP5xI?e`8s_RBuYn!B}}{4 zHs;nXkncp$VU+)mINo4(DJeWEyz0=XKt@hf2l!*l;eb}qfH!mV@df_+F1>UC{bI@d zmt^F=UAuG)4L@QZ)JZ{~fVAeFa>Ch)XZ!X|n>LZiFvJpXUE?ChUZz(ZeTg3(WeTld zlE?(~P6(2^sKIS*x0;=3<@e!~r3J1BZG$YyN*#(XAuj%8Gc6kwFT8f|KE%%yDp7!v zwGxcKyVqQGapWdg>60htFI~EH<;oTOKe|a`B73;~R+=H~-^BR%kV5-fsE~bqeMv?1 zqWG%lYX$pIsBy8V!RU^)wHd|53oYpfK0iDh5|K4KH+RC?dMSiC|H+FN$22t^#@ezu z!oRk+56pNUKmOG=aLsF~yAqP-_rUhE>v|v!dqhPc9)<>d`~3MLj_yB|l+K3R1FK|Y zWTY7UtR|lK{=Kf-bA;54MiloeGkLvY$;ivw zQV04dY||LLnYNda4FV1j{?U!cWo2bgp3pNyn;9ExWFLXpMi4**sB;l%P+co3D^-ct zxCUG>R4adQB?v;i>H({Nep>+sbz9TX)7w^fV@uF`XKA|ItnR1z_6?PI_wFrMZi}($ zTUx$)`qac(NCk`icX4W@a>!i~`XZ3kP1ICXhwgMb;%Y>MjsI%U8a;v6O053=&r+e=YgHkh@t7wvO&u_VqyZ^8}qLO0c*%ZEn{Pg;Z;TT^_kN~ zkMHW*z8*X|K90kD*3FHI@VstOgubfez8&qBpBw* z1t#caU-I&*`ED24J3G>ItnftnyPqP%pVBtkZ3DNQkL&d#Bd8d7mX=4-{x$KAjt)?M z9P5tq%aUR*o;?fpw|*@x8#n(i8e=Kmu_xoHQTqV0xm=tF~`)52jNqexxJrouZtCxGfwI==sPh6ul-gl=8&f2mUhr`cb`TVfqX5p^?GQi zmgJsI#Dl6T-nydcX?KZ4<#XS}WRmG5<$sTkeh1jX$8`MsSv_$5iw=Io!@~ojdoL%X zg)qRa)1U4yudFz5BqS!H8p2VKrn@rJABIzrpD%VtkF*?82BVY*(~WU2r0CAMxor$3 z+Cqp7sq3@b1W-EWxe~gC)!^`9kP<(C|7FQQCQI%OOL{Xe9)?}$35ETY;PfD@zAn2f zj+>31&d$n$Mkq~J4sn$)aCOJ--Hqi{8l$95v8+I|Wa%75F%o6Z;g+7Nc)4Kj^$#G9d$wylh<>x0Pe7>tfzfF-jbv-C(KcF~lnO_|Ao*4$m)21g1t4U&X zwd4F~>vX+~t}Zo0gzVnEU(pBZ&7VJijsoCv{(R2idnM<8%J1D4dDR|IZ!qeY?CgDSs%-J6pZ@F+KzAYyg1AUhp1GeZ%beR%uU zEr+M(o=V&A)5*!m+*Q6Tp~AKiCJlDj9h2Jqa~3)*kO1~Hzz%4xMB*Ov*=;>8e9K=P zC`cbg&n-_7z4xgfQt;Cu z{~fZjtaU}VZ*N^HdHk5Ru1I}jm9>g~%a%T`tsoNP0|T1~pjl`?Q8#XEeYKxCQtR^N z%jmqoSb>3o3=yAOTCUa)ytH<`e7Q6vBqTUE7&3Kg>UNb&p9EjXvqav$dzWTclA6C# zr$~uwm#DC?lbv0W!&@33pJm?aVt7Aj`E&%+$`5Rle)lr)(oZS-o}-GtqpTL=cUhiu zdsM-zasIq`=No|9Q9qpfCyyRk9zFUTL=l2+$B!R4&XBI^zJ9%3sGq$s$uZy;+)r&PE-|5_6UFxpQ#E zCZ8S!AD@_f_&a3U0MB5E}N4fTM zsOL)5Qq8$Rf+(tIB!YmYJ36&V46Gnd zH*0?0lQN{Qzh7X-j@Gs|7!7B^x9rXJ^=WyY4MU5o*q?QRRRtQBjO>fq6ZIpfB!7ShCo3sDJ^YpZ9R1O@L^ru zGT()>P?CIoeO+9{!tJG{r6DZv^YbeyS=!iC<>peui4}2nb7Q2Xy|T8l*I-+0SlDJi z&xh638{zcab|o+>4`^s;K!3EfynByE*T3$+S%7=osfM;CE+l>j6oc&oRmH~I`h(MR z$bfTwbyRe9=seK8oaHQab+6sNeQf`JGQDjZZ134@&!D!U=&tUJi;F9gB{LD(s<^s0 zOcSkXVRp9P<0Y{55!HC-4#KD>FQ9OI*jOfwTw%a^mK0Wj9thuu(GT1=b@)M{!Z$KfpA@Gv^QxR_O|>Dk55cgIMXJyzEK;*WtML~ z1DOFz6K)J$9Stq*ojZ3R^`hAJCH0{ZvGQ2015s7j+Er9l_0H{ylMMan5g3i`MtbA) z88^4Y+qVY~Yor^ax;}aMP&?fid&I8vF1~Vda%5Cge4}Ic05r;qeWyS2a7CM1TGB)e zNQ#QW5g$~gB>t2$J2EZ(3a@i`>MX~#p#ygjHO#cYy0JRZNLP3C=|luK*Q#4UKmf`H z%K3&4#PiKMuMe(o`%=2Z1^5$ly^^jj_t<#KzKc?Hg7J;0BOE>7XMx@EzUc_d|CuIGgZ7A1B>%WjsFsZuK-`NJc5*mQ7H!Bati!VZX(mX@A7b7uFRJqgYVqCIumtY=9fs zeK9&VaC0>4*B&G|uyCaE1AjmuuAy8CC`L|RzBb~~ERJeJLj(A>iPm-gjQu&E!F40G z9AbXnfhdFkLd?ZpSVu1MRzL?RNdRdePpdKGXPupmO-+XbzcJlwc6$C})A$7&bsA5h zN7XaDK?<&&it8Rc4DEu)!Qdd+#iZ|OxT?X=)Vr^OH`J8@HWMRG#Fz2(fk`mZ9{C$`K zJ|lE-J4S)|(O$&ZqMDuN*8h0h+u2EJNYrSYY+7XW6gn${KC&{Flh%8(+B*!)3JnpE z2Zr75jY^XSCTQ;$pr?SsE>)a^s8ZM0YjP9~9@6gQBvLuY*PD`K_cNY~+VLnoz2?V{ zm(ZhY>|V2=?Ik5~)ZAB=aU>&nRlMD&d-uyEcXoBr*Y6<(5OQ)(dwVOc9FqR>VCu>> za2P1;FC!wTRJwM7*h)%HVV8}LdIMLktoWKxUAx9>y{ETN*gNknIuYU<0s;cYk2r!` z%+x#&>FUBRR}&J_0yl)e_VJ^Hs%lqHkGibvXNYp|-VMW6h18qDz{(ti;6+P|v7lfk zfDs25mxSeu-12fOZSCRjPfvoO!IZq_{6NrzT08p)U`Tm+IgDVcaxUOZv^TIO)Jzy> z)@AN}V3OD(THANGjXZn)93}*`KKuwk9!cV+3`vI_@9@;&pzGeLk-V%QQufU?#KH9x7TChbsR&PLo$6lm`maiTe7@9q zP`BFdcaWZ2&wS$3mrUIffR#jR#-^IuppFZoJViS=Q3($L5JEzt;OW!W=H~Ob1}Fyu ze5c4bui}?L>3njcoNc?UW)%~XTbGSZOvpZKLurhPYQoiGbAkfE$(`MpQDWs&4?qfH zZf1tLBUvNX2#dCS|LnPQ19fgWbdh+CR z_dZQCvvy`d?Q2Q}HE0bH5fODCDJnihDoCjX`|ZUl2ed)pMDNFs0GT^EmDtq;qt!h| z_rs5bXlKHN$4_N`q-bNuTCV&gX{KG}xD9D3Dfu9VZd=>i+E~1-)up~9YpjqVgV8Yk zj{T+A1RIa7BNootFHSN-iB&fcnKfor#VTD0v7j(qwuAbyjf2oC-`3ZYKHUwUP8rKP z5cT>+&^z|N{i$2DLP`HA7o5Voo-d@v9PThSTK`YEfTy(3|q1=S;DIpvW0U;2j1aUr=NG*OQq@keeRTY$gl;A$5Z)AKPgF2&X`00qq zR?#~h?CgK2wZUxSK~Ze$-@e^UMFsR&Q#$e~4biOad(Up&n3v-^eDGj)Uf!Yo`_oZ9 zMy;V5K-Ijm6-oigGD|d_kG*~S%eQauY}>wlb8>ToWe6+#)albBzkmCqXqp#1dbBdM zH_-kAiUUx&`|%p74{#5_1U8;AH^k7ZmN|{SZ*1JbL=989;ubPzsQk6~cAsYY>ow|ddr)yl8N{mE-@KuSs58m?f~X37 zOBJ74Eh8gF(+2g*-ioD#+$ZQE85x>rVt_K}V6vw_{@Tf+YigR%>~xZYl30RB2ZtIa zzck%|yCP(E?C6|UXGn2Cu~5Zev5nu_sV}s1XI*VA9J;yjuX~W8sVM=vxp;97&E&Y5 z8M@L~Hmu!U!)D&Esb#-(oj95V@C^(JJFK~t!0Y>Zqifld=sUkw|AaGxJF z5r`{;(|zX57%Uz#!dxsNJ9`KhiNg_EKhV_FL`EQnqNk?^3k;14WrUfTnYaqg9||NW z)lnlONf8lh!hN)52ec=EaZtJo7iQ2BiK|gj`p1slZt_zqB;cLefe~z92WmRiq5z>0Wr*i5dnvq813W_nOgnR?{iKuAaBuJQa5MLMEi`y&X~OZlJ$FNVk4Du-3KWVE zc#DaNi7m%P3kyz$2oRxAH^kwfg<+XOONK^UGl5@_O5ld)n|CxPG=X1TfOJk78Dn7h zmZ9MS*(fQoP>14b2?9$zzpzmL>J>piO9RQGB;Y;PsKWCBalk#GqdfT~*94LsaTPu% zWUI6^qnytG2w<>8FB(5Wu$zf8;K)i@!mjI;7la6cfNFi~7EAhEKeOdMcpdldaYxjV z5ePqtC@Pve3#~4MhKJWyKn%DW7k6RgV=96<_-k=-$rGe1>|@?j}-+ZB|vPq zbHIZ0Fu)DoOAt6|CMG~6fR0HjJ~BivdMl2w`^w&P-(0$0-BIVL>G%uaBik0$+qt)jhd0N8o56(F%I|{MoY` z(a|`>$^bgvAG8h~+7eUG&B5V$`7$s&;v27krWF*}c~y4&pSmyiUIAzQ*M0eacQW$l z{-=#$neorY(ENEnK0XuRzppRIJ_(XOSQctZvO!5vk@NZUs-B}QFV1}K?MsEf2t>4Q zM{#bCxcHraDZ<_1_Mo2LDmEw&5T4O|3W2x7?NJF;Z$7c-a5{N%Q;b?yb>Id(`-{UL zV4r9Ii;in19zhT$Qi}@;v$Y=H4psngxPB|C(eW7=P)Nw8aC@{fY?T;gUCq`$oT<()qT3J9@yR8%}bE-x1M8dcvDs2MnGHEAs7q+fB(R(k#my(w?fDl zKHNJHxzLYM>bf-@FmG{c`*tw1ML`?y`u<%+jwRs#!4psw5~3hlzJA3IeC_ULAVz=v zx*Z#fRL_A67o=Stwv?nnmc`*OnyszXM30`FgzC45{f~e#h@8ptw4`HtF;3{qva;7( zz+u6fuuY`t9_Qr+g+W7u9l9!Ri68>JJRdi=u2p(3t1a6;@QOSKYt=Wf8nJy zA|=%u>)eE~mDM>ryJ;YtmX?;ZfR!zTM$Tu*pS}C8;@=wE+Y{^hzO=VvlT%Sr%FD_1 zx|fkcDiBnzmX$3*bB0t8wY~UaxoQC*b<^LCg_Wv*dymbr-0xN#?Fw>1J zos&n890_OS1GubvYyn1m;6O;DBRSE#+jFV##tk}ue}6&)QFe&1WQ69=$-X}O)2FEj zG_8wXUST>XVWtA};xnMA*-ru`CP4I1xl6I-3G!SU$j-P2qcx)Pw>itfX#`FnCnmcq zA(w|~_PNDHMm7Qk_f6m$Y#u_(bA)h(6@}se`s4nxbA0?PIvpUjZ<0q zRFs?y%lJpBTN=0rqP`v;uP*(zL{I_}0iqWmIzjaVkYx@D#A)B;Ib&yMcj{DF{XpQ# z*e(l;AEBY4*g=qSSR#c41!XalfTQBT0o8>C0fKs`@4DwU$lb_Ho*u0jna9%5&9KXEAWPekdC9{miXC{f}BlK9^{ zJ6*tr&$ML$8{OEhY>L>+!GlBKX44PogEN4guw9S0Ara25FswC5y)hxhMy16OTMY%8o@=VD@#3Rv~ViH6T} z?%dxn>5-8UeF!-d6N{w1EaSg2kCZZ81FuV$Ceaq)QUvd`EeRLc#K5(ShPfZPLKG{& zE;w{W$nnW5DAY}8-Mf3YciS3H6=W(Pk=4?}xIr=7mDwWdAPT_Qf*na$$3drk@#6D` z4~G*!M5VQKP;7}FW4;D3^k*!{tcj&Q7M|8`Uzl+3&x_|ho4$1wYd!ubxzlP6`t6M)As)Z<^T z3oyW=!n}Wl9Q2bv?%usCbHj&`%W=!gS~PiIozgP%(Di+#15yG4dp?*#tM9Yb@34LOab?NgdlvnvYmt{WWE8Hu{u(Oigv zX65E4B_zn(*HW0Dx3}NH8xs+thS?f00qNuqgM%aq6>^A|*MgeO_Xguogs1sy%Fp;T zC5ZF#@{-(A7+i?OVizEVO=8NRfT#(RKc3gu*HhIMVao$p)P8#R<_!>zshJtvcA(k1 z)@?q2rh2MT#z{_!`O|*f9FA}>O-ZYg511o>mV`nLEXom%kT`S`d;k(=0M8jZCEwBZ zuoaf49OYpfv9hA*kEz~513*q;X?a=Ie+42EbZlnQP*R}i9UAp#_I2SvYe3}>v$J8e zD5ZAqYGUV{#ca>A^oM&2g~(}C3(3f^ToUG|3G46cBO@@+g+2i~Z!N(dQHQ$FiPI>3IZ-0PSR@FE9CP>)W**V{`_$;!26=&7`mQdtnWo6&Kd4mL~$X1#Z8{l&Z z2}5gZOvXGeF22*~h+NDJGzFY3=qy;H;p&|9+}u%APYC&gG1cHIgp}|6==AiojX*M{ zGXTU2Y^!hDbMVH*L`7Y^a3TFj-n5{#M511{rMWrWu>z~oN#LclS6$opS21Jb#qE>Gz_|DAtBk|I14?W=n)xG={faf9?Jy+ zr43qEJzTxMat=Tc4h+^AC=uD?2zI(44ezy;Vwki%+Sx@##y}g#k3%H=+R#9qO_Mc+ zko+ovE@ftF`pz~ZE9;GV!PYQMPI!TL?{sdT?WPMBV*8O7O>I*$C}S zq&vX`95|37J!WCic;zF73g>I|awLHfjs`eF0YWk?q(($kG&qM70;!=PL!_1xY8q^s zJ{|PFUK3%Poi6g+YRfmxbaOr*&?LQlW003E$gnMlB}pEVvRyfwkOp{|sN1VCH2ua4a%N&vDqw#4fe1__5)UxH zB_`$quEP-y_KgJIe9beR*o}~9n`bv+(&6`z!_j}Y88LXIZh6*})zxheAI4aw3wd0)_1k%PR%C~#f}5Rkva<4RD(^NsUA}awf5zKHCzQ?$ZX=yD z^hBH%;BE=DDJi;`ddL>u92g)(V@6cb`lUzMM&pB!cR21iIj2EmmyS8A@EY+m4Gs<6 zxqTa@c(3ogGb1CT_sgxp^N^8Z`QV}L+&P3q)K;48@^bE*_vKK>->phz*d11LjBLFi?YY zzc7C1#S3hsoIZcbko&OCQc|q7wJGm4BY$sBw%wcn6@6?qIXhS=!nbm|m}6_PCL7%c(Fz_<*j zD25O)p#UF}o_;R|#b#!trKCjm>?ucx17u5z4wC}c0hvMBeXEbU8FwIK1R#`bFpNC{ zCe6yia$n8AqoqX(d>08f_y)(mkO_qFDK$mYZAI|{>&91s{A^QxN&ExTDi05j;eC}e zj*ddtM=3*5p&w>tbyi+UG@C`p5pFG#E(q1)U?ZL#DW&4*4xqsN^glzp5YV6haKW4s z8ac#WYC}`J$DSij_tzppl>qex5#H+h-L8}&7ofo6v*F=TP*Q$G@pDgG)zN~$tmO!7 zR9jaEdO}hlam=YN2{Wa`(GtP^H2*l{0eSl7c4h6%R&sK3jQ>e^%1|sT0oAPird4Kb zFw-|OQb+&5@Ca@+aL-2cCs7?H>eM0a6(dyj(o%&uU9@hxEn5&tJ*=TY=xysst*l%_ z^kNRE==yaU#K2&+*9~}6&x(_zWorbi;M1Zl#>B*=r`rQHVQ#wRLQd7goSe(hgwR~j zm*J{oD|csBFc0p5v!TnUd0LqA8uC2Xu3ZD;is4p}kdkWo@q;s!QfHlHBuoLOsfvn@ zBhfPY;my@H*b2zBz?_5qhV{MT>pQFdgl)fX1PYldQttPaFEe-vQ$X*XyT>13?_yB1Fi43tgf7((SEcU1@}jCLz|QUgM)qa(xjcV zh*d@*!tBG$!or>Scvdg1YonNj@}nF#ptFD(0woih9{{|o!bjHEvWF?+qlaMajO%Ng z;7kvA(43Rnf^O_%razIbs51(ASmGl5RVp`!9X=;_TMS$kN8QK=a9^`+7oKl`;Fec&`3n{I>&KkPvfQ1YJU-;l#4AWbwHVMkFN zg}Doe>AdmhA+JGvSYwKL07Dc*neDG%YY1H&c?l`i%q%f2jW67uxcZ+S0hGsBC#94M zdikd(;O}{ecokzv>W&T%KP)W#L^1;mTtGsQsE8?C$2LZ=XW`GEN!9zX65!!N*ADy{ zE1AD>WuMphZRjnao`r*?IAGw0+J+odzf|dy+UgXaPkui6)SO%1WmFoWbpwp^s8a~$ z@?FweYb}NFP8!<+IgZp4h|{GYuW4%9gZ4Xdb`KhVV6oxQ!6_ zgABiMeos}!`V=5}R(<0E< zS)gSRl^0R723t_Jmsb{DmtFxiqF>9(#xL5kMJ=F{U<3{to(*Z-2Z50N`)klF*N{iI z#{$642ONV=OGY53g@_ck=DxsnmBL!2;aq^DkIwZcBf>`F1o{Zec7FLnVO#wld&1eJ zVg-{y4R%s?_-jTaX{kx!cno8`M1n8S%J<9|APuN9obZf{49IHUM~4Ro-@JVbD0?_f zO?BtauS=hqNI=yEA!H!M28mH<5C?*BtH!gQL+=CR$tH(2y;^8Z$S0_ug5=oKPo8WhJ7u z%kfLGb)j;!2(EwoW-5`WpM6Bqy6koJZQp!G^n9R4YY8){+JF))Db5f@81XS1X^^I;jCg?eZREj+n>=^LCTOg zD8{U;pF28eXp;?`prhma;cmvPQ4$&uY~_onMDK91v0cJE*-}EF4_ZbkDYy@r9+Sa+ z6eu7dS(=&sw#^!a_jq5Rf?}w8y8F*}bKftv@GsKR7;{3c_~IKW$jcw{-lGet0q1!I zBiPMq@|4b(%PWFbr0ntkU)~Cmc!v7=1Cq(`yWj=)PGAG4?YpS$>{7IjAUL)xThwO4 z*~R6}zzm))(dhUQVZnFroG`Er0sw7$pwQO&JdhLa%86%=k=fZh!Nw;Z7Zw&mP{roQ zhXiT#KKT}l$s`y4YMe35slk|p%6WrZVG_y-a42*dM1GO|tzMmtiiu$)dLdD9gx55G z`uuqgBBW;KT}+MRyy2M~5O=}?*i}Qr!r&pzc55Fzc=*1G1)h5VM<;jzNg_KAM9a63 zHnZ9B<4+0-0?^`-g~Fgwq*g{;oXP3ay8>4|mAXED#3-c~22Jtogsb~$3K(%n;LWF* z@A-S&*ti94{a>IO2mpj0Cz*=CxXuA1qnM_lS;-8b0#qUd>Nq(#lJ4EJEx&YlG!fe` z11Y=VVa%I@JI=4KT`9W;MQLhJH!c+Acv(L*U^Dg%Py)K+^QfpOuqWcG*#;cjVoWK@Dy3TXqa4@Zq}@&#&Qj+`Y?1^x~i(L>HV10fGT%X-Va(GPm~QolH;y&bLUIC?rB|DpFvs9qPR=d@anxdb=4gdC z6n>ODcwkGkiDDMdFn*_43F;bA$9yB&Yy)ucq`f`a26&1iNhwzJ7}T}1;}^5WkQ?gL z@&tQ+bkmTih{$VAhKLY*a}3F0V_`nqj<*9B4xYZe$6ks9`J$Nmrj2&YR9J{56cm6T z;C3|)pKW#K!k?7yOgzqsi`R>W=ye3N=hQAX#f02+Svg>jhEI1EmNA)+_uGM zzaoF`?Y6eIhF>-6`KrYfhUb8L8CLe+AQRN3PeUHywsxm){&xZhk3reK9bzc`p2!68s1o88>dP=?e4I0ZrAAVIh#-zdLEnvE(U%|=ywhq`W6 z&&G>b3X2A71F3M^%7?J53evPh}7%UbnX|LSvs6#N0#Y^V5uhJ4x;;E9=0MaTHW^ z8}Jl}7w(@wHZ1JpGA{F6J%TOWPOfEnNTC zz!b-?(pp&xJTK|i?c3IszI(&%fq8KV>ZM$O!vI;qHVSZ#-oKZTmsbOAL8U=em!^ZE zP&+V#dx|6vP9n%80txS%o4bn7v8S{`4eB+(w`YieMT46StQWv+%Ka{szKG=izp3#8l4RjOushTjH&+ z+2MZMSX}O)hT(P3prgl%w3sus-q;nL%Xr7MMLOZlVh-iG8+Nq8dXaGyVOKMb9XvLv zwUw5d`r7Tx#_c*I?^oB86#lwSn!cuKU0$ylx%AzC7-QwbKax}Z@$eU@8(>AOLrr=J zN@cb><9pXi-N1oBbbEBvh4hegg zA2{ghFiHV)_xg1`SJ#5->S{O|;r38=v0}JNj6sB(mI0GaRsA)zu~|QOs`J??T8w0$ zr)^`~zylm2zy3vVqPD^F*=*jiN6E<+7~$3uX#Dsw0Qxef9855#3eA?67f)M)_yP$H zZO45L@&+&uv^Y{e%;kp+B97_Cx@Q@WFa}Z4qRyrpdylp4#2;X>RaB^`rKKe%)(?3= zqr9>9{5nqcJe=qeoN^9}>}^}OqJY;u5h(J9Zi8n<#m6754#$%ya9P)OKRbNYJ_$8F zl64n;BepYsDWuWcj5}W!gxYf;0*0`~p?f!y!t$XCJcp1Bz;==Yn(=8D7i$v};EN+D z3zB%WL2O%mvy-I7Ge?YdOdCUN0MF|2U+lWv<4?6nj*-F&hMAQwZEe67AP>DLQ%Jph z$5_?s(hPKlMT4=NaKJC zE`K&sr)OXgE~fJ1=Soto5_S8^PDTK9OViassv*>t2U)$JXCf?}*#gsC&s(J%B2^%s z*#V9^I5Gk`Z4-fl6>c<-VJl2Z{WJA#UpSk<$AUqG5|2n9q~S47rTb0ju~VHdS^4FT`T|&-|}_18E!Cyo&%N z5Of}!K2dV-y$W|rS7^NahU8h=-4x{TrGiS25m)cu=f!teat=MFCKrkRji-7b&PPuC zM~E=YSHc$h!bgDPCnqH-Uissq*ce+(l_WXVR#T3NoEo6V#zv@&v;>~_a}rw)Ujffj znf@e-+|+|sSm@_r{uTx3?)i;s2*WR^mQU5!(bZLgCDLx&!g+7vDmae~p5>!=AWvA= zzyMji!+LtY=&vyTs+Rg`(Z)ZG%z<6^c_923hiP0ykj}*S)gH=bHZw#qhq3~JGsvg~ z>=n9YmK@SDJ30sg(O5i9V92A-9*hT+R5#y^$#$EFECe53Y5#&LbVXa-B#lIjSzJo0aT@W!O zFiU@b)jN7&v^qV0bJ0-XU~)soj@Cxhi7o0a)Pu052PlWZ&ozHkToZly>J={@mp0<| zARW<%cGx8le+&~2d4Vw6iB#0(cC|;_PhjW;`G4jaf9f z1Ib%OD6@u!N7~^HQaCH(f@iE6O1z;%0oDdII6cRf_$#uP=>0oYjp*syW`AV(kTYkA z%mR&RzPs1`07XF{;98RONjq-vPj6q}TOFIEd-m_bqwaA0agL^os;X@E@3%)%V0z0g zldnj1AcjI{Ab6#S)1EIWjs*ZPVhYnAPS9qwx+JGb>DI%vT*aP=~nQ z;-5bS7SFZMc8>o3jTxESmdh^Z&Y>s32PUp!`EVFskJP<+h&ANIn2R6fzO!F)u{AVz zebM10Bi1gdHUL$i*hllRDAVTo5wCHz)+bJ+8wqT`du;{50*JXaJy;f!Ayb_?|9j?J z7D`tER3?IGD~T15lk-FpaLL}>oFjnUK$MTPlMiRMLJXiYx-#7x1nz;m0B;-v z9-*4)x7Q7X5t+kNpPDc;t=1o3Oyy7&@)2q$3i{hb+&)nZeT%;3B8Xl(KKPX*xdQ5nqYM)dTfv3axkUsk=AntB4dHK`~) zo3&p-;Xs?8e&YL#)YKr90Dpk0KwSkf&=a~9pgi_-;DpN1WC*Sd{@_w56&@WJ`DqK{5{TNniYEY)4)7T?G8h zGuV$?V#sdnh*eLxf(F`m?@`lqW9rKf`Y{-**eBd}IeuYBv@TS2$o$i(qnn^$efQgzSBhWZS1gS!edB#~bYW!i8Z%`cn zoxD}O!3xvhctf|zo7qKZ6;PYN8-eDa@c|JbPd}$bzLO==Tr7Mlih&8w1=@wzBBRj; z@W!FdRI2X1ugkYoi*lQC&DhlTxnocOg1f4U%Jds>#(7AHKTBigS&mq}^%8vGcdh2XwJ z+Id+y>Wlcl-vk5>KP@c6rd~=6%~DQot2UkB!EdG)Y)1Z)9}v~sh}d-3s)7PC%Gb}I zF}o(FlA_}CEGVc3o7~^eFI2M+iZ62Rs1ALJfl#PWv9R}`ah-<8a&iwD0YwaY))Y#h ztE&y3j)14A0g+vNX^on|8$(JT0tA3YE3V^-AeaUPTSpcd4@^4a>}(B=04v))QMEe{ zd7_2+dD7Trc2T}5zN@EFWlj!h(+IJ6$9qE$f{=kSNKRmo=Al8dX7-V$_wRd^v%z%m zcq+VL9(Q)CC@7GgZinwnQoD^sNKa>+@dp3*H;cZ?AqOZL^)|Thk^_e@TNE^oU&F(c zn?z8&p^uQ_BRx2C&rfH#!UK>kYV`Yf|T&nUpj*S zS8Hz`kki`s{V$Y~BqSjkOhw38NK#29Bq2(Z%u%K-sWfPkp^!{T6haydg)}E5QZhw@ zahuCnN&P-6`@Y}zdGF`<{PVv3vA1nk*LAIRuJb&O?{w%Y-(imdW{xYpY&Xm+X)_ch z3sNZvBo&ocRmLWq=F{iT-vpM?svpX`c@sljVrJ%%qE|F9GJ*8Nv**lth2&}3vXCyG z<~UUFDOc-sBmrgG{n~&R(bpc=xt)ZEnmpO>TlYhN9Rv5=bWQa3X~<7B>A8;DFg3L{-^61CDkC~t)VUAno#N2HYnN5ui+vm% zrA^+p$Qx8X-*WrN#EN$@^8NBYAd6Ni@izrg?wh@dur4Y@^&Jz3^>N>Xplnvx7u$(;f}N3P3q(~dBY2Yn8|-ZyH;`DlC>ix^jNH|odTgz<8R zis@9(BFWWL9_wmD+jMqrzWXh-2kH^{UxyGiSmBm+&8uPL_V!2-EqeX#-8uHDo6Yk4 zti72ZV~Uqd(A8B^QlbQ<)BOkleD`irO3Ir2kS-jK#^<+o`8C2nvGnaXoqBJ-*q-q% zM#84B7OQ#le!jff&3PN;kLhvx&>y~0Fq16MxEnW2)31i+)zqU_%6Q~Dc71zf z5I$YnfVG@}zXEdNwDEBE^2#_nH@Uab8{^~mIDzR+*cwoq@ibGFql3h)3fLo57Y)xE zJ!%x9+}+2IFCxkSt&p{9zkYduCLB$9+DcXJH--K5_4%msWH5oRV^&y0;LsM}VWiAm zQ|NnWF#&0mDqM?O3#_SecNGTQE!CEtHhnsJozb6`z%|W?(ckfFaQy+PV*?@6t#%b+ ziXgwO!xp+|Te_s1H{a3@hyg62D&F5_(UC&tu=-EJC9)W#+t%7(H&akM7C`XOl7;-_uvZW=HO`Pj?`t-Y;04bK0S-chO^+1dLzz{)f^I!tz z#puA%xI=7E^n*W+9(}*C@J;c9rmWB$yY|24sVT^S_ObgSP%n1WMxu!hQ4n|#Kz?{y zA#pJe@V==CAH7Ija|ulbYPhdr4;8eYK3_Cac^;*%RquW9koAy+pbb++^XuIlG)+gOI!SW zol7#6>0G$v+{B;>l4{N=>Fnn$Z~a9cT_By=eo*`5A6lay(>bjXT`u7tP*k&MQ4+hv^O^b0aCy&H*i^A&&a<|L$If0{>Q_eX&B?jqzJ_cbXa(}ixEa-7 z8>np92UI@vQjplx@lRFc8P(g5-uHJvMuFuUbZu6L=E#Tq?3*z4Q%J0^Ahg#zQdqGk zh!{;kqIBE3oiG`rwYBj}9{A8tB45@2wW3ikz#=$7YIZ8SoClJA9#aXa{`u`2|LlB8 zJ!Fe-MnU*M)Qjfv&PqRUNy%LrCY?XwIV!b!hy0Q@o5IwlyST)$d%L+2oc!7Gy}v;Q zW)2zdF2NrwRx~;;3g|pNJWc5e%73=9+$zrZ+CJkYp8tLgXhLbA6trRE#=LN;5Vf{n z6pf-_WjQzqF5?R_x9|A%%aX?!s#Xr;)}U4lbUIYvJVJKZgh%FT%^k%b5XFkZZ{SqK zh}W+}rN~{flFqk^BCTtV@If98kfK$BBw-1cuFd zbU`|Qvl%-uWi&C`G-rG?7P`0%P@X<|r2FW!nzk&zp@@eRZ@Q8!=|+B^*P7}`00XwoD?ti@XL$&l z-U(2}UOUE~I;|$}Mhc5ueTZD1w#=(7M%_mA84+^ya)G?$E}L_wPMLZ|^u8>U|Lazm zUE8(YjU-+U4H|D%Nr|o6UQ+zCSXZ-lxT<|9wN08jjQp1tKsw)&GcZ<8ti+u)SQM60 z;xZheU{L9NDj-9$t)G&Ns@sVBlf~aAE6M$Sr|QP<4QhMCR(3;m+E+)}rL0;dt?;z^ z9=<1f@LNhIS3Y;(wf^0{IFdbbM64V#U& z?0cMj5oGP&qRYrQcp4-bs(kot|EN7JCwzmvh5S~nB#Cf%tM#jD3Q-Wxj==o(VG zwU=wt0s{-)zx*;@%onHnP3jkW^r-5@iG7-9n40RsV~bpvlZ(qsSo*2kl_u-Ksn5aD zPaYPZs(;srTNxx>V8l9;;0Z*;SrIj~Ap2F8=F!-$vw`N~;4Pd}fU2qTVfpS?R_^@0 za8drKI<@DK)A!o6q<(Qwe5@wgb+2DXqjrQiO=cuKxlHOE@9Nf#zw+ko{bGWAv%I84 z^@Q$(32u*5C7XRHFYN4|(sb3epbbM0N!T+LkHSozYSK4=r*r6i$XMvm4YZ0hU22k{ zT|)%{yaG^*PL>3ObTM)O^>6c(O*LM``BO=#oq&$hAvvIm>Vw86?n=!U3J5AUCtSiy zHg41r4AdiNa3-Qbwb`d{PAY;Zj0KR!^T2DIb-lT<|9c3OfW<PbV-72Ns8cS;CXx zo75@zdr)9FN0gP7)#Y&t<+fy=8ccWzLOjXY{QI%%*d}6g4}u!ET5bp0c1SHntH*&{ zR$A)Q@_XZ>6TY`C*Bm{*V)g2v;8uY)#-8k60imfz5~F81cgi~D1MP_cfNG4YCiMHv zy$(d;QDXGzQ~aW?QDcgV(N+bpJ|F?ZSoyx<#d$Mj=m6WV`FD^F(NDuV+9&pwJFN41 zs2mceSFZw9^t~IANnaL)C}M&tZap!KZN^EgH$8=tiVB>O8C*bYIEW^h1<+0)XD}%t zft(^V25u`>^y<=u_{5Y&!RODfL*++&;<9BLf{09jSy7Jzd6C?OscC|cT~R?8M9}Er z>R?$S1$Tn1vZ=5VRaC8d>^ljoEqzF}M~v&{He5Iw8#@`|QcDqJclv>m1sL{0>X|`- zHo>?dt`vv#z!`^0A`rbeoaoE^(Gn<;*?{%|t}-Ae`>L|In6;H;b(>i2zZ>5tLA%2h zRM&Zo?j@d`P{{P*u%=*cltY1?Y6$27vqzuAbyN&{_2I))LY-|VQO$vMtE$4Z&f|dX z-?cbqk^`Ct6olzb|IvZ}K4x{}(mV@`?PP?U&B>09y>g|Ocsqtny%cY{Qk=&Ep$2Hi zIg1IYigK9B8Ww&7He4Z_PM38^J28Zgi3d~9p-HZ~oZam=9_Lm`1g}cB%O2fVjKZx1 zdsC0#>Evpn<`NSZXr~Fn;T|j+d4PM6_4`NfgosDvz}eW)Ve<#tIC8^kPXAc7ma?3K zBY!VG5ZOHbBnZfZrcOOcE3oS{wEYbNzhsg~Vd*R_EeKCDy*Fd`A&ZLl58rOtYv8Hk_V=NX-B143N zl1eA}(j|McoKu?DG(ZtTJ}tm*!^H~?HDgCwuGy%h?y~9ywHoe@dbL?I=Z}l~XI;xn z+h{#tvcNvA`Nx>l5!us2$4j$ve_HL=uUL1tvlNn&KGW|Y0`cWEtp@LQCHk(xu-~H-aJawLc)*ZR=Nk$Su>axt2=J{=%{@LN*?i zu|ow%_yw+mAoS@I&BZIta7Pk>qmRtG&`_pMJWW|7rAK3F!a?>fsA#5{8M(>+E#@<3 zEJ?9x1vJ`AN#*5pLVN%I{?ND~wG_jqr-U=pQ>dw)scHu3TZ z=>9-0#tr8c1I1+S1^-^ba>`2^N7u#(YUeg1>k&$Ev zofkbLDKSw}K(C4gRmesePB|e6JU|rPfLenF6|&UkUW-!K(^Ho7q8z4%MG$dNG#Y0= ze%wI0BKT4jJ+7#rfD^J&pF2tYfcp74KJJ;HdAz9KPWEI|MYraA=1JO3awVm%3{#FU zHIBE!`Rn*e)SEY++s0m{?Dh%47iuI<1^`yw7}{;d(-aO;@i<|{1uDhs20Tc1{SEfIv$u}i&N%9qBcqne zr8LJjRaV;5DA~xMU`k4gIdWvif^GUi((@~97<+*IrIrho`sYH0Mh_S^>`r-kcbRdZ zELe=DZODrHL1Mrh}q*arBUKF!%0$4B2-sY9LOa*(|gz?VuqP;Gdu~HhO|IVI+6O3 zmluk~cwr5PxxDF~J4|d@{mM?fzPK6?6%eS@Ye$gNemK7)9gjSO&ZpJzbFx8GL-7LL z38GChF?>FdFGwW6L~lN%*Ug*EfUyAT$Nal=!Ye?u-TIXuIdDL8j!fx~++bER0eo~Y6H_+0 zPYaLiS78-5CT8EhppA-HitwmYCed(kNtxWkRh7%=ovEDkc9kk+wo*_{(JjGurhbD& z;^-NL>w2QPrGCYU zjn;g|!5*`2Le9XkOk3`Q*O7@Or%q|;PK8K{nnY5$S1Pht!gpF4-w$Vrd9}?qSB*3| z-1W$$Euzz$ijz0GvW&`6x^w42gBuEZIM60_nUt~d^AQRr8!gIgeW(*KrP`h|u|K05 z;aDK22|KzV=A83LY;B25jG@_o{*cy+k{AXQJDO*oy(%O(!W`V~5>|kt#_#UnIP=L* z?72mzmUb;YHRVZ$@S zZ~crUp~0Q!e(hS;NLv8`_apR)4%RMt;n@CNAS(X<5K0dhKD-)59ovh~I!K`Jf z><-e>OqCipVz!rB^OVw%A)_FV!AawS%&o1aO$)2nT}Azjz#?bm_VppY1I^Dml{OwA zCR5**5}rvkdGA%ko3b64Op>Wo?&AET2ve77_kPN&1sbSgl622hU)lm=koUwsNH9hkDYqNvSrJ%2OZ#;VcZ6oFmDK9OM3x2 zj>M#;#r%hTigTci*6X#GDJ#&cbA%DoH%!_4Yq1VRD6JEC!g#rh^TS|Fu~TiO->W&`Aw!px2zlW{yJp`PT-n0a-~fO|+(b zvVGFGc7=xG)~fm1U>K_nn@v9@9^}Kv9$JN;YQ-oK@a9nP33+cexV89X-3i%j4=k!S z0uKcrlf8-gVzf(wFWLv{-gJ|#Z+?lh6R7%Se0bSF~hPd#zdQ<4l;7H;p^E;yB%28uuGW6C+Pr9jZV=*G8bcMN*J){`^<)_nxvQ zV1XpB{Bh```Qaq4HfgIE7J2xv#lapsEj2jF^36o0s#sh0!E}4BUzVwkT{D6rUjO*< z7a*-PG;IXd1Dp)V1JP8lz*(Vx8y!UaoB2`9_TTpnm-Put4U2*6@E23@=l4z{^rHSO zL$`YESmNZALcfZY3-_il3@_}rfp*mH8Osl^3tGxC}khKc_2 zW%8DG*es$mUwtgU*TBS>KaLI58-Fp8%Y9T=`<8UC^zJ3JW>cmNAgo6{BK*(NWB(TA zcfrOJ&A1SIU5lq}P#m}?p*0)!6%KNh+p-+4T5caSH>!ZKaAR|W&xGH(GsCMUJ~p;Z zGrcS9fYrjEqOL-UvN5<~P8)HVBrlQL{jkXJbZ@z+qR4lHVMFj*@=ZyqJ4`9Rss??V z{6_%MJ~buyf)DMT`-_0mxW6)(#K8&gF}q49?&EhES>qX1V>%1eMyj7QC4~Fs<&%31 zP>`wlt7bA#SEqe-Q%sl#Gwq6JiCd18p~@V!uAwd!SLmgI5UMK2yDv9xzxq^MxLlXi z@CP%ARkn_;Z5(t$0X@g3&I3o*&iHNe^4r3%oQzP8Q47j8&wgepqcDd_s3ME-+?XUW zL>2!6SX=R1`H<#TNVk<{knAA%!csaoIG~?J|3`^}agX+HM`q|P;e8JVS3 zt6%VDON>FK;Xx=KRv@8sQW6p$DzDih1}t#Si7IzEfO0^xef!M&13YfKiz5l)?sgUs zeXT{^OmB^t$x+Fq*8$~So0@OM?q3t_FzCy;I}_vrcX&ubwQ{9vO90df5)`AGj#|Xs zSfF|5z1RF|?`?Nm^y{uaH@>EGcHz~zGiQDVb*mNKHOQYu^94zRGJzll35ki+r7AkB zm4lq<0_i!~X=wFfD1#>>g<=Ee(xOXb+|O|EFxX*4rHKD%baoX|GauwlfX`hx{o#Wv z%`O6e1~#FX$EM9@i91;8)5XH8q;kL-2j6ppUbEDwouefa_=RmD$5`q4qi4^eiWNV)-YNkCl>tVq-*lhfSCFKJg?0RKx7ra=r|VdVMy2Ly z=6h(0s@v~jBITQ}BV9pTE0SO9Y<;ZoboZGL{Ft>LFJAMWL4scUSABMG8 zx@gNrD=E)Z1&Hef7na?Fhn4F3Xuf(x^@zMs87+s*rmLSbNiFZcoAQ!MEGI3&$z`p9 z;#cL)1s2<1Oz-9C2^9$^Gw++cnucPXDp5+EJ_lHz>IFUxY?EPD z0c{3XT3Ng2+e(@g5XhXDw~{g$kj#&2d&}?dQLblwoLx58n(zqNUw^Y@Qhjws0n0D3 zxx)yJGLVH3w|CuoI^JLXSjfeIju<_2*0}8KJ3IpFDB{e_LWxrSHGzjR)-q)3z(G4U z?UX9K{=#EVdxK2ceCqt_3Gc8Lb(D>6zv23;sw*2n_WNW?h;dkeHm`{G%Kn+%L(9g! zzSgO9WM;&v>X3(VZbf8YpmBq0?;yLJQ4_13o!j>7De5_{zbj1qR_rss`r7upEk3n5 ziN+tFU7h#tvhs*KBocz`;NeR0zqtowY-+lnvfg2|0P2sOj$z1F!t5Bb9z?WbWjru(*UZUfc_M1Xk zQ%eh6G{0ETxdGUT9eI(&5QuCE!3)7Ws~s)H+V$%ha$QsB;a))e1=1A2kr%565{Urh zl%C|jv9Hy^>?*uxm6go(o30)~9y5I{?p>PhTqs>7SiA3m~`od(6w%ue;9NkL@0Q zqQhq`q^$G?fVlG#7oaV)WDPud!r4sw!bOz&D4Vr7XkzTSb9e6F-)nN5`gtQGTuNTE zLo(cr3CDkI2sKk-ZXUNw+@>M%V-E}zon6i}_mG%$uKVL;CtB4~npDS3>%oyG$8(}n zxw-&DsT7L*LS$pif>kg7&7Bm{!b!unko3cYz?aQSnx^KemftbxFwTwIJ2TdjUUJr~ zEBQbI4glB5S zQ=l=(7=XRgQiRVro17f}=;6_D?pCQ4vVgnHVe)<^AL#VA=Fdr-q~H#;guv5G2WKOs z9T0r|rheSlNtGF2Yk_oWx;kkmkLo+>@To_DR8E^=cnDFlju6tFoKF|XleZ))V3isWHvqOAr zbNqQ;@KRo$ezim#0?u0!=AZRB7MYndykkaGT|-rG*ypbBM|^5-d#9K|M)}Tb7}9?5 zU@tp4&;Ly<68+js-(jIRQhityH~bjB=&qsg)=0$? z1Dpiu)^Gf~pI#lz=;&TMJZ!hV-#**cmg!lXEavf6zrrVFk5q47C}zzqUtVK0?#Ij_ zOc`VcI%Y*7lE}c1VdC&66271wZkW>okc|&rnO~mVhMJ7ykO;=mXL}S%?L=S*z+HDv z?v2JL!shWm{H?MI|5f2NBp+!d*PoXoA9O%XYprt611ZTa&=xt7gfB7ARBz1umloi@ z(EvTCIyU=+0yp4iRBr>2MKbUX;{f6neQqPgJJ7v)vtu#r-C zCaK6N)-9R5E-ZFuRMb3A&ql;V@KKe&rlSZ5a-xNRNTl5c$xwD(DBseqcxcdQdLTCT z)_@$uA)PLbN8ND}IO?B)O(zh1=FF9PPJJIc?@x(Y$%)unhG-8uiayb>KAr5@TvuZ_W5>iDi2F7Lb+EWZC%@5 z<@qXK_ft;VmSA-9I17FyxVw*ND6DM9jmMB(ERC)X_1C;g z{4JDgBJE4aWGQ~hPSgH|>qK$N-=ZQ#oPms}&v7L`r@!7(Tao|q(qPT8Al24i^}jVZ zqe_a$vXwxs24|78M%_uhU_W$PtR?d{-T`=)w&3dW{`D~peVB(iR*Zc^ZBgZFD444_ zi_?l&3N62~S~kyb6;!O@RHj4nt}E!_VUD4Q{^zJPeoQKWIt-e#vmVAofcgV($T;>7^^fe)Ci{_53^J`?uk)##2NpPQeWIBX^fbY*Ac{dg4$qwC(x5ubI>}|MJ=adWR__c=$Q) zV28ht|3X;izvcJhoVBDmR#xvmeDES+iOwm~922sowKc%fiL>X$Y)71BcntRtv7nd2 zH!vv*e1n8blyPyIabqw^Mny!#!jQgw+i*+){|8^#M`08eFnCiu^*qr_knY2xU|1Dq zvpB8b3yF)zu$9D?y=6CLi=x{KFDEb)NMt(7GbS0)4Lkrs&Zd`F66j+Hjn3^HLzu_e zvvxK%(gI0*F)1l^@Tm-fptqG3us)F`iP^n|{RiE4Yjiaf2S^gSVn+CpI=dqzL=b4o z@*Y1P*S~*$ZZ7s61tFP>2P2Qwi1velsgM|b1SVee>DJBYV2>_ChbH0*>N*=Z4qZX@ zXI6gSiJp6{bu@^|LmW$w+d}}8Im(?=3?sl9C&6>Zkz%17AML}uyklNg%YhCdhZ&|2 z3v9q-PA2gPjzq~)=MZ#Btdyg+5{IGjIQlYJg8a@*`&oh3Il|O_st>~=Nf;;FMQ1ew z-;3_t33^EO7?{~1+_ntfyK-gN{8VEjBT*G=6$u+pb`+@v3wz%U7eg zp!-w|TRhuzrRWew^4Cd5rWfx~6FU2XTQ z5KUQdi0C`enB92i{<#wQ;c-OEw+Ixub4TuO8qV&yM)|gjeT}+3UpVsUz`FlS2A!4O zMxg&z3L=%*K~>%h5T1fWsAXL;*OEMy7cYQq^*la;dqWhq5t$4C$hb{4oc^>jOw{bw z4IO(r^CvtqIoydihwO>jy}RvalQsh40U%EynZt?L-Tmnd5+}R#AY|o1WA#~_`Jv7! zN@6jznaSGJ>VF60C0Vg#iHSmKMFqngb)jc%&?jA@bwKl%q&Z1LV;MoQwNGHdlNMZ* zvFF^g7YqRP5u~*0m#}tCWPh^`1AFv-oVr->1!h2om77lq?Bxi14$XA!(h^M25FXG*0;!jog}r%~+(GZvH%$Vmzp+3mA=qcMi z(p=oyEHxmV7bZLUwQhbu|5op2f2PEv&?2*o#**?u+{ICnL73HjA2#-oIKU5?1xF76 zWL{tht>^z~clUphj{0fm&O5Y1qU5`(@IgsQ_By|(SzBUgVp1$xRcODX9DLrg!S(rv z1g@9q8fnhHiVK(>H(+KK_)(9c3tSu>eVxR}(73*;1V{2Y9#&Ot;qc?eLRW)@l0?qf z4?HeM*3m~(JSQlW_CimwVa*!o6n2Ff1_s%KV!ZsF_PcIV$bU8UkvbiMd*HSiCyN&B zw6^`);5C1`qb=gRK*QMZ6|dgD-2{(Ana$n`t{@Z00CajDmvSRjeS^lIiu4n_Fus5s z6@7;*>qGD27T>pf_gbcubLsbsF$QnM9*<;6nDolBvQf;u;OV4i<;~=-L%6`<&q#I0 z|L{@#aX}3E0E&3x1m?zGa!=znb&1^D%TATMA_CXI1X#lX_Dna3?*3|yy`_BW+T1^V za}_Zv)2FY(gP3lhn_*}gk7oHwdODBXWO42cI~lM5Q-|#%k;q`f)+}c4cb_zxPs5Ja zQNsUW1QLkVE-n&%P8+KOE+DaM8=SXh-MRp|$h=miVXL5;WMGFC2C_0Tw6g&tS;f$^ zZ0z7^?gzkF=oy(xG?UvLm|v1#ba zajC1g$XaJ^!u0@ob9bG#?Ukdmf|h_RYoTVqj8bEzG{QmRxzWk0$AyUd$kPhZ1RNOe z)09p>UQ$xe4%9}JtNb@SVgqR(?F2FJg)x6AHn(4`4lN8MF!K25~Q~aW$fCdYV+~rY>_J6(-W`+^s^XFJz-F(8 zMxdh}A^UGq5skgz`^P(-{-m8+BpcQhPSu=ltdjp=7W1@GKHL{i`NAF+f&ikb6f|*5 zbJK>GNQn{h*EV>?S^{faK_Hi~5~SLvrP*7^Mi?%3WR1j27GS#|ByuJ>D{Q9!NiwEV zB8=Via3hFWah&%re88sdZ z8No5dhEK+c!d+nM)OtT|P+Nhnfp)lF;oB6pEWGiPas2ojM5b`;QBbFxx}rX?ry z^X^l62U|m`E%NjnulL{5Y9)JWm=*=rk)saW2J%o8R1X<0ScI_?3HAQ5 zs}3@gWBvNk%eN^|xGKm@0cX#{;gSAU=zHtWIq#qLJ?sK**~KX~zzWon2N=+CyNAB& zMO^kqjoH*9A07JLTEO5o0w)8d5#HYk6Dla9 z>Ez?%3yO-S85y<9OUCuZ7R3nwL5YQtNG;Kft9?)_&@e*gDADQovz?YL+mG)gHn!&N z+naAhMX}hKFl2$&%uYw)T+{SR-zrepAEjr!L_D&X?3wV-$UTOz(&~Hya|(HrcIgr> zVua{0#uQ7>d+X_n58&z3yUq1BemYEPoYknT@3mj)zDsp$yGTSaHs1WbAi8-`>a9vC zJvLYpzvj+;aAb%m#?K-p(R?=Ktho3 z)k|hk$@dMVo9|LAKt)Y%OoA$*qZ2hwl*IY@BuHRUB@tOXk4tQ{1v4;j#_Nz_O#Z>x zHP4MhjYo31IUnjv(_Mv+1U_<&(GGCt6y3bZp;}2pd((w#zX?I3v7}}C7oC!9w*$Nc zOrank_l%4zN9N+>YmYjHvOhc=dBbDZzv%1vC7bl@eSF~T0#xL$5=$r?C47}H5;sgV zP#)P|Yb59weHU#EwOBwX$O|A<_2>HClr;4Xx}33qegJ+m5#Z-k)k+E3wo?0j(1?Ix z)pYq1i*orjdeIyOrTz-d2;K=p;mbeAIxakNA8(BymVNtvkgZ`fTSDaesm_^b^zgw0 ztjVSwh*%nQ+7mICUT)p{8%bx*goTEN?%esh&ZGWfTR&``{Ro@v-<5dP!t2+;1q?3P zRe#pLjh4h?jv)M7%I+uS5I#L3aYU%`Zjv{@W%$y zT-Q!ryF^m9BmLM>O?*t^)o?c=xR+^1Qi3Qm*twF%S5)>1s(<9M)sk&4z_q?*f^fhb zEt}+OC{(6p3?H7be*k;L^7JpUCg|L^mqn6Pv+Bu(^mJXNd6V?@`(F9M>?E`#fGpJH zQ;m%Y5Z&dm&fr}=cY{0&rli3yu@&M%taV%d?f0BWXjqOPXQntYJzh1Q8SHrNh3!aj&7knebxGGB!t+w~p&0N8- z#U;fDQQfjhU$v{PxsbCEWIJ3tI%Ar7@5Vy>+q z-LWH9Pb7RHOr@WGk%4WrOM>9Z2xWqi*T1#mDzPi?$Hv}i9%2)kc8eJ^f?kZN+b1uC z$HXL2uJcLv?-vnMn#Bb(W{ByZf-j&iVPfKph9n7s+OsN@k{~eOkU31 z0%>V!-&oz+%1kacdmObtmq%&)XC(6ePIhespb%3tGquy!vt}`fGis>q4>4Q{t1(Hb zT8e}oAWrT&RsQi_pbeM{cu%h%qSofe0mh;#OY7F#Y>_L)>U%;9wC zyndmsdIU$fV)yPjPg}mmwD{_0mDh1mU+8q3wy$Z+<~P0W=a*lvi#$^^GCHKk*73_r z4TL(YE>^=<#m~_kb>ZO7?Xef{n8q&)Je|0`&)HEkrWMXe=`pCw${iO=?>z|{HS4gP z)szIw;?XyN#nKSG}50!6+Qq5mPTPHeX9hrM>?@bqNVVUE>w%v|{c@gd} z`oOAfzNQsrm2Vxctu5~lu+u)NSJK1Y^77fclfQZBQR}JRLi5$~p(xN>z3s zW^g&ug)~o#zFU7OUb}WpF)XmB)2bKDMQT?l?MT=l)+Qocng6iQ3JmWErJ3C@@{u;O zVM{E3_JNfVXo#M9HYa9U1rXQSvbP2`hld=Uh+pH`GttS>O`_(ns})b4(CK9#d>%2i zuhU%FqR6keBCFg81Ks|4iA*^5dgdV<{otIMF_7-kI_h7Z0k2)YYxow?#H>^zQypmy+H~Q*82`Q*s=2 z39hnF3XYwpb&J{p2~PAyqfw8)E=&8v@lo}k&4Jlx%rBmFzHTpB$B?SY^3Z>rP5>dQ(g!U5VxJ-t^1M1ZRh`lb zup|J_y+-zIsX;zKO=cgRT*H%P95176L;Fs98j<&LWo0H$)$!ks=@-{teU?#a`1#t; zzMtz`hG*`%8Rtk5u&JeE$gDCF^Vs7oYsMZb#$QAmDjmzV1K77iVG4w@h@xDWx3u`+ zl$mY%ckN)ddvN5t9Xgf1Ayx@ZAI{%ZmYYg84}R+;-?3%xj3w;;trEQN3MqJVi&N~z zCD}FnzK)8Rj`ro+O=N8uo;rDwkzpV{XRHTrEkWta$>CKib^zdj>(?tN`b(=FDpu^) z?L1f(y%2I7X_5X(UNS{mG%bN25hX>O&+&VQ$8RA1HA%HV~JXtBNrm+R$pILv3fx!37MaMRV`uxj~q>Nmz z*(a<qW#|O%1V;X?!UnAr`Jp;KFowHMUV|Wp(vqXU}dw#;P~28sEEb-}Wb= zrsnz?gzw({1qC!?Pj(*D2+kV;?vj4HuzSfl%!l90=f#GD)~B1;;YH}#^X3P`t*>r1 zyu9_<2$3Z`3pcge9Y_WPB!^m!yXscQ;mS?#5$s|w9p-Ey=g}?8Dq(98qlQ)i5W8P& zlQG)s>gnuWo*-10*7}{(8b16kMfS~`eq~-B8}OqugtfwT?5;vYR_p}w$OWgE$L~I- zakA_(q#Sxe?MeD>%b%K+lhg&bRlZ`wWjopc#{JBwL+AG^-5u()8O^;9~o0Q}H;aNuF$ z=|V9svn|HXad4Ql>dENF@NxS*rpl!yZThwI$Ksj?ejELZyc|@ThNMawh8#P^=KJI4 z&$6){vj6^j+2+j?J`a>1xTUEM4zIV}B1xv-c$a5pWvTq=j%Gu9&}%JN@R|!1PF`Mz zD+jag|9)YCL2rD{i#qDcoH12bLvFe_U+g=?a29h>RNkM6$Z>T1*uKW()4J-|J*atg z8Ih?f?TpUN{ghS0-+_jN|A6+$FIt;@sJ_5?4H9H5Cq|toT3cB?|L(bbc&Dm!gBK+3 z+uWy}nl-GrvhvfivUVpMYTqgK?AayMn9_&)00@GSUeoXt=0#|ckq3wuzk-%+aZc{g z9UHASfFO#ySD+y?`dG#LH1BW}RgWH@y5arY{qHKx8ZrlYee<5W)e?>Mx@l7wBTD$s z--&aj)gEazqmacDJrf@;?iD-^{yWT`O1p&-hDMkf3Jtvp6MC;+>)ubRa!ZT%>%XSI zwt3!q3O(5RN-8h0-Ji?t7_A}u`iM4W4tZ%(CEQ-kMr%mVnBKc7V$#x`6*4O7qb|zK9dU?Hu8XMe>t~b>yl?BSZ|!NNZGh( z&fv&rtFz)vjgAR|#CS8~$<|*>`&##v;5xN`(azo0Z01azUOSEoKSXm4=or^x?d7K{ zF24Kj89wIxf9eeI?Te3z!4yut4N%WT#3cXjI(J!9U& zg`E_8NKE#)W^Y-hE)Bj*x*DQQI(I|4>J10ijE}~vczEPun)ThqONh-LB<=q&ehENp ze>3&1kebs6mZ4B)RAM;3_EpCqbU3WCzCW;qH>1FiZ(KnWGY91p$nQJ##J4u zeidp{9vjBvkCv~r)9B_bJDs=DDhk=Yr z0PMuq$x9QwM_R9beRVs3Rj8k=U!SfrH*m>xpv&yQl8=AU@FVRJ14>tXCs@HW-s=2g ztq4*2s#o7V;RWdDUck!`(Ad7~>a@*d`vA>B z1&F5Hv)g-5miFtNf~#wMG=F#ec%Gv+8!GiiHwjP}wWNoldgHwM#;YwYQ0I}X(0 z!9uUJ$b{VQTYC53u16t-aV#Yz;@BxD4779USFSY9ZTtFf`&;62zgqIDWze6W^!dFI z&Dn&{86=NwH+jKMj`Q#5qeZ*u9G3&bQy<=c|J`wG366M*Tyo$`?X@!Whb%}O%Y>+m zr_?=$Mn*7?bi3p@mEFIe|9(yG*_-Hz<^o?%MG-6QFY;M{X{cZ5;Rz;?*jQw?+httw z;fb5)_V1e0xe-P5=FL|rQ(<2_NA)^cwh3a)riv77u!aC5S#3SNrcYNte|nVCZtHI9 ztj?cQ9W&d$QQC2xpIrSC1)WTwGewd-5yI2Z9%6ZT?0W9ZnX+Z0>7`e?x^52(TQsHF zvvZYBlS5K~llJ}z1!-Bx<)MMO{uDjDz`dy|V-8pVKT_Nc+!H!4yQy_^SZjapiyloMAXeH$k3wkO1HC=?c03aV!ygi*gghK zy87j?KebdZz05F)_AgWp55@KU|Nrlp7U6Q?^M0ZCAIlNLE0|50VSLWe(f|JgWif<` literal 0 HcmV?d00001 diff --git a/doc/default.css b/doc/default.css new file mode 100644 index 0000000..2e1fddb --- /dev/null +++ b/doc/default.css @@ -0,0 +1,188 @@ +/* +:Author: David Goodger +:Contact: goodger@users.sourceforge.net +:date: $Date$ +:version: $Revision$ +:copyright: This stylesheet has been placed in the public domain. + +Default cascading style sheet for the HTML output of Docutils. +*/ + +.first { + margin-top: 0 } + +.last { + margin-bottom: 0 } + +a.toc-backref { + text-decoration: none ; + color: black } + +dd { + margin-bottom: 0.5em } + +div.abstract { + margin: 2em 5em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } + +div.attention, div.caution, div.danger, div.error, div.hint, +div.important, div.note, div.tip, div.warning { + margin: 2em ; + border: medium outset ; + padding: 1em } + +div.attention p.admonition-title, div.caution p.admonition-title, +div.danger p.admonition-title, div.error p.admonition-title, +div.warning p.admonition-title { + color: red ; + font-weight: bold ; + font-family: sans-serif } + +div.hint p.admonition-title, div.important p.admonition-title, +div.note p.admonition-title, div.tip p.admonition-title { + font-weight: bold ; + font-family: sans-serif } + +div.dedication { + margin: 2em 5em ; + text-align: center ; + font-style: italic } + +div.dedication p.topic-title { + font-weight: bold ; + font-style: normal } + +div.figure { + margin-left: 2em } + +div.footer, div.header { + font-size: smaller } + +div.system-messages { + margin: 5em } + +div.system-messages h1 { + color: red } + +div.system-message { + border: medium outset ; + padding: 1em } + +div.system-message p.system-message-title { + color: red ; + font-weight: bold } + +div.topic { + margin: 2em } + +h1.title { + text-align: center } + +h2.subtitle { + text-align: center } + +hr { + width: 75% } + +ol.simple, ul.simple { + margin-bottom: 1em } + +ol.arabic { + list-style: decimal } + +ol.loweralpha { + list-style: lower-alpha } + +ol.upperalpha { + list-style: upper-alpha } + +ol.lowerroman { + list-style: lower-roman } + +ol.upperroman { + list-style: upper-roman } + +p.caption { + font-style: italic } + +p.credits { + font-style: italic ; + font-size: smaller } + +p.label { + white-space: nowrap } + +p.topic-title { + font-weight: bold } + +pre.address { + margin-bottom: 0 ; + margin-top: 0 ; + font-family: serif ; + font-size: 100% } + +pre.line-block { + font-family: serif ; + font-size: 100% } + +pre.literal-block, pre.doctest-block { + margin-left: 2em ; + margin-right: 2em ; + background-color: #eeeeee } + +span.classifier { + font-family: sans-serif ; + font-style: oblique } + +span.classifier-delimiter { + font-family: sans-serif ; + font-weight: bold } + +span.interpreted { + font-family: sans-serif } + +span.option-argument { + font-style: italic } + +span.pre { + white-space: pre } + +span.problematic { + color: red } + +table { + margin-top: 0.5em ; + margin-bottom: 0.5em } + +table.citation { + border-left: solid thin gray ; + padding-left: 0.5ex } + +table.docinfo { + margin: 2em 4em } + +table.footnote { + border-left: solid thin black ; + padding-left: 0.5ex } + +td, th { + padding-left: 0.5em ; + padding-right: 0.5em ; + vertical-align: top } + +th.docinfo-name, th.field-name { + font-weight: bold ; + text-align: left ; + white-space: nowrap } + +h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { + font-size: 100% } + +tt { + background-color: #eeeeee } + +ul.auto-toc { + list-style-type: none } diff --git a/doc/facade-and-adaptor.rst b/doc/facade-and-adaptor.rst new file mode 100644 index 0000000..169b856 --- /dev/null +++ b/doc/facade-and-adaptor.rst @@ -0,0 +1,1598 @@ ++++++++++++++++++++++++++++++ + Iterator Facade and Adaptor ++++++++++++++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, University of Hanover `Institute for Transport + Railway Operation and Construction`_ +:date: $Date$ +:Number: N1476=03-0059 +:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:abstract: We propose a set of class templates that help programmers + build standard-conforming iterators, both from scratch and + by adapting other iterators. + +.. contents:: Table of Contents + +============ + Motivation +============ + +Iterators play an important role in modern C++ programming. The +iterator is the central abstraction of the algorithms of the Standard +Library, allowing algorithms to be re-used in in a wide variety of +contexts. The C++ Standard Library contains a wide variety of useful +iterators. Every one of the standard containers comes with constant +and mutable iterators [#mutable]_, and also reverse versions of those +same iterators which traverse the container in the opposite direction. +The Standard also supplies ``istream_iterator`` and +``ostream_iterator`` for reading from and writing to streams, +``insert_iterator``, ``front_insert_iterator`` and +``back_insert_iterator`` for inserting elements into containers, and +``raw_storage_iterator`` for initializing raw memory [7]. + +Despite the many iterators supplied by the Standard Library, obvious +and useful iterators are missing, and creating new iterator types is +still a common task for C++ programmers. The literature documents +several of these, for example line_iterator [3] and Constant_iterator +[9]. The iterator abstraction is so powerful that we expect +programmers will always need to invent new iterator types. + +Although it is easy to create iterators that *almost* conform to the +standard, the iterator requirements contain subtleties which can make +creating an iterator which *actually* conforms quite difficult. +Further, the iterator interface is rich, containing many operators +that are technically redundant and tedious to implement. To automate +the repetitive work of constructing iterators, we propose +``iterator_facade``, an iterator base class template which provides +the rich interface of standard iterators and delegates its +implementation to member functions of the derived class. In addition +to reducing the amount of code necessary to create an iterator, the +``iterator_facade`` also provides compile-time error detection. +Iterator implementation mistakes that often go unnoticed are turned +into compile-time errors because the derived class implementation must +match the expectations of the ``iterator_facade``. + +A common pattern of iterator construction is the adaptation of one +iterator to form a new one. The functionality of an iterator is +composed of four orthogonal aspects: traversal, indirection, equality +comparison and distance measurement. Adapting an old iterator to +create a new one often saves work because one can reuse one aspect of +functionality while redefining the other. For example, the Standard +provides ``reverse_iterator``, which adapts any Bidirectional Iterator +by inverting its direction of traversal. As with plain iterators, +iterator adaptors defined outside the Standard have become commonplace +in the literature: + +* Checked iter[13] adds bounds-checking to an existing iterator. + +* The iterators of the View Template Library[14], which adapts + containers, are themselves adaptors over the underlying iterators. + +* Smart iterators [5] adapt an iterator's dereferencing behavior by + applying a function object to the object being referenced and + returning the result. + +* Custom iterators [4], in which a variety of adaptor types are enumerated. + +* Compound iterators [1], which access a slice out of a container of containers. + +* Several iterator adaptors from the MTL [12]. The MTL contains a + strided iterator, where each call to ``operator++()`` moves the + iterator ahead by some constant factor, and a scaled iterator, which + multiplies the dereferenced value by some constant. + +.. [#concept] We use the term concept to mean a set of requirements + that a type must satisfy to be used with a particular template + parameter. + +.. [#mutable] The term mutable iterator refers to iterators over objects that + can be changed by assigning to the dereferenced iterator, while + constant iterator refers to iterators over objects that cannot be + modified. + +To fulfill the need for constructing adaptors, we propose the +``iterator_adaptor`` class template. Instantiations of +``iterator_adaptor`` serve as a base classes for new iterators, +providing the default behavior of forwarding all operations to the +underlying iterator. The user can selectively replace these features +in the derived iterator class. This proposal also includes a number +of more specialized adaptors, such as the ``transform_iterator`` that +applies some user-specified function during the dereference of the +iterator. + +======================== + Impact on the Standard +======================== + +This proposal is purely an addition to the C++ standard library. +However, note that this proposal relies on the proposal for New +Iterator Concepts. + +======== + Design +======== + +Iterator Concepts +================= + +This proposal is formulated in terms of the new ``iterator concepts`` +as proposed in `n1477`_, since user-defined and especially adapted +iterators suffer from the well known categorization problems that are +inherent to the current iterator categories. + +.. _`n1477`: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/papers/2003/n1477.html + +This proposal does not strictly depend on proposal `n1477`_, as there +is a direct mapping between new and old categories. This proposal +could be reformulated using this mapping if `n1477`_ was not accepted. + +Interoperability +================ + +The question of iterator interoperability is poorly addressed in the +current standard. There are currently two defect reports that are +concerned with interoperability issues. + +Issue `179`_ concerns the fact that mutable container iterator types +are only required to be convertible to the corresponding constant +iterator types, but objects of these types are not required to +interoperate in comparison or subtraction expressions. This situation +is tedious in practice and out of line with the way built in types +work. This proposal implements the proposed resolution to issue +`179`_, as most standard library implementations do nowadays. In other +words, if an iterator type A has an implicit or user defined +conversion to an iterator type B, the iterator types are interoperable +and the usual set of operators are available. + +Issue `280`_ concerns the current lack of interoperability between +reverse iterator types. The proposed new reverse_iterator template +fixes the issues raised in 280. It provides the desired +interoperability without introducing unwanted overloads. + +.. _`179`: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#179 +.. _`280`: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html#280 + + +Iterator Facade +=============== + +While the iterator interface is rich, there is a core subset of the +interface that is necessary for all the functionality. We have +identified the following core behaviors for iterators: + +* dereferencing +* incrementing +* decrementing +* equality comparison +* random-access motion +* distance measurement + +In addition to the behaviors listed above, the core interface elements +include the associated types exposed through iterator traits: +``value_type``, ``reference``, ``difference_type``, and +``iterator_category``. + +Iterator facade uses the Curiously Recurring Template Pattern (CRTP) +[Cop95]_ so that the user can specify the behavior of +``iterator_facade`` in a derived class. Former designs used policy +objects to specify the behavior. The proposal does not use policy +objects for several reasons: + + 1. the creation and eventual copying of the policy object may create + overhead that can be avoided with the current approach. + + 2. The policy object approach does not allow for custom constructors + on the created iterator types, an essential feature if + ``iterator_facade`` should be used in other library + implementations. + + 3. Without the use of CRTP, the standard requirement that an + iterator's ``operator++`` returns the iterator type itself means + that all iterators generated by ``iterator_facade`` would be + instantiations of ``iterator_facade``. Cumbersome type generator + metafunctions would be needed to build new parameterized + iterators, and a separate ``iterator_adaptor`` layer would be + impossible. + +The user of ``iterator_facade`` derives his iterator class from an +instantiation of ``iterator_facade`` and defines member functions +implementing the core behaviors. The following table describes +expressions which are required to be valid depending on the category +of the derived iterator type. These member functions are described +briefly below and in more detail in the `iterator facade requirements`_. + + +----------------------------------------+-------------------------------------------+ + | Expression | Effects | + +========================================+===========================================+ + | ``i.dereference()`` | Access the value referred to | + +----------------------------------------+-------------------------------------------+ + | ``i.equal(j)`` | Compare for equality with ``j`` | + +----------------------------------------+-------------------------------------------+ + | ``i.increment()`` | Advance by one position | + +----------------------------------------+-------------------------------------------+ + | ``i.decrement()`` | Retreat by one position | + +----------------------------------------+-------------------------------------------+ + | ``i.advance(n)`` | Advance by ``n`` positions | + +----------------------------------------+-------------------------------------------+ + | ``i.distance_to(j)`` | Measure the distance to ``j`` | + +----------------------------------------+-------------------------------------------+ + +.. Should we add a comment that a zero overhead implementation of iterator_facade + is possible with proper inlining? + +In addition to implementing the core interface functions, an iterator +derived from ``iterator_facade`` typically defines several +constructors. To model any of the standard iterator concepts, the +iterator must at least have a copy constructor. Also, if the iterator +type ``X`` is meant to be automatically interoperate with another +iterator type ``Y`` (as with constant and mutable iterators) then +there must be an implicit conversion from ``X`` to ``Y`` or from ``Y`` +to ``X`` (but not both), typically implemented as a conversion +constructor. Also, if the iterator is to model Forward Traversal +Iterator, a default constructor is required. + + + +Iterator Core Access +==================== + +``iterator_facade`` and the operator implementations need to be able +to access the core member functions in the derived class. Making the +core member functions public would expose an implementation detail to +the user. This proposal frees the public interface of the derived +iterator type from any implementation detail. + +Preventing direct access to the core member functions has two +advantages. First, there is no possibility for the user to accidently +use a member function of the iterator when a member of the value_type +was intended. This has been an issue with smart pointer +implementations in the past. The second and main advantage is that +library implementers can freely exchange a hand-rolled iterator +implementation for one based on ``iterator_facade`` without fear of +breaking code that was accessing the public core member functions +directly. + +In a naive implementation, keeping the derived class' core member +functions private would require it to grant friendship to +``iterator_facade`` and each of the seven operators. In order to +reduce the burden of limiting access, this proposal provides +``iterator_core_access``, a class that acts as a gateway to the core +member functions in the derived iterator class. The author of the +derived class only needs to grant friendship to +``iterator_core_access`` to make his core member functions available +to the library. + +.. This is no long uptodate -thw +.. Yes it is; I made sure of it! -DWA + +``iterator_core_access`` will be typically implemented as an empty +class containing only private static member functions which invoke the +iterator core member functions. There is, however, no need to +standardize the gateway protocol. Note that even if +``iterator_core_access`` used public member functions it would not +open a safety loophole, as every core member function preserves the +invariants of the iterator. + +``operator[]`` +================ + +The indexing operator for a generalized iterator presents special +challenges. A random access iterator's ``operator[]`` is only +required to return something convertible to its ``value_type``. +Requiring that it return an lvalue would rule out currently-legal +random-access iterators which hold the referenced value in a data +member (e.g. `counting_iterator`_), because ``*(p+n)`` is a reference +into the temporary iterator ``p+n``, which is destroyed when +``operator[]`` returns. + +Writable iterators built with ``iterator_facade`` implement the +semantics required by the preferred resolution to `issue 299`_ and +adopted by proposal `n1477`_: the result of ``p[n]`` is a proxy object +containing a copy of ``p+n``, and ``p[n] = x`` is equivalent to ``*(p ++ n) = x``. This approach will work properly for any random-access +iterator regardless of the other details of its implementation. A +user who knows more about the implementation of her iterator is free +to implement an ``operator[]`` which returns an lvalue in the derived +iterator class; it will hide the one supplied by ``iterator_facade`` +from clients of her iterator. + +.. _issue 299: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html#299 + +``operator->`` +============== + +The ``reference`` type of a readable iterator (and today's input +iterator) need not in fact be a reference, so long as it is +convertible to the iterator's ``value_type``. When the ``value_type`` +is a class, however, it must still be possible to access members +through ``operator->``. Therefore, an iterator whose ``reference`` +type is not in fact a reference must return a proxy containing a copy +of the referenced value from its ``operator->``. + +This proposal does not explicitly specify the return type for +``operator->`` and ``operator[]``. Instead it requires each +``iterator_facade`` instantiation to meet the requirements of its +``iterator_category``. + +Iterator Adaptor +================ + +The ``iterator_adaptor`` class template adapts some ``Base`` [#base]_ +type to create a new iterator. Instantiations of ``iterator_adaptor`` +are derived from a corresponding instantiation of ``iterator_facade`` +and implement the core behaviors in terms of the ``Base`` type. In +essence, ``iterator_adaptor`` merely forwards all operations to an +instance of the ``Base`` type, which it stores as a member. + +.. [#base] The term "Base" here does not refer to a base class and is + not meant to imply the use of derivation. We have followed the lead + of the standard library, which provides a base() function to access + the underlying iterator object of a ``reverse_iterator`` adaptor. + +The user of ``iterator_adaptor`` creates a class derived from an +instantiation of ``iterator_adaptor`` and then selectively +redefines some of the core member functions described in the table +above. The ``Base`` type need not meet the full requirements for an +iterator. It need only support the operations used by the core +interface functions of ``iterator_adaptor`` that have not been +redefined in the user's derived class. + +Several of the template parameters of ``iterator_adaptor`` default to +``use_default``. This allows the user to make use of a default +parameter even when the user wants to specify a parameter later in the +parameter list. Also, the defaults for the corresponding associated +types are fairly complicated, so metaprogramming is required to +compute them, and ``use_default`` can help to simplify the +implementation. Finally, ``use_default`` is not left unspecified +because specification helps to highlight that the ``Reference`` +template parameter may not always be identical to the iterator's +``reference`` type, and will keep users making mistakes based on that +assumtion. + +Specialized Adaptors +==================== + +This proposal also contains several examples of specialized adaptors +which were easily implemented using ``iterator_adaptor``: + +* ``indirect_iterator``, which iterates over iterators, pointers, + or smart pointers and applies an extra level of dereferencing. + +* A new ``reverse_iterator``, which inverts the direction of a Base + iterator's motion, while allowing adapted constant and mutable + iterators to interact in the expected ways (unlike those in most + implementations of C++98). + +* ``transform_iterator``, which applies a user-defined function object + to the underlying values when dereferenced. + +* ``projection_iterator``, which is similar to ``transform_iterator`` + except that when dereferenced it returns a reference instead of + a value. + +* ``filter_iterator``, which provides a view of an iterator range in + which some elements of the underlying range are skipped. + +.. _counting_iterator: + +* ``counting_iterator``, which adapts any incrementable type + (e.g. integers, iterators) so that incrementing/decrementing the + adapted iterator and dereferencing it produces successive values of + the Base type. + +* ``function_output_iterator``, which makes it easier to create custom + output iterators. + +Based on examples in the Boost library, users have generated many new +adaptors, among them a permutation adaptor which applies some +permutation to a random access iterator, and a strided adaptor, which +adapts a random access iterator by multiplying its unit of motion by a +constant factor. In addition, the Boost Graph Library (BGL) uses +iterator adaptors to adapt other graph libraries, such as LEDA [10] +and Stanford GraphBase [8], to the BGL interface (which requires C++ +Standard compliant iterators). + +=============== + Proposed Text +=============== + + +Header ```` synopsis [lib.iterator.helper.synopsis] +======================================================================= + + +:: + + struct use_default; + + struct iterator_core_access { /* implementation detail */ }; + + template < + class Derived + , class Value + , class AccessCategory + , class TraversalCategory + , class Reference = Value& + , class Difference = ptrdiff_t + > + class iterator_facade; + + template < + class Derived + , class Base + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default + > + class iterator_adaptor; + + template < + class Iterator + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default + > + class indirect_iterator; + + template + class reverse_iterator; + + template < + class UnaryFunction + , class Iterator + , class Reference = use_default + , class Value = use_default + > + class transform_iterator; + + template + class filter_iterator; + + template < + class Incrementable + , class Category = use_default + , class Difference = use_default + > + class counting_iterator + + template + class function_output_iterator; + + + +Iterator facade [lib.iterator.facade] +===================================== + +``iterator_facade`` is a base class template which implements the +interface of standard iterators in terms of a few core functions +and associated types, to be supplied by a derived iterator class. + +Class template ``iterator_facade`` +---------------------------------- + +:: + + template < + class Derived + , class Value + , class AccessCategory + , class TraversalCategory + , class Reference = /* see below */ + , class Difference = ptrdiff_t + > + class iterator_facade { + public: + typedef remove_cv::type value_type; + typedef Reference reference; + typedef /* see description of operator-> */ pointer; + typedef Difference difference_type; + typedef iterator_tag iterator_category; + + reference operator*() const; + /* see below */ operator->() const; + /* impl defined */ operator[](difference_type n) const; + Derived& operator++(); + Derived operator++(int); + Derived& operator--(); + Derived operator--(int); + Derived& operator+=(difference_type n); + Derived& operator-=(difference_type n); + Derived operator-(difference_type n) const; + }; + + // Comparison operators + template + typename enable_if_interoperable::type // exposition + operator ==(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator !=(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator <(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator <=(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator >(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator >=(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator >=(iterator_facade const& lhs, + iterator_facade const& rhs); + + // Iterator difference + template + typename enable_if_interoperable::type + operator -(iterator_facade const& lhs, + iterator_facade const& rhs); + + // Iterator addition + template + Derived operator+ (iterator_facade const&, + typename Derived::difference_type n) + + +[*Note:* The ``enable_if_interoperable`` template used above is for exposition +purposes. The member operators should be only be in an overload set +provided the derived types ``Dr1`` and ``Dr2`` are interoperable, by +which we mean they are convertible to each other. The +``enable_if_interoperable`` approach uses SFINAE to take the operators +out of the overload set when the types are not interoperable.] + + +.. we need a new label here because the presence of markup in the + title prevents an automatic link from being generated + +.. _iterator facade requirements: + +``iterator_facade`` requirements +-------------------------------- + +The ``Derived`` template parameter must be a class derived from +``iterator_facade``. + +The default for the ``Reference`` parameter is `Value&`` if the access +category for ``iterator_facade`` is implicitly convertible to +``writable_iterator_tag``, and ``const Value&`` otherwise. + +The following table describes the other requirements on the +``Derived`` parameter. Depending on the resulting iterator's +``iterator_category``, a subset of the expressions listed in the table +are required to be valid. The operations in the first column must be +accessible to member functions of class ``iterator_core_access``. + +In the table below, ``X`` is the derived iterator type, ``a`` is an +object of type ``X``, ``b`` and ``c`` are objects of type ``const X``, +``n`` is an object of ``X::difference_type``, ``y`` is a constant +object of a single pass iterator type interoperable with X, and ``z`` +is a constant object of a random access traversal iterator type +interoperable with ``X``. + ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| Expression | Return Type | Assertion/Note/Precondition/Postcondition | Required to implement Iterator Concept(s) | +| | | | | ++========================================+========================================+=================================================+===========================================+ +| ``c.dereference()`` | ``X::reference`` | | Readable Iterator, Writable Iterator | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| ``c.equal(b)`` | convertible to bool |true iff ``b`` and ``c`` are equivalent. | Single Pass Iterator | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| ``c.equal(y)`` | convertible to bool |true iff ``c`` and ``y`` refer to the same | Single Pass Iterator | +| | |position. Implements ``c == y`` and ``c != y``. | | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| ``a.advance(n)`` | unused | | Random Access Traversal Iterator | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| ``a.increment()`` | unused | | Incrementable Iterator | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| ``a.decrement()`` | unused | | Bidirectional Traversal Iterator | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| ``c.distance_to(b)`` | convertible to X::difference_type | equivalent to ``distance(c, b)`` | Random Access Traversal Iterator | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| ``c.distance_to(z)`` | convertible to X::difference_type |equivalent to ``distance(c, z)``. Implements ``c| Random Access Traversal Iterator | +| | |- z``, ``c < z``, ``c <= z``, ``c > z``, and ``c | | +| | |>= c``. | | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ + + +.. We should explain more about how the + functions in the interface of iterator_facade + are there conditionally. -JGS + + +``iterator_facade`` operations +------------------------------ + +The operations in this section are described in terms of operations on +the core interface of ``Derived`` which may be inaccessible +(i.e. private). The implementation should access these operations +through member functions of class ``iterator_core_access``. + +``reference operator*() const;`` + +:Returns: ``static_cast(this)->dereference()`` + +*see below* ``operator->() const;`` + +:Returns: If ``X::reference`` is a reference type, returns an object + of type ``X::pointer`` equal to:: + + &static_cast(this)->dereference() + + Otherwise returns an object of unspecified type such that, given an + object ``a`` of type ``X``, ``a->m`` is equivalent to ``(w = *a, + w.m)`` for some temporary object ``w`` of type ``X::value_type``. + + The type ``X::pointer`` is ``Value*`` if the access category for + ``X`` is implicitly convertible to ``writable_iterator_tag``, and + ``Value const*`` otherwise. + + +*unspecified* ``operator[](difference_type n) const;`` + +:Returns: an object convertible to ``X::reference`` and holding a copy + *p* of ``a+n`` such that, for a constant object ``v`` of type + ``X::value_type``, ``X::reference(a[n] = v)`` is equivalent + to ``p = v``. + + + +``Derived& operator++();`` + +:Effects: + + :: + + static_cast(this)->increment(); + return *this; + +.. I realize that the committee is moving away from specifying things + like this in terms of code, but I worried about the imprecision of + saying that a core interface function is invoked without describing + the downcast. An alternative to what I did would be to mention it + above where we talk about accessibility. + + +``Derived operator++(int);`` + +:Effects: + + :: + + Derived tmp(static_cast(this)); + ++*this; + return tmp; + + +``Derived& operator--();`` + +:Effects: + + :: + + static_cast(this)->decrement(); + return *this; + + +``Derived operator--(int);`` + +:Effects: + + :: + + Derived tmp(static_cast(this)); + --*this; + return tmp; + + +``Derived& operator+=(difference_type n);`` + +:Effects: + + :: + + static_cast(this)->advance(n); + return *this; + + +``Derived& operator-=(difference_type n);`` + +:Effects: + + :: + + static_cast(this)->advance(-n); + return *this; + + +``Derived operator-(difference_type n) const;`` + +:Effects: + + Derived tmp(static_cast(this)); + return tmp -= n; + +:Returns: ``static_cast(this)->advance(-n);`` + + +Iterator adaptor [lib.iterator.adaptor] +======================================= + +The ``iterator_adaptor`` is a base class template derived from an +instantiation of ``iterator_facade``. The core interface functions +expected by ``iterator_facade`` are implemented in terms of the +``iterator_adaptor``\ 's ``Base`` template parameter. A class derived +from ``iterator_adaptor`` typically redefines some of the core +interface functions to adapt the behavior of the ``Base`` type. +Whether the derived class models any of the standard iterator concepts +depends on the operations supported by the ``Base`` type and which +core interface functions of ``iterator_facade`` are redefined in the +``Derived`` class. + + +Class template ``iterator_adaptor`` +----------------------------------- + +:: + + template < + class Derived + , class Base + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default + > + class iterator_adaptor + : public iterator_facade + { + friend class iterator_core_access; + public: + iterator_adaptor(); + explicit iterator_adaptor(Base iter); + Base base() const; + protected: + Base const& base_reference() const; + Base& base_reference(); + private: // Core iterator interface for iterator_facade. + typename iterator_adaptor::reference dereference() const; + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + bool equal(iterator_adaptor const& x) const; + + void advance(typename iterator_adaptor::difference_type n); + void increment(); + void decrement(); + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + typename iterator_adaptor::difference_type distance_to( + iterator_adaptor const& y) const; + + private: + Base m_iterator; + }; + + + +``iterator_adaptor`` requirements +--------------------------------- + +The ``Derived`` template parameter must be a derived class of +``iterator_adaptor``. The ``Base`` type must implement the expressions +involving ``m_iterator`` in the specifications of those private member +functions of ``iterator_adaptor`` that are not redefined by the +``Derived`` class and that are needed to model the concept +corresponding to the chosen ``Category`` according to the requirements +of ``iterator_facade``. The rest of the template parameters specify +the types for the member typedefs in ``iterator_facade``. The +following pseudo-code specifies the traits types for +``iterator_adaptor``. + +:: + + if (Value == use_default) + value_type = iterator_traits::value_type; + else + value_type = remove_cv::type; + + if (Reference == use_default) { + if (Value == use_default) + reference = iterator_traits::reference; + else + reference = Value&; + } else + reference = Reference; + + if (Distance == use_default) + difference_type = iterator_traits::difference_type; + else + difference_type = Distance; + + if (Category == use_default) + iterator_category = iterator_tag< + access_category< + iterator< iterator_traits::iterator_category, + Value, + Distance, + Value*, + Reference > >, + traversal_category< + iterator< iterator_traits::iterator_category, + Value, + Distance, + Value*, + Reference > > + else + iterator_category = Category; + + +.. Replaced with new semantics --thw + if (Category == use_default) + iterator_category = iterator_traits::iterator_category; + else + iterator_category = Category; + + + +``iterator_adaptor`` public operations +-------------------------------------- + +``iterator_adaptor();`` + +:Requires: The ``Base`` type must be Default Constructible. +:Returns: An instance of ``iterator_adaptor`` with + ``m_iterator`` default constructed. + + +``explicit iterator_adaptor(Base iter);`` + +:Returns: An instance of ``iterator_adaptor`` with + ``m_iterator`` copy constructed from ``iter``. + +``Base base() const;`` + +:Returns: ``m_iterator`` + + +``iterator_adaptor`` protected member functions +----------------------------------------------- + +``Base const& base_reference() const;`` + +:Returns: A const reference to ``m_iterator``. + + +``Base& base_reference();`` + +:Returns: A non-const reference to ``m_iterator``. + + +``iterator_adaptor`` private member functions +--------------------------------------------- + +``typename iterator_adaptor::reference dereference() const;`` + +:Returns: ``*m_iterator`` + +:: + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + bool equal(iterator_adaptor const& x) const; + +:Returns: ``m_iterator == x.base()`` + + +``void advance(typename iterator_adaptor::difference_type n);`` + +:Effects: ``m_iterator += n;`` + +``void increment();`` + +:Effects: ``++m_iterator;`` + +``void decrement();`` + +:Effects: ``--m_iterator;`` + +:: + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + typename iterator_adaptor::difference_type distance_to( + iterator_adaptor const& y) const; + +:Returns: ``y.base() - m_iterator`` + + + +Specialized adaptors [lib.iterator.special.adaptors] +==================================================== + +.. The requirements for all of these need to be written *much* more + formally -DWA + + +[*Note:* The ``enable_if_convertible::type`` expression used in +this section is for exposition purposes. The converting constructors +for specialized adaptors should be only be in an overload set provided +that an object of type ``X`` is implicitly convertible to an object of +type ``Y``. The ``enable_if_convertible`` approach uses SFINAE to +take the constructor out of the overload set when the types are not +implicitly convertible.] + + +Indirect iterator +----------------- + +The indirect iterator adapts an iterator by applying an *extra* +dereference inside of ``operator*()``. For example, this iterator +adaptor makes it possible to view a container of pointers +(e.g. ``list``) as if it were a container of the pointed-to type +(e.g. ``list``) . + +.. At some point we should add the capability to handle + iterators over smart pointers, which the impl handles. -JGS + + +Class template ``indirect_iterator`` +.................................... + +:: + + template < + class Iterator + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default + > + class indirect_iterator + : public iterator_adaptor + { + friend class iterator_core_access; + public: + indirect_iterator(); + indirect_iterator(Iterator x); + template < + class Iterator2, class Value2, class Category2 + , class Reference2, class Difference2 + > + indirect_iterator( + indirect_iterator< + Iterator2, Value2, Category2, Reference2, Difference2 + > const& y + , typename enable_if_convertible::type* = 0 // exposition + ); + private: // as-if specification + typename indirect_iterator::reference dereference() const + { + return **this->base(); + } + }; + +``indirect_iterator`` requirements +.................................. + +The ``value_type`` of the ``Iterator`` template parameter should +itself be dereferenceable. The return type of the ``operator*`` for +the ``value_type`` must be the same type as the ``Reference`` template +parameter. The ``Value`` template parameter will be the ``value_type`` +for the ``indirect_iterator``, unless ``Value`` is const. If ``Value`` +is ``const X``, then ``value_type`` will be *non-* ``const X``. The +default for ``Value`` is + +:: + + iterator_traits< iterator_traits::value_type >::value_type + +If the default is used for ``Value``, then there must be a valid +specialization of ``iterator_traits`` for the value type of the base +iterator. + +The ``Reference`` parameter will be the ``reference`` type of the +``indirect_iterator``. The default is ``Value&``. + +The ``Category`` parameter is the ``iterator_category`` type for the +``indirect_iterator``. The default is +``iterator_traits::iterator_category``. + +The indirect iterator will model the most refined standard traversal +concept that is modeled by the ``Iterator`` type. The indirect +iterator will model the most refined standard access concept that is +modeled by the value type of ``Iterator``. + + +``indirect_iterator`` operations +................................ + +``indirect_iterator();`` + +:Requires: ``Iterator`` must be Default Constructible. +:Returns: An instance of ``indirect_iterator`` with + a default constructed base object. + + +``indirect_iterator(Iterator x);`` + +:Returns: An instance of ``indirect_iterator`` with + the ``iterator_adaptor`` subobject copy constructed from ``x``. + +:: + + template < + class Iterator2, class Value2, class Category2 + , class Reference2, class Difference2 + > + indirect_iterator( + indirect_iterator< + Iterator2, Value2, Category2, Reference2, Difference2 + > const& y + , typename enable_if_convertible::type* = 0 // exposition + ); + +:Requires: ``Iterator2`` is implicitly convertible to ``Iterator``. +:Returns: An instance of ``indirect_iterator`` that is a copy of ``y``. + +Reverse iterator +---------------- + +.. I think we'd better strike the old reverse_iterator text from the standard, eh? + +The reverse iterator adaptor flips the direction of a base iterator's +motion. Invoking ``operator++()`` moves the base iterator backward and +invoking ``operator--()`` moves the base iterator forward. + +Class template ``reverse_iterator`` +................................... + +:: + + template + class reverse_iterator : + public iterator_adaptor< reverse_iterator, Iterator > + { + friend class iterator_core_access; + public: + reverse_iterator() {} + explicit reverse_iterator(Iterator x) ; + + template + reverse_iterator( + reverse_iterator const& r + , typename enable_if_convertible::type* = 0 // exposition + ); + + private: // as-if specification + typename reverse_iterator::reference dereference() const { return *prior(this->base()); } + + void increment() { --this->base_reference(); } + void decrement() { ++this->base_reference(); } + + void advance(typename reverse_iterator::difference_type n) + { + this->base_reference() += -n; + } + + template + typename reverse_iterator::difference_type + distance_to(reverse_iterator const& y) const + { + return this->base_reference() - y.base(); + } + + }; + + +``reverse_iterator`` requirements +................................. + +The base ``Iterator`` must be a model of Bidirectional Traversal +Iterator. The resulting ``reverse_iterator`` will be a model of the +most refined standard traversal and access concepts that are modeled +by ``Iterator``. + + +``reverse_iterator();`` + +:Requires: ``Iterator`` must be Default Constructible. +:Returns: An instance of ``reverse_iterator`` with a + default constructed base object. + +``explicit reverse_iterator(Iterator x);`` + +:Returns: An instance of ``reverse_iterator`` with a + base object copy constructed from ``x``. + + +:: + + template + reverse_iterator( + reverse_iterator const& r + , typename enable_if_convertible::type* = 0 // exposition + ); + +:Requires: ``OtherIterator`` is implicitly convertible to ``Iterator``. +:Returns: An instance of ``reverse_iterator`` that is a copy of ``r``. + + +Transform iterator +------------------ + +The transform iterator adapts an iterator by applying some function +object to the result of dereferencing the iterator. In other words, +the ``operator*`` of the transform iterator first dereferences the +base iterator, passes the result of this to the function object, and +then returns the result. + + +Class template ``transform_iterator`` +..................................... + +:: + + template + class transform_iterator + : public iterator_adaptor + { + friend class iterator_core_access; + public: + transform_iterator(); + transform_iterator(Iterator const& x, AdaptableUnaryFunction f); + + template + transform_iterator( + transform_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition + ); + + AdaptableUnaryFunction functor() const; + private: + typename transform_iterator::value_type dereference() const; + AdaptableUnaryFunction m_f; + }; + + +``transform_iterator`` requirements +................................... + +The type ``AdaptableUnaryFunction`` must be Assignable, Copy +Constructible, and the expression ``f(x)`` must be valid where ``f`` +is an object of type ``AdaptableUnaryFunction``, ``x`` is an object of +type ``AdaptableUnaryFunction::argument_type``, and where the type of +``f(x)`` must be ``AdaptableUnaryFunction::result_type``. + +The type ``Iterator`` must at least model Readable Iterator. The +resulting ``transform_iterator`` models the most refined of the +following options that is also modeled by ``Iterator``. + + * Writable Lvalue Iterator if the ``result_type`` of the + ``AdaptableUnaryFunction`` is a non-const reference. + + * Readable Lvalue Iterator if the ``result_type`` is a const + reference. + + * Readable Iterator otherwise. + + +The ``transform_iterator`` models the most refined standard traversal +concept that is modeled by ``Iterator``. + +The ``value_type`` of ``transform_iterator`` is +``remove_reference::type``. The ``reference`` type is +``result_type``. + + +``transform_iterator`` public operations +........................................ + + +``transform_iterator();`` + +:Returns: An instance of ``transform_iterator`` with ``m_f`` + and ``m_iterator`` default constructed. + + +``transform_iterator(Iterator const& x, AdaptableUnaryFunction f);`` + +:Returns: An instance of ``transform_iterator`` with ``m_f`` + initialized to ``f`` and ``m_iterator`` initialized to ``x``. + + +:: + + template + transform_iterator( + transform_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition + ); + +:Returns: An instance of ``transform_iterator`` that is a copy of ``t``. +:Requires: ``OtherIterator`` is implicitly convertible to ``Iterator``. + +``AdaptableUnaryFunction functor() const;`` + +:Returns: ``m_f`` + +``transform_iterator`` private operations +......................................... + +``typename transform_iterator::value_type dereference() const;`` + +:Returns: ``m_f(transform_iterator::dereference());`` + + + +Filter iterator +--------------- + +The filter iterator adaptor creates a view of an iterator range in +which some elements of the range are skipped over. A predicate +function object controls which elements are skipped. When the +predicate is applied to an element, if it returns ``true`` then the +element is retained and if it returns ``false`` then the element is +skipped over. When skipping over elements, it is necessary for the +filter adaptor to know when to stop so as to avoid going past the end +of the underlying range. Therefore the constructor of the filter +iterator takes two iterator parameters: the position for the filtered +iterator and the end of the range. + + + +Class template ``filter_iterator`` +.................................. + +:: + + template + class filter_iterator + : public iterator_adaptor< + filter_iterator, Iterator + , use_default + , /* see details */ + > + { + public: + filter_iterator(); + filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()); + filter_iterator(Iterator x, Iterator end = Iterator()); + template + filter_iterator( + filter_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition + ); + Predicate predicate() const; + Iterator end() const; + + private: // as-if specification + void increment() + { + ++(this->base_reference()); + satisfy_predicate(); + } + + void satisfy_predicate() + { + while (this->base() != this->m_end && !this->m_predicate(*this->base())) + ++(this->base_reference()); + } + + Predicate m_predicate; + Iterator m_end; + }; + + +``filter_iterator`` requirements +-------------------------------- + +The base ``Iterator`` parameter must be a model of Readable Iterator +and Single Pass Iterator. The resulting ``filter_iterator`` will be a +model of Forward Traversal Iterator if ``Iterator`` is, otherwise the +``filter_iterator`` will be a model of Single Pass Iterator. The +access category of the ``filter_iterator`` will be the most refined +standard access category that is modeled by ``Iterator``. + +.. Thomas is going to try implementing filter_iterator so that + it will be bidirectional if the underlying iterator is. -JGS + + +The ``Predicate`` must be Assignable, Copy Constructible, and the +expression ``p(x)`` must be valid where ``p`` is an object of type +``Predicate``, ``x`` is an object of type +``iterator_traits::value_type``, and where the type of +``p(x)`` must be convertible to ``bool``. + + + +``filter_iterator`` operations +------------------------------ + +``filter_iterator();`` + +:Requires: ``Predicate`` and ``Iterator`` must be Default Constructible. +:Returns: a ``filter_iterator`` whose + predicate is a default constructed ``Predicate`` and + whose ``end`` is a default constructed ``Iterator``. + + +``filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());`` + +:Returns: A ``filter_iterator`` at position ``x`` that filters according + to predicate ``f`` and that will not increment past ``end``. + + +``filter_iterator(Iterator x, Iterator end = Iterator());`` + +:Requires: ``Predicate`` must be Default Constructible. +:Returns: A ``filter_iterator`` at position ``x`` that filters + according to a default constructed ``Predicate`` + and that will not increment past ``end``. + + +:: + + template + filter_iterator( + filter_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition + );`` + +:Requires: ``OtherIterator`` is implicitly convertible to ``Iterator``. +:Returns: A copy of iterator ``t``. + + +``Predicate predicate() const;`` + +:Returns: A copy of the predicate object used to construct ``*this``. + + +``Iterator end() const;`` + +:Returns: The object ``end`` used to construct ``*this``. + + +Counting iterator +----------------- + +The counting iterator adaptor implements dereference by returning a +reference to the base object. The other operations are implemented by +the base ``m_iterator``, as per the inheritance from +``iterator_adaptor``. + + +Class template ``counting_iterator`` +.................................... + +:: + + template + class counting_iterator + : public iterator_adaptor< + counting_iterator + , Incrementable + , Incrementable + , /* see details for category */ + , Incrementable const& + , Incrementable const* + , /* distance = Difference or a signed integral type */> + { + friend class iterator_core_access; + public: + counting_iterator(); + counting_iterator(counting_iterator const& rhs); + counting_iterator(Incrementable x); + private: + typename counting_iterator::reference dereference() const + { + return this->base_reference(); + } + }; + + +[*Note:* implementers are encouraged to provide an implementation of + ``distance_to`` and a ``difference_type`` that avoids overflows in + the cases when the ``Incrementable`` type is a numeric type.] + +``counting_iterator`` requirements +---------------------------------- + +The ``Incrementable`` type must be Default Constructible, Copy +Constructible, and Assignable. The default distance is +an implementation defined signed integegral type. + +The resulting ``counting_iterator`` models Readable Lvalue Iterator. + +Furthermore, if you wish to create a counting iterator that is a Forward +Traversal Iterator, then the following expressions must be valid: +:: + + Incrementable i, j; + ++i // pre-increment + i == j // operator equal + +If you wish to create a counting iterator that is a +Bidirectional Traversal Iterator, then pre-decrement is also required: +:: + + --i + +If you wish to create a counting iterator that is a Random Access +Traversal Iterator, then these additional expressions are also +required: +:: + + counting_iterator::difference_type n; + i += n + n = i - j + i < j + + + + +``counting_iterator`` operations +-------------------------------- + +``counting_iterator();`` + +:Returns: A default constructed instance of ``counting_iterator``. + + +``counting_iterator(counting_iterator const& rhs);`` + +:Returns: An instance of ``counting_iterator`` that is a copy of ``rhs``. + + + +``counting_iterator(Incrementable x);`` + +:Returns: An instance of ``counting_iterator`` with its base + object copy constructed from ``x``. + + +Function output iterator +------------------------ + +The function output iterator adaptor makes it easier to create custom +output iterators. The adaptor takes a unary function and creates a +model of Output Iterator. Each item assigned to the output iterator is +passed as an argument to the unary function. The motivation for this +iterator is that creating a conforming output iterator is non-trivial, +particularly because the proper implementation usually requires a +proxy object. + + +Class template ``function_output_iterator`` +........................................... + +:: + + template + class function_output_iterator { + public: + typedef iterator_tag< + writable_iterator_tag + , incrementable_iterator_tag + > iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + explicit function_output_iterator(const UnaryFunction& f = UnaryFunction()); + + struct output_proxy { + output_proxy(UnaryFunction& f); + template output_proxy& operator=(const T& value); + }; + output_proxy operator*(); + function_output_iterator& operator++(); + function_output_iterator& operator++(int); + }; + + +``function_output_iterator`` requirements +----------------------------------------- + +The ``UnaryFunction`` must be Assignable, Copy Constructible, and the +expression ``f(x)`` must be valid, where ``f`` is an object of type +``UnaryFunction`` and ``x`` is an object of a type accepted by ``f``. +The resulting ``function_output_iterator`` is a model of the Writable +and Incrementable Iterator concepts. + + +``function_output_iterator`` operations +--------------------------------------- + +``explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());`` + +:Returns: An instance of ``function_output_iterator`` with + ``f`` stored as a data member. + + +``output_proxy operator*();`` + +:Returns: An instance of ``output_proxy`` constructed with + a copy of the unary function ``f``. + + +``function_output_iterator& operator++();`` + +:Returns: ``*this`` + + +``function_output_iterator& operator++(int);`` + +:Returns: ``*this`` + + +``function_output_iterator::output_proxy`` operations +----------------------------------------------------- + +``output_proxy(UnaryFunction& f);`` + +:Returns: An instance of ``output_proxy`` with ``f`` stored as + a data member. + + +``template output_proxy& operator=(const T& value);`` + +:Effects: + :: + + m_f(value); + return *this; + + + +.. [Cop95] [Coplien, 1995] Coplien, J., Curiously Recurring Template + Patterns, C++ Report, February 1995, pp. 24-27. + +.. + LocalWords: Abrahams Siek Witt istream ostream iter MTL strided interoperate + LocalWords: CRTP metafunctions inlining lvalue JGS incrementable BGL LEDA cv + LocalWords: GraphBase struct ptrdiff UnaryFunction const int typename bool pp + LocalWords: lhs rhs SFINAE markup iff tmp OtherDerived OtherIterator DWA foo + LocalWords: dereferenceable subobject AdaptableUnaryFunction impl pre ifdef'd + LocalWords: OtherIncrementable Coplien diff --git a/doc/iterator-categories.html b/doc/iterator-categories.html new file mode 100644 index 0000000..eb76523 --- /dev/null +++ b/doc/iterator-categories.html @@ -0,0 +1,822 @@ + +Improved Iterator Categories and Requirements + + + +

+
Improved Iterator Categories and Requirements

+

Introduction

The standard iterator categories and requirements are +flawed because they use a single hierarchy of requirements to address two +orthogonal issues: iterator traversal and dereference return +type. The current iterator requirement hierarchy is mainly geared +towards iterator traversal (hence the category names), while requirements that +address dereference return type sneak in at various places. The following table +gives a summary of the current dereference return type requirements in the +iterator categories. +

+

+ + + + + + + + + + + + + + +
Output Iterator*i = a
Input Iterator*i is convertible to T
Forward Iterator*i is T& (or const T& once issue + 200 is resolved)
Random Access Iteratori[n] is convertible to T (which is odd because the + operational semantics say i[n] is equivalent to *(i + n) + which would have a return type of T&)
Table 1. Summary of current dereference return type + requirements.
+

Examples of useful iterators that do not ``fit''

+

Because of the mixing of iterator traversal and dereference return type, many +useful iterators can not be appropriately categorized. For example, +vector<bool>::iterator is almost a random access iterator, but +the return type is not bool& (see +issue 96 +and Herb Sutter's paper J16/99-0008 = WG21 N1185). Therefore, the +iterators only meet the requirements of input iterator and output iterator. This +is so nonintuitive that at least one implementation erroneously assigns +random_access_iterator_tag as its iterator_category. Also, +vector<bool> is not the only example of useful iterators that do +not return true references: there is the often cited example of disk-based +collections. +

Another example is a counting iterator, an iterator the returns a sequence of +integers when incremented and dereferenced (see boost::counting_iterator). +There are two ways to implement this iterator, 1) make the reference +type be a true reference (a reference to an integer data member of the counting +iterator) or 2) make the reference type be the same as the +value_type. Option 1) runs into the problems discussed in Issue +198, the reference will not be valid after the iterator is destroyed. Option +2) is therefore a better choice, but then we have a counting iterator that +cannot be a random access iterator. +

Yet another example is a transform iterator, an iterator adaptor that applies +a unary function object to the dereference value of the wrapped iterator (see boost::transform_iterator). +For unary functions such as std::times the return type of +operator* clearly needs to be the result_type of the function +object, which is typically not a reference. However, with the current iterator +requirements, if you wrap int* with a transform iterator, you do not +get a random access iterator as expected, but an input iterator. +

A fourth example is found in the vertex and edge iterators of the Boost Graph +Library. These iterators return vertex and edge descriptors, which are +lightweight handles created on-the-fly. They must be returned by-value. As a +result, their current standard iterator category is +std::input_iterator_tag, which means that, strictly speaking, you could +not use these iterators with algorithms like std::min_element(). As a +temporary solution, we introduced the concept Multi-Pass +Input Iterator to describe the vertex and edge descriptors, but as the +design notes for concept suggest, a better solution is needed. +

In short, there are many useful iterators that do not fit into the current +standard iterator categories. As a result, the following bad things happen: +

    +
  • Iterators are often miss-categorized. +
  • Algorithm requirements are more strict than necessary, because they can + not separate out the need for random-access from the need for a true reference + return type.
+

Proposal for new iterator categories and requirements

The iterator +requirements should be separated into two hierarchies. One set of concepts +handles the return type semantics: +The other set of concepts handles iterator +traversal: + + +

The current Input Iterator and Output Iterator requirements will +continue to be used as is. Note that Input Iterator implies Readable +Iterator and Output Iterator implies Writable Iterator.

+ +

Note: we considered defining a Single-Pass Iterator, which could be +combined with Readable or Writable Iterator to replace the Input and +Output Iterator requirements. We rejected this idea because there are +several differences between Input and Output Iterators that make it +hard to merge them: Input Iterator requires Equality Comparable while +Output Iterator does not and Input Iterator requires Assignable while +Output Iterator does not.

+ +

New category tags and traits classes

+ +

The new iterator categories will require new tag classes.

+ +
namespace std {
+
+  // Returns Category Tags
+  struct readable_iterator_tag { };
+  struct writable_iterator_tag { };
+  struct swappable_iterator_tag { };
+  struct mutable_lvalue_iterator_tag : virtual public writable_iterator_tag,
+    virtual public readable_iterator_tag { };
+  struct constant_lvalue_iterator_tag : public readable_iterator_tag { };
+
+  // Traversal Category Tags
+  struct input_traversal_tag { };
+  struct output_traversal_tag { };
+  struct forward_traversal_tag { };
+  struct bidirectional_traversal_tag : public forward_traversal_tag { };
+  struct random_access_traversal_tag : public bidirectional_traversal_tag { };
+
+}
+
+ +

Access to the return and traversal tags will be through the +following two traits classes, which have a member typedef named +type that provides the tag type. We explain the +definitions of these classes later.

+ +
+  template <typename Iterator>
+  struct return_category; // contains: typedef ... type;
+
+  template <typename Iterator>
+  struct traversal_category; // contains: typedef ... type;
+
+ +

We want it to be convenient for programmers to create iterators +that satisfy both the old and new iterator requirements. Therefore +the following class is provided as a way to create tags for use as the +old iterator_category typedef within +iterator_traits. + +

namespace std {
+  template <class ReturnTag, class TraversalTag>
+  struct iterator_tag : cvt_iterator_category<ReturnTag, TraversalTag>::type
+  {
+    typedef ReturnTag returns;
+    typedef TraversalTag traversal;
+  };
+
+ +

The cvt_iterator_category template computes the +appropriate old iterator category based on the return and traversal +category.

+ +
namespace std {
+  template <class RC, class TC>
+  struct cvt_iterator_category
+  {
+    // Pseudo-code, <= means inherits or same type
+    if (RC <= constant_lvalue_iterator_tag || RC <= mutable_lvalue_iterator_tag) {
+      if (TC <= random_access_traversal_tag)
+        typedef random_access_iterator_tag type;
+      else if (TC <= bidirectional_traversal_tag)
+        typedef bidirectional_iterator_tag type;
+      else if (TC <= forward_traversal_tag)
+        typedef forward_iterator_tag type;
+      else
+        error;
+   } else if (RC <= readable_iterator_tag && RC <= input_traversal_tag)
+     typedef input_iterator_tag type;
+   else if (RC <= writable_iterator_tag && output_traversal_tag)
+     typedef output_iterator_tag type;
+   else
+     error;
+  };
+}
+
+ +

The following is an example of a new iterator class using the +iterator_tag class to create its iterator_category +member typedef.

+ +
+struct my_iterator {
+  typedef std::iterator_tag<std::readable_iterator_tag, 
+    std::random_access_traversal_tag> iterator_category;
+  ...
+};
+
+ +We also want old iterators to work with new algorithms, that is, +algorithms that use the new iterator categories. We facilitate this by +defining the return_category and traversal_category +in such a way as they can be used with both old and new iterators. +For old iterators, the appropriate return and traversal categories are +computed based on the old iterator category. For new iterators, the +return and traversal tags are extracted from within the +iterator_category tag. + + +
+  template <typename Iterator>
+  class return_category
+  {
+    // Pseudo-code
+    typedef iterator_traits<Iterator>::iterator_category tag;
+    typedef iterator_traits<Iterator>::value_type T;
+  public:
+    if (exists(tag::returns)) // must be a new iterator
+      typedef tag::returns type;
+    else if (tag <= forward_iterator_tag) {
+      if (is-const(T))
+        typedef constant_lvalue_iterator_tag type;
+      else
+        typedef mutable_lvalue_iterator_tag type;
+    } else if (tag <= input_iterator_tag)
+      typedef readable_iterator_tag type;
+    else if (tag <= output_iterator_tag)
+      typedef writable_iterator_tag type;
+    else
+      error;
+  };
+
+  template <typename T>
+  struct return_category<T*>
+  {
+    // Pseudo-code
+    if (is-const(T))
+      typedef boost::constant_lvalue_iterator_tag type;
+    else
+      typedef boost::mutable_lvalue_iterator_tag type;
+  };
+
+  template <typename Iterator>
+  class traversal_category
+  {
+    typedef iterator_traits<Iterator>::iterator_category tag;
+  public:
+    // Pseudo-code
+    if (exists(tag::traversal)) // must be a new iterator
+      typedef tag::traversal type;
+    else if (tag <= random_access_iterator_tag)
+      typedef random_access_traversal_tag type;
+    else if (tag <= bidirectional_iterator_tag)
+      typedef bidirectional_traversal_tag type;
+    else if (tag <= is_forward_iterator_tag)
+      typedef forward_traversal_tag type;
+    else if (tag <= input_iterator_tag)
+      typedef input_traversal_tag type;
+    else if (tag <= out_iterator_tag)
+      typedef output_traversal_tag type;
+    else
+      error;
+  };
+
+  template <typename T>
+  struct traversal_category<T*>
+  {
+    typedef random_access_traversal_tag type;
+  };
+
+ +

Impact on the Standard Algorithms

+ +

Many of the standard algorithms place more requirements than +necessary on their iterator parameters due to the coarseness of the +current iterator categories. By using the new iterator categories a +better fit can be achieved, thereby increasing the reusability of the +algorithms. These changes will not affect user-code, though they will +require changes by standard implementers: dispatching should be based +on the new categories, and in places return values may need to be +handled more carefully. In particular, uses of std::swap() +will need to be replaced with std::iter_swap(), and +std::iter_swap() will need to call std::swap().

+ +

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AlgorithmRequirement Change
find_endForward Iterator
-> Forward Traversal Iterator and + Readable Iterator
find_first_of
adjacent_find
search
search_n
rotate_copy
lower_bound
upper_bound
equal_range
binary_search
min_element
max_element
iter_swapForward Iterator
-> Swappable Iterator
fillForward Iterator
-> Forward Traversal Iterator and + Writable Iterator
generate
swap_rangesForward Iterator
-> Forward Traversal Iterator and + Swappable Iterator
rotate
replaceForward Iterator
-> Forward Traversal Iterator + and
Readable Iterator and Writable Iterator
replace_if
remove
remove_if
unique
reverseBidirectional Iterator
-> Bidirectional Traversal + Iterator and Swappable Iterator
partition
copy_backwardsBidirectional Iterator
-> Bidirectional Traversal Iterator and + Readable Iterator
Bidirectional Iterator
-> Bidirectional + Traversal Iterator and Writable Iterator
next_permutationBidirectional Iterator
-> Bidirectional Traversal + Iterator and
Swappable Iterator and Readable Iterator
prev_permutation
stable_partitionBidirectional Iterator
-> Bidirectional Traversal + Iterator and
Readable Iterator and Writable Iterator
inplace_merge
reverse_copyBidirectional Iterator
-> Bidirectional Traversal Iterator and + Readable Iterator
random_shuffleRandom Access Iterator
-> Random Access Traversal + Iterator and Swappable Iterator
sort
stable_sort
partial_sort
nth_element
push_heap
pop_heap
make_heap
sort_heap
Table 2. Requirement changes for standard + algorithms.
+

The New Iterator Requirements

+

Notation

+ + + + + + + + + + + + + +
XThe iterator type.
TThe value type of X, i.e., + std::iterator_traits<X>::value_type.
x, yAn object of type X.
tAn object of type T.
+

+


+ +

Readable Iterator

A Readable +Iterator is an iterator that dereferences to produce an rvalue that is +convertible to the value_type of the iterator. +

Associated Types

+ + + + + + + + + + + + + +
Value typestd::iterator_traits<X>::value_typeThe type of the objects pointed to by the iterator.
Reference typestd::iterator_traits<X>::referenceThe return type of dereferencing the iterator. This type must be + convertible to T.
Return Categorystd::return_category<X>::typeA type convertible to std::readable_iterator_tag +
+

Refinement of

Copy +Constructible +

Valid expressions

+ + + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Dereference*x std::iterator_traits<X>::reference
Member accessx->mT is a type with a member named m.If m is a data member, the type of m. If m + is a member function, the return type of m.
+

+


+ +

Writable Iterator

A Writable +Iterator is an iterator that can be used to store a value using the +dereference-assignment expression. +

Definitions

If x is an Writable Iterator of type X, +then the expression *x = a; stores the value a into +x. Note that operator=, like other C++ functions, may be +overloaded; it may, in fact, even be a template function. In general, then, +a may be any of several different types. A type A belongs to +the set of value types of X if, for an object a of type +A, *x = a; is well-defined and does not require performing any +non-trivial conversions on a. +

Associated Types

+ + + + + +
Return Categorystd::return_category<X>::typeA type convertible to std::writable_iterator_tag +
+

Refinement of

Copy +Constructible +

Valid expressions

+ + + + + + + + + +
NameExpressionReturn type
Dereference assignment*x = aunspecified
+

+


+ +

Swappable Iterator

A Swappable +Iterator is an iterator whose dereferenced values can be swapped. +

Note: the requirements for Swappable Iterator are dependent on the issues +surrounding std::swap() being resolved. Here we assume that the issue +will be resolved by allowing the overload of std::swap() for +user-defined types. +

Note: Readable Iterator and Writable Iterator combined implies Swappable +Iterator because of the fully templated std::swap(). However, Swappable +Iterator does not imply Readable Iterator nor Writable Iterator. +

Associated Types

+ + + + + +
Return Categorystd::return_category<X>::typeA type convertible to std::swappable_iterator_tag +
+

Valid expressions

Of the two valid expressions listed below, only one +OR the other is required. If std::iter_swap() is overloaded for +X then std::swap() is not required. If +std::iter_swap() is not overloaded for X then the default +(fully templated) version is used, which will call std::swap() (this +means changing the current requirements for std::iter_swap()). +

+ + + + + + + + + + + + + +
NameExpressionReturn type
Iterator Swapstd::iter_swap(x, y)void
Dereference and Swapstd::swap(*x, *y)void
+

+


+ +

Constant Lvalue Iterator

A +Constant Lvalue Iterator is an iterator that dereferences to produce a const +reference to the pointed-to object, i.e., the associated reference type +is const T&. Changing the value of or destroying an iterator that +models Constant Lvalue Iterator does not invalidate pointers and references +previously obtained from that iterator. +

Refinement of

Readable +Iterator +

Associated Types

+ + + + + + + + + +
Reference typestd::iterator_traits<X>::referenceThe return type of dereferencing the iterator, which must be const + T&.
Return Categorystd::return_category<X>::typeA type convertible to std::constant_lvalue_iterator_tag +
+

+


+ +

Mutable Lvalue Iterator

A +Mutable Lvalue Iterator is an iterator that dereferences to produce a reference +to the pointed-to object. The associated reference type is +T&. Changing the value of or destroying an iterator that models +Mutable Lvalue Iterator does not invalidate pointers and references previously +obtained from that iterator. +

Refinement of

Readable +Iterator, Writable +Iterator, and Swappable +Iterator. +

Associated Types

+ + + + + + + + + +
Reference typestd::iterator_traits<X>::referenceThe return type of dereferencing the iterator, which must be + T&.
Return Categorystd::return_category<X>::typeA type convertible to std::mutable_lvalue_iterator_tag +
+

+


+ +

Forward Traversal Iterator +

The Forward Iterator is an iterator that can be incremented. Also, it is +permissible to make multiple passes through the iterator's range. +

Refinement of

Copy +Constructible, Assignable, Default +Constructible, and Equality +Comparable +

Associated types

+ + + + + + + + + +
Difference Typestd::iterator_traits<X>::difference_typeA signed integral type used for representing distances between + iterators that point into the same range.
Traversal Categorystd::traversal_category<X>::typeA type convertible to std::forward_traversal_tag +
+

Valid expressions

+ + + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Preincrement++i X&
Postincrementi++ convertible to const X&
+

+


+ +

Bidirectional Traversal +Iterator

An iterator that can be incremented and decremented. +

Refinement of

Forward +Traversal Iterator +

Associated types

+ + + + + +
Traversal Categorystd::traversal_category<X>::typeA type convertible to std::bidirectional_traversal_tag +
+

Valid expressions

+ + + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Predecrement--i X&
Postdecrementi-- convertible to const X&
+

+


+ +

Random Access Traversal +Iterator

An iterator that provides constant-time methods for moving forward +and backward in arbitrary-sized steps. +

Refinement of

Bidirectional +Traversal Iterator and Less Than +Comparable where < is a total ordering +

Associated types

+ + + + + +
Traversal Categorystd::traversal_category<X>::typeA type convertible to std::random_access_traversal_tag +
+

Valid expressions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Iterator additioni += n X&
Iterator additioni + n or n + i X
Iterator subtractioni -= n X&
Iterator subtractioni - n X
Differencei - j std::iterator_traits<X>::difference_type
Element operatori[n]X must also be a model of Readable + Iterator. std::iterator_traits<X>::reference
Element assignmenti[n] = tX must also be a model of Writable + Iterator.unspecified
+

+


+ diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst new file mode 100644 index 0000000..cd29dbe --- /dev/null +++ b/doc/new-iter-concepts.rst @@ -0,0 +1,731 @@ +++++++++++++++++++++++ + New Iterator Concepts +++++++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organization: `Boost Consulting`_, Indiana University `Open Systems Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ +:date: $Date$ +:Number: N1477=03-0060 +:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:Abstract: We propose a new system of iterator concepts that treat + access and positioning independently. This allows the + concepts to more closely match the requirements + of algorithms and provides better categorizations + of iterators that are used in practice. This proposal + is a revision of paper n1297_. + +.. contents:: Table of Contents + +.. _n1297: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2001/n1297.html + +============ + Motivation +============ + +The standard iterator categories and requirements are flawed because +they use a single hierarchy of concepts to address two orthogonal +issues: *iterator traversal* and *value access*. As a result, many +algorithms with requirements expressed in terms of the iterator +categories are too strict. Also, many real-world iterators can not be +accurately categorized. A proxy-based iterator with random-access +traversal, for example, may only legally have a category of "input +iterator", so generic algorithms are unable to take advantage of its +random-access capabilities. The current iterator concept hierarchy is +geared towards iterator traversal (hence the category names), while +requirements that address value access sneak in at various places. The +following table gives a summary of the current value access +requirements in the iterator categories. + ++------------------------+-------------------------------------------------------------------------+ +| Output Iterator | ``*i = a`` | ++------------------------+-------------------------------------------------------------------------+ +| Input Iterator | ``*i`` is convertible to ``T`` | ++------------------------+-------------------------------------------------------------------------+ +| Forward Iterator | ``*i`` is ``T&`` (or ``const T&`` once | +| | `issue 200`_ is resolved) | ++------------------------+-------------------------------------------------------------------------+ +| Random Access Iterator | ``i[n]`` is convertible to ``T`` (also ``i[n] = t`` is required for | +| | mutable iterators once `issue 299`_ is resolved) | ++------------------------+-------------------------------------------------------------------------+ + +.. _issue 200: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#200 +.. _issue 299: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#299 + + +Because iterator traversal and value access are mixed together in a +single hierarchy, many useful iterators can not be appropriately +categorized. For example, ``vector::iterator`` is almost a +random access iterator, but the return type is not ``bool&`` (see +`issue 96`_ and Herb Sutter's paper J16/99-0008 = WG21 +N1185). Therefore, the iterators of ``vector`` only meet the +requirements of input iterator and output iterator. This is so +nonintuitive that at least one implementation erroneously assigns +``random_access_iterator_tag`` as its ``iterator_category``. + +.. _issue 96: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#96 + +Another difficult-to-categorize iterator is the transform iterator, an +adaptor which applies a unary function object to the dereferenced +value of the some underlying iterator (see `transform_iterator`_). +For unary functions such as ``times``, the return type of +``operator*`` clearly needs to be the ``result_type`` of the function +object, which is typically not a reference. Because random access +iterators are required to return lvalues from ``operator*``, if you +wrap ``int*`` with a transform iterator, you do not get a random +access iterator as might be expected, but an input iterator. + +.. _`transform_iterator`: http://www.boost.org/libs/utility/transform_iterator.htm + +A third example is found in the vertex and edge iterators of the +`Boost Graph Library`_. These iterators return vertex and edge +descriptors, which are lightweight handles created on-the-fly. They +must be returned by-value. As a result, their current standard +iterator category is ``input_iterator_tag``, which means that, +strictly speaking, you could not use these iterators with algorithms +like ``min_element()``. As a temporary solution, the concept +`Multi-Pass Input Iterator`_ was introduced to describe the vertex and +edge descriptors, but as the design notes for the concept suggest, a +better solution is needed. + +.. _Boost Graph Library: http://www.boost.org/libs/graph/doc/table_of_contents.html +.. _Multi-Pass Input Iterator: http://www.boost.org/libs/utility/MultiPassInputIterator.html + +In short, there are many useful iterators that do not fit into the +current standard iterator categories. As a result, the following bad +things happen: + +- Iterators are often mis-categorized. + +- Algorithm requirements are more strict than necessary, because they + cannot separate the need for random access or bidirectional + traversal from the need for a true reference return type. + + +======================== + Impact on the Standard +======================== + +The new iterator concepts are backward-compatible with the old +iterator requirements, and old iterators are forward-compatible with +the new iterator concepts. That is to say, iterators that satisfy the +old requirements also satisfy appropriate concepts in the new system, +and iterators modeling the new concepts will automatically satisfy the +appropriate old requirements. + +.. I think we need to say something about the resolution to allow + convertibility to any of the old-style tags as a TR issue (hope it + made it). -DWA + +.. Hmm, not sure I understand. Are you talking about whether a + standards conforming input iterator is allowed to have + a tag that is not input_iterator_tag but that + is convertible to input_iterator_tag? -JGS + +The algorithms in the standard library benefit from the new iterator +concepts because the new concepts provide a more accurate way to +express their type requirements. The result is algorithms that are +usable in more situations and have fewer type requirements. The +following lists the proposed changes to the type requirements of +algorithms. + +Forward Iterator -> Forward Traversal Iterator and Readable Iterator + ``find_end, adjacent_find, search, search_n, rotate_copy, lower_bound, upper_bound, equal_range, binary_search, min_element, max_element`` + +Forward Iterator (1) -> Single Pass Iterator and Readable Iterator +Forward Iterator (2) -> Forward Traversal Iterator and Readable Iterator + ``find_first_of`` + +Forward Iterator -> Readable Iterator and Writable Iterator + ``iter_swap`` + +Forward Iterator -> Single Pass Iterator and Writable Iterator + ``fill, generate`` + +Forward Iterator -> Forward Traversal Iterator and Swappable Iterator + ``rotate`` + +Forward Iterator (1) -> Swappable Iterator and Single Pass Iterator +Forward Iterator (2) -> Swappable Iterator and Incrementable Iterator + ``swap_ranges`` + +Forward Iterator -> Forward Traversal Iterator and Readable Iterator and Writable Iterator + ``remove, remove_if, unique`` + +Forward Iterator -> Single Pass Iterator and Readable Iterator and Writable Iterator + ``replace, replace_if`` + +Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator + ``reverse`` + +Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable and Swappable Iterator + ``partition`` + +Bidirectional Iterator (1) -> Bidirectional Traversal Iterator and Readable Iterator, +Bidirectional Iterator (2) -> Bidirectional Traversal Iterator and Writable Iterator + ``copy_backwards`` + +Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator and Readable Iterator + ``next_permutation, prev_permutation`` + +Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator and Writable Iterator + ``stable_partition, inplace_merge`` + +Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator + ``reverse_copy`` + +Random Access Iterator -> Random Access Traversal Iterator and Readable and Swappable Iterator + ``random_shuffle, sort, stable_sort, partial_sort, nth_element, push_heap, pop_heap + make_heap, sort_heap`` + +Input Iterator (2) -> Incrementable Iterator and Readable Iterator + ``equal`` + +Input Iterator (2) -> Incrementable Iterator and Readable Iterator + ``transform`` + +======== + Design +======== + +The iterator requirements are be separated into two hierarchies. One +set of concepts handles the syntax and semantics of value access: + +- Readable Iterator +- Writable Iterator +- Swappable Iterator +- Readable Lvalue Iterator +- Writable Lvalue Iterator + +The refinement relationships among these iterator concepts are given +in the following diagram. + +.. image:: access.png + +The access concepts describe requirements related to ``operator*`` and +``operator->``, including the ``value_type``, ``reference``, and +``pointer`` associated types. + +The other set of concepts handles traversal: + +- Incrementable Iterator +- Single Pass Iterator +- Forward Traversal Iterator +- Bidirectional Traversal Iterator +- Random Access Traversal Iterator + +The refinement relationships for the traversal concepts are in the +following diagram. + +.. image:: traversal.png + +In addition to the iterator movement operators, such as +``operator++``, the traversal concepts also include requirements on +position comparison such as ``operator==`` and ``operator<``. The +reason for the fine grain slicing of the concepts into the +Incrementable and Single Pass is to provide concepts that are exact +matches with the original input and output iterator requirements. + +The relationship between the new iterator concepts and the old are +given in the following diagram. + +.. image:: oldeqnew.png + +Like the old iterator requirements, we provide tags for purposes of +dispatching. There are two hierarchies of tags, one for the access +concepts and one for the traversal concepts. We provide an access +mechanism for mapping iterator types to these new tags. Our design +reuses ``iterator_traits::iterator_category`` as the access +mechanism. To enable this, a pair of access and traversal tags are +combined into a single type using the following `iterator_tag` class. + +:: + + template + struct iterator_tag : /* appropriate old category or categories */ + { + typedef AccessTag access; + typedef TraversalTag traversal; + }; + +The ``iterator_tag`` class template is derived from the appropriate +iterator tag or tags from the old requirements based on the new-style +tags passed as template parameters. The algorithm for determining the +old tag or tags from the new tags picks the least-refined old concepts +that include all of the requirements of the access and traversal +concepts (that is, the closest fit), if any such category exists. For +example, a the category tag for a Readable Single Pass Iterator will +always be derived from ``input_iterator_tag``, while the category tag +for a Single Pass Iterator that is both Readable and Writable will be +derived from both ``input_iterator_tag`` and ``output_iterator_tag``. + +We also provide two helper classes that make it convenient to obtain +the access and traversal tags of an iterator. These helper classes +work both for iterators whose ``iterator_category`` is +``iterator_tag`` and also for iterators using the original iterator +categories. + +:: + + template struct access_category { typedef ... type; }; + template struct traversal_category { typedef ... type; }; + + +The most difficult design decision concerned the ``operator[]``. The +direct approach for specifying ``operator[]`` would have a return type +of ``reference``; the same as ``operator*``. However, going in this +direction would mean that an iterator satisfying the old Random Access +Iterator requirements would not necessarily be a model of Readable or +Writable Lvalue Iterator. Instead we have chosen a design that +matches the preferred resolution of `issue 299`_: ``operator[]`` is +only required to return something convertible to the ``value_type`` +(for a Readable Iterator), and is required to support assignment +``i[n] = t`` (for a Writable Iterator). + + +=============== + Proposed Text +=============== + +Addition to [lib.iterator.requirements] +======================================= + +Iterator Value Access Concepts [lib.iterator.value.access] +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +In the tables below, ``X`` is an iterator type, ``a`` is a constant +object of type ``X``, ``T`` is +``std::iterator_traits::value_type``, and ``v`` is a constant +object of type ``T``. + +.. _Readable Iterator: + +Readable Iterators [lib.readable.iterators] +------------------------------------------- + +A class or built-in type ``X`` models the *Readable Iterator* concept +for the value type ``T`` if the following expressions are valid and +respect the stated semantics. ``U`` is the type of any specified +member of type ``T``. + + +------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Readable Iterator Requirements (in addition to CopyConstructible) | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition | + +======================================+===================================================+=================================================================+ + | ``iterator_traits::value_type`` | ``T`` | Any non-reference, non-cv-qualified type | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + | ``iterator_traits::reference`` | Convertible to ``iterator_traits::value_type`` | | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + | ``access_category::type`` | Convertible to ``readable_iterator_tag`` | | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + | ``*a`` | ``iterator_traits::reference`` | pre: ``a`` is dereferenceable. If ``a == b`` then | + | | | ``*a`` is equivalent to ``*b`` | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + | ``a->m`` | ``U&`` | pre: ``(*a).m`` is well-defined. Equivalent to ``(*a).m`` | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + + +.. _Writable Iterator: + +Writable Iterators [lib.writable.iterators] +------------------------------------------- + +A class or built-in type ``X`` models the *Writable Iterator* concept +if the following expressions are valid and respect the stated +semantics. + +.. A type ``T`` belongs to the *set of value types* of ``X`` + if, for an object ``v`` of type ``T``, ``*a = v`` is valid. + + ** This appears to be a mutual recursion which ends up meaning + nothing. Kill the assertion column? + + Separate but related question: Is a writable iterator required + to have a meaningful value_type? If not, we need to use a + different name from ``v`` in this table -DWA + ++------------------------------------------------------------------------------------------------------------------------------+ +| Writable Iterator Requirements (in addition to CopyConstructible) | ++--------------------------------------+------------------------------------------+--------------------------------------------+ +| Expression | Return Type | Assertion/Note/Precondition/Postcondition | ++======================================+==========================================+============================================+ +| ``access_category::type`` | Convertible to ``writable_iterator_tag`` | | ++--------------------------------------+------------------------------------------+--------------------------------------------+ +| ``*a = v`` | | .. ** pre: The type of ``v`` is in the set | +| | | of value types of ``X`` | ++--------------------------------------+------------------------------------------+--------------------------------------------+ + + +Swappable Iterators [lib.swappable.iterators] +--------------------------------------------- + +A class or built-in type ``X`` models the *Swappable Iterator* concept +if the following expressions are valid and respect the stated +semantics. + + +------------------------------------------------------------------------------------------------+ + | Swappable Iterator Requirements (in addition to CopyConstructible) | + +------------------------------------+-------------+---------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition | + +====================================+=============+=============================================+ + | ``iter_swap(a, b)`` | ``void`` | post: the pointed to values are exchanged | + +------------------------------------+-------------+---------------------------------------------+ + +[*Note:* An iterator that is a model of the *Readable* and *Writable Iterator* concepts + is also a model of *Swappable Iterator*. *--end note*] + + +Readable Lvalue Iterators [lib.readable.lvalue.iterators] +--------------------------------------------------------- + +The *Readable Lvalue Iterator* concept adds the requirement that the +``reference`` type be a reference to the value type of the iterator. + + +--------------------------------------------------------------------------------------------------------------------------------------------------+ + | Readable Lvalue Iterator Requirements (in addition to Readable Iterator) | + +------------------------------------+-------------------------------------------------+-----------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition | + +====================================+=================================================+===========================================================+ + | ``iterator_traits::reference`` | ``T&`` | ``T`` is *cv* ``iterator_traits::value_type`` where | + | | | *cv* is an optional cv-qualification | + +------------------------------------+-------------------------------------------------+-----------------------------------------------------------+ + | ``access_category::type`` | Convertible to ``readable_lvalue_iterator_tag`` | | + +------------------------------------+-------------------------------------------------+-----------------------------------------------------------+ + + +Writable Lvalue Iterators [lib.writable.lvalue.iterators] +--------------------------------------------------------- + +The *Writable Lvalue Iterator* concept adds the requirement that the +``reference`` type be a non-const reference to the value type of the +iterator. + + +------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Writable Lvalue Iterator Requirements (in addition to Readable Lvalue Iterator) | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition | + +======================================+==================================================+============================================================+ + | ``iterator_traits::reference`` | ``iterator_traits::value_type&`` | | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + | ``access_category::type`` | Convertible to ``writable_lvalue_iterator_tag`` | | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + + +Iterator Traversal Concepts [lib.iterator.traversal] +++++++++++++++++++++++++++++++++++++++++++++++++++++ + +In the tables below, ``X`` is an iterator type, ``a`` and ``b`` are +constant objects of type ``X``, ``r`` and ``s`` are mutable objects of +type ``X``, ``T`` is ``std::iterator_traits::value_type``, and +``v`` is a constant object of type ``T``. + + +Incrementable Iterators [lib.incrementable.iterators] +----------------------------------------------------- + +A class or built-in type ``X`` models the *Incrementable Iterator* +concept if the following expressions are valid and respect the stated +semantics. + + + +------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Incrementable Iterator Requirements (in addition to Assignable, Copy Constructible) | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition | + +======================================+==================================================+============================================================+ + | ``++r`` | ``X&`` | ``&r == &++r`` | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + | ``r++`` | convertible to ``const X&`` | ``{ X tmp = r; ++r; return tmp; }`` | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + | ``traversal_category::type`` | | Convertible to ``incrementable_iterator_tag`` | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + + +Single Pass Iterators [lib.single.pass.iterators] +------------------------------------------------- + +A class or built-in type ``X`` models the *Single Pass Iterator* +concept if the following expressions are valid and respect the stated +semantics. + + +------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality Comparable) | + +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition/Semantics | + +==================================+=========================+=========================================================================================+ + | ``++r`` | ``X&`` | pre: ``r`` is dereferenceable; post: ``r`` is dereferenceable or ``r`` is past-the-end | + +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ + | ``a == b`` | convertible to ``bool`` | ``==`` is an equivalence relation over its domain | + +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ + | ``a != b`` | convertible to ``bool`` | ``!(a == b)`` | + +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ + | ``traversal_category::type`` | | Convertible to ``single_pass_iterator_tag`` | + +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ + + +Forward Traversal Iterators [lib.forward.traversal.iterators] +------------------------------------------------------------- + +A class or built-in type ``X`` models the *Forward Traversal Iterator* +concept if the following expressions are valid and respect the stated +semantics. + + +----------------------------------------------------------------------------------------------------------------------------------+ + | Forward Traversal Iterator Requirements (in addition to Single Pass Iterator) | + +------------------------------------------+--------------+------------------------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition/Semantics | + +==========================================+==============+========================================================================+ + | ``X u;`` | ``X&`` | ``note: u may have a singular value.`` | + +------------------------------------------+--------------+------------------------------------------------------------------------+ + | ``++r`` | ``X&`` | ``r == s`` and ``r`` is dereferenceable implies ``++r == ++s.`` | + +------------------------------------------+--------------+------------------------------------------------------------------------+ + | ``iterator_traits::difference_type`` | | A signed integral type representing the distance between iterators | + +------------------------------------------+--------------+------------------------------------------------------------------------+ + | ``traversal_category::type`` | | Convertible to ``forward_traversal_iterator_tag`` | + +------------------------------------------+--------------+------------------------------------------------------------------------+ + + +Bidirectional Traversal Iterators [lib.bidirectional.traversal.iterators] +------------------------------------------------------------------------- + +A class or built-in type ``X`` models the *Bidirectional Traversal +Iterator* concept if the following expressions are valid and respect +the stated semantics. + + +-------------------------------------------------------------------------------------------------------------+ + |Bidirectional Traversal Iterator Requirements (in addition to Forward Traversal Iterator) | + +-----------------------------------------+-------------+-----------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition/Semantics | + +=========================================+=============+=====================================================+ + | ``--r`` | ``X&`` |pre: there exists ``s`` such that ``r == ++s``. | + | | |post: ``s`` is dereferenceable. ``--(++r) == r``. | + | | |``--r == --s`` implies ``r == s``. ``&r == &--r``. | + +-----------------------------------------+-------------+-----------------------------------------------------+ + |``r--`` |convertible |``{ X tmp = r; --r; return tmp; }`` | + | |to ``const | | + | |X&`` | | + +-----------------------------------------+-------------+-----------------------------------------------------+ + | ``traversal_category::type`` | | Convertible to | + | | | ``bidirectional_traversal_iterator_tag`` | + | | | | + +-----------------------------------------+-------------+-----------------------------------------------------+ + + +Random Access Traversal Iterators [lib.random.access.traversal.iterators] +------------------------------------------------------------------------- + +A class or built-in type ``X`` models the *Random Access Traversal +Iterator* concept if the following expressions are valid and respect +the stated semantics. In the table below, ``Distance`` is +``iterator_traits::difference_type`` and ``n`` represents a +constant object of type ``Distance``. + + +--------------------------------------------------------------------------------------------------------------------------------------------+ + | Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal Iterator) | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + | Expression | Return Type | Operational Semantics | Assertion/Note/Pre/Post-condition | + +================================+=======================================+==========================+========================================+ + |``r += n`` | ``X&`` |:: | | + | | | | | + | | | { | | + | | | Distance m = n; | | + | | | if (m >= 0) | | + | | | while (m--) | | + | | | ++r; | | + | | | else | | + | | | while (m++) | | + | | | --r; | | + | | | return r; | | + | | | } | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + | ``a + n``, ``n + a`` | ``X`` |``{ X tmp = a; return tmp | | + | | |+= n; }`` | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``r -= n`` | ``X&`` |``return r += -n`` | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a - n`` | ``X`` |``{ X tmp = a; return tmp | | + | | |-= n; }`` | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``b - a`` |``Distance`` |``a < b ? distance(a,b) : |pre: there exists a value ``n`` of | + | | |-distance(b,a)`` |``Distance`` such that ``a + n == b``. | + | | | |``b == a + (b - a)``. | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a[n]`` |convertible to T |``*(a + n)`` |pre: a is a `readable iterator`_ | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a[n] = v`` |convertible to T |``*(a + n) = v`` |pre: a is a `writable iterator`_ | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a < b`` |convertible to ``bool`` |``b - a > 0`` |``<`` is a total ordering relation | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a > b`` |convertible to ``bool`` |``b < a`` |``>`` is a total ordering relation | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a >= b`` |convertible to ``bool`` |``!(a < b)`` | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a <= b`` |convertible to ``bool`` |``!(a > b)`` | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``traversal_category::type`` | | |Convertible to | + | | | |``random_access_traversal_iterator_tag``| + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + + + +Addition to [lib.iterator.synopsis] +=================================== + +:: + + // lib.iterator.traits, traits and tags + template struct access_category; + template struct traversal_category; + + template + struct iterator_tag : /* appropriate old category or categories */ { + typedef AccessTag access; + typedef TraversalTag traversal; + }; + + struct readable_iterator_tag { }; + struct writable_iterator_tag { }; + struct swappable_iterator_tag { }; + struct readable_writable_iterator_tag + : virtual readable_iterator_tag + , virtual writable_iterator_tag + , virtual swappable_iterator_tag { }; + struct readable_lvalue_iterator_tag { }; + struct writable_lvalue_iterator_tag + : virtual public readable_writable_iterator_tag + , virtual public readable_lvalue_iterator_tag { }; + + struct incrementable_iterator_tag { }; + struct single_pass_iterator_tag : incrementable_iterator_tag { }; + struct forward_traversal_tag : single_pass_iterator_tag { }; + struct bidirectional_traversal_tag : forward_traversal_tag { }; + struct random_access_traversal_tag : bidirectional_traversal_tag { }; + + struct null_category_tag { }; + struct input_output_iterator_tag : input_iterator_tag, output_iterator_tag {}; + +Addition to [lib.iterator.traits] +================================= + +The ``iterator_tag`` class template is an iterator category tag that +encodes the access and traversal tags in addition to being compatible +with the original iterator tags. The ``iterator_tag`` class inherits +from one of the original iterator tags according to the following +pseudo-code. + +:: + + inherit-category(access-tag, traversal-tag) = + if (access-tag is convertible to readable_lvalue_iterator_tag) { + if (traversal-tag is convertible to random_access_traversal_tag) + return random_access_iterator_tag; + else if (traversal-tag is convertible to bidirectional_traversal_tag) + return bidirectional_iterator_tag; + else if (traversal-tag is convertible to forward_traversal_tag) + return forward_iterator_tag; + else if (traversal-tag is convertible to single_pass_traversal_tag) + if (access-tag is convertible to writable_iterator_tag) + return input_output_iterator_tag; + else + return input_iterator_tag; + else if (access-tag is convertible to writable_iterator_tag) + return output_iterator_tag; + else + return null_category_tag; + } else if (access-tag is convertible to readable_writable_iterator_tag + and traversal-tag is convertible to single_pass_iterator_tag) + return input_output_iterator_tag; + else if (access-tag is convertible to readable_iterator_tag + and traversal-tag is convertible to single_pass_iterator_tag) + return input_iterator_tag; + else if (access-tag is convertible to writable_iterator_tag + and traversal-tag is convertible to incrementable_iterator_tag) + return output_iterator_tag; + else + return null_category_tag; + + +The ``access_category`` and ``traversal_category`` class templates are +traits classes. For iterators whose +``iterator_traits::iterator_category`` type is ``iterator_tag``, +the ``access_category`` and ``traversal_category`` traits access the +``access`` and ``traversal`` member types within ``iterator_tag``. +For iterators whose ``iterator_traits::iterator_category`` type +is not ``iterator_tag`` and instead is a tag convertible to one of the +original tags, the appropriate traversal and access tags is deduced. +The following pseudo-code describes the algorithm. + +:: + + access-category(Iterator) = + cat = iterator_traits::iterator_category; + if (cat == iterator_tag) + return Access; + else if (cat is convertible to forward_iterator_tag) { + if (iterator_traits::reference is a const reference) + return readable_lvalue_iterator_tag; + else + return writable_lvalue_iterator_tag; + } else if (cat is convertible to input_iterator_tag) + return readable_iterator_tag; + else if (cat is convertible to output_iterator_tag) + return writable_iterator_tag; + else + return null_category_tag; + + traversal-category(Iterator) = + cat = iterator_traits::iterator_category; + if (cat == iterator_tag) + return Traversal; + else if (cat is convertible to random_access_iterator_tag) + return random_access_traversal_tag; + else if (cat is convertible to bidirectional_iterator_tag) + return bidirectional_traversal_tag; + else if (cat is convertible to forward_iterator_tag) + return forward_traversal_tag; + else if (cat is convertible to input_iterator_tag) + return single_pass_iterator_tag; + else if (cat is convertible to output_iterator_tag) + return incrementable_iterator_tag; + else + return null_category_tag; + + +The following specializations provide the access and traversal +category tags for pointer types. + +:: + + template + struct access_category + { + typedef readable_lvalue_iterator_tag type; + }; + template + struct access_category + { + typedef writable_lvalue_iterator_tag type; + }; + + template + struct traversal_category + { + typedef random_access_traversal_tag type; + }; + + + +.. + LocalWords: Abrahams Siek Witt const bool Sutter's WG int UL LI href Lvalue + LocalWords: ReadableIterator WritableIterator SwappableIterator cv pre iter + LocalWords: ConstantLvalueIterator MutableLvalueIterator CopyConstructible TR + LocalWords: ForwardTraversalIterator BidirectionalTraversalIterator lvalue + LocalWords: RandomAccessTraversalIterator dereferenceable Incrementable tmp + LocalWords: incrementable xxx min prev inplace png oldeqnew AccessTag struct + LocalWords: TraversalTag typename lvalues DWA Hmm JGS diff --git a/doc/oldeqnew.png b/doc/oldeqnew.png new file mode 100644 index 0000000000000000000000000000000000000000..30cd1598cb0b5f4cc54a8c600b7d55de7de270d5 GIT binary patch literal 33786 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 z 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 literal 0 HcmV?d00001 diff --git a/doc/traversal.png b/doc/traversal.png new file mode 100644 index 0000000000000000000000000000000000000000..a9bbe981a1c3b6492afdbb0786018aec326433c1 GIT binary patch literal 9112 zcmZ{K2RxSV+xJC6D7TDk8QE0!mOCq(ls&R#%bpEnkF4yUB&jIbJ0W{h_MT-coBKWV z|2@z9e4h97-k<7@x?JaZUdQoW#~r4jrf`vfngBtNi+2=dwcz~~{I12vhCl03H_zU1 ztYuVX5aeU4@cHl+1i6abk(JT*N?*(HymeP+szn_?2qnbB@s#?Nip+)EI5>vxWLM}! zoEr%BOT(Y(m;T(bVHg$rX_L*1>cgiP|L4BU7cH{OA=vjX5PX&miNry(Fdozfrk8u~ zphm?=N7H&t_D)^bH;yZ&e7hxCgr{N=#CAU~CwCoN;4OAkXV5KXe#YKb6?_3c(*OA- zZfqysC0a#wbsbM~f0Bsiz~B9IEivWxBmHbIQ&Li5V>dnQe7xa*ReNqEwORZuoUONU zbQHRIb7gI9ZEq+|*y;P=;O`5pY;5IaWpyY0#?eohcH-I8Go}2+tU6zom6d({`ZXyj zDIp;tGLp#q+2P?~P*6~3r;1;{w}i2(s;ZovoQum%wBl9N>o;dF4|n&O-I0-zjEoGp zzp&$YtWxg1d-uY^!uHlD;@LiY_@JVs)ZWq2Slxc&;pW!V(n3tdhr@6!PSJ6qDls8} zB{`{aCX!xKjEn2n{??qkySqs1f~%yYBncXcO-oCA`SPtF$6G8)%5>?#$#36q5i@gh z*b1z;#ypooYL%yAC}`O=xf&!+P7iv{0DlX_zfjT?UZ zo72;#tns1`2idbVh9@W0nBrJfQ^{y)?M+Q@xc}5h)dg5uUPCIXs>H;^aB*>~ zs;W{`Qc6oo+}zzY*%Q{+9pe-QTxMlWOs4Yh=4s^*8k9Tc@62Npk)0hEB`qxxqMXco zk%%ZkDHqvnW6L_;Y$P@-@@fht+3!qBPVPw;B}JCq4$BE>bsi6ql9F2L$=X<7XN_;WbLWmoab@K}FyR$fS64$rL&OxG zBaM*#m$hUbgEGenv3r>+mL)@yX~ztPyuvqbpqy66%GH&X2^j}_d*Qg}W@mM|zkhnr zh(hn~?&jy`mzI`Z4zuV;;$gYWaqZf|Oyl#Le_#07a5B_UNhv9!fv0{nG&DiIjn9d5 zUcEx0Vc`PQUH$#8-RYua1lPE^i5Lg_`ebtY4q^2bhU;<63Me$Qd?Y(BZzjLBn!mrl zu`zu_Gbb;vhqLobVJCXDqOx+wmoHxi2NN1+rjNRXr~LQ>j`!svC>Vp3l$EW!Qgbs0 zI2CGjsN^{lsVOPv7ZxrAqX~kU$Oy1*aZ}vQAB4(=hZV3l;aRZ&4Msyvt)->)MlB

)uMijb**qppUA?DBG9c6Qhkub^OJgDHE` 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 literal 0 HcmV?d00001 diff --git a/example/Jamfile b/example/Jamfile new file mode 100644 index 0000000..921ff30 --- /dev/null +++ b/example/Jamfile @@ -0,0 +1 @@ +unit-test ia1 : reverse_iterator.cpp : ../../.. $(BOOST) ; \ No newline at end of file diff --git a/example/reverse_iterator.cpp b/example/reverse_iterator.cpp new file mode 100644 index 0000000..ffe6e3d --- /dev/null +++ b/example/reverse_iterator.cpp @@ -0,0 +1,16 @@ +#include +#include +#include +#include +#include + +int main() +{ + int x[] = { 1, 2, 3, 4 }; + boost::reverse_iterator + , std::ptrdiff_t> first(x + 4), last(x); + std::copy(first, last, std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + return 0; +} diff --git a/include/boost/iterator/detail/categories.hpp b/include/boost/iterator/detail/categories.hpp new file mode 100644 index 0000000..48d1e3d --- /dev/null +++ b/include/boost/iterator/detail/categories.hpp @@ -0,0 +1,338 @@ +// (C) Copyright Thomas Witt 2002. Permission to copy, use, modify, +// sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. + +#ifndef BOOST_ITERATOR_DETAIL_CATEGORIES_HPP +# define BOOST_ITERATOR_DETAIL_CATEGORIES_HPP + +# include +# include + +# include + +# include +# include + +# include +# include +# include +# include +# include +# include + +# include + +namespace boost +{ + + // faked new old-style categories needed to make new->old mapping + // work + namespace detail + { + struct null_category_tag {}; + struct input_output_iterator_tag : std::input_iterator_tag, std::output_iterator_tag {}; + } + + // + // Access Categories + // + struct readable_iterator_tag + { + typedef std::input_iterator_tag max_category; + }; + + struct writable_iterator_tag + { + typedef std::output_iterator_tag max_category; + }; + + struct swappable_iterator_tag + { + typedef detail::null_category_tag max_category; + }; + + struct readable_writable_iterator_tag + : virtual readable_iterator_tag + , virtual writable_iterator_tag + , virtual swappable_iterator_tag + { + typedef detail::input_output_iterator_tag max_category; + }; + + struct readable_lvalue_iterator_tag + : virtual readable_iterator_tag + { + typedef std::random_access_iterator_tag max_category; + }; + + struct writable_lvalue_iterator_tag + : virtual public readable_writable_iterator_tag + , virtual public readable_lvalue_iterator_tag + { + typedef std::random_access_iterator_tag max_category; + }; + + // + // Traversal Categories + // + struct incrementable_traversal_tag + { + typedef std::output_iterator_tag max_category; + }; + + struct single_pass_traversal_tag + : incrementable_traversal_tag + { + typedef detail::input_output_iterator_tag max_category; + }; + + struct forward_traversal_tag + : single_pass_traversal_tag + { + typedef std::forward_iterator_tag max_category; + }; + + struct bidirectional_traversal_tag + : forward_traversal_tag + { + typedef std::bidirectional_iterator_tag max_category; + }; + + struct random_access_traversal_tag + : bidirectional_traversal_tag + { + typedef std::random_access_iterator_tag max_category; + }; + + struct error_iterator_tag { }; + + namespace detail + { + // + // Tag detection meta functions + // + + // I bet this is defined somewhere else. Let's wait and see. + struct error_type; + +# ifndef BOOST_NO_IS_CONVERTIBLE + + // True iff T is a tag "derived" from Tag + template + struct is_tag + : mpl::or_< + is_convertible + + // Because we can't actually get forward_iterator_tag to + // derive from input_output_iterator_tag, we need this + // case. + , mpl::and_< + is_convertible + , is_convertible + > + > + {}; + + +# else + template + struct is_tag; +# endif + + // Generate specializations which will allow us to find + // null_category_tag as a minimum old-style category for new-style + // iterators which don't have an actual old-style category. We + // need that so there is a valid base class for all new-style + // iterators. +# define BOOST_OLD_ITERATOR_CATEGORY(category) \ + template <> \ + struct is_tag \ + : mpl::true_ {}; + + BOOST_OLD_ITERATOR_CATEGORY(input_iterator_tag) + BOOST_OLD_ITERATOR_CATEGORY(output_iterator_tag) + BOOST_OLD_ITERATOR_CATEGORY(forward_iterator_tag) + BOOST_OLD_ITERATOR_CATEGORY(bidirectional_iterator_tag) + BOOST_OLD_ITERATOR_CATEGORY(random_access_iterator_tag) +# undef BOOST_OLD_ITERATOR_CATEGORY + + template <> + struct is_tag + : mpl::true_ + { + }; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct is_tag : mpl::true_ + {}; + +# ifdef BOOST_NO_IS_CONVERTIBLE + // Workarounds for CWPro7 which can't detect derivation at + // compile-time. + + // Fact of life: we can only detect tag refinement relationships + // among predefined tags. + // + // Algorithm: + // is_tag(T,U) -> + // T == U + // || (exists d in derived_from(T) such that is_tag(d, U)) + // + // T == U case is handled above + + // false by default + template + struct is_tag_impl : mpl::false_ + {}; + + // The generalized template dispatches to is_tag_impl because + // is_tag and is_tag are equally specialized. + // This technique simulates making is_tag more-specialized. + template + struct is_tag + : is_tag_impl + {}; + +# define BOOST_ITERATOR_DERIVED_TAG1(base, derived) \ + BOOST_ITERATOR_DERIVED_TAG1_AUX(base, _, derived) + +# define BOOST_ITERATOR_DERIVED_TAG1_AUX(base, underscore, derived) \ + template \ + struct is_tag_impl \ + : is_tag \ + { \ + }; + + // Old-style tag relations + template + struct is_tag_impl + : mpl::or_< + is_tag + , is_tag + > + { + }; + + BOOST_ITERATOR_DERIVED_TAG1(std::output_iterator, detail::input_output_iterator) + BOOST_ITERATOR_DERIVED_TAG1(std::input_iterator, detail::input_output_iterator) + BOOST_ITERATOR_DERIVED_TAG1(detail::input_output_iterator, std::forward_iterator) + BOOST_ITERATOR_DERIVED_TAG1(std::forward_iterator, std::bidirectional_iterator) + BOOST_ITERATOR_DERIVED_TAG1(std::bidirectional_iterator, std::random_access_iterator) + + // Access tag relations + BOOST_ITERATOR_DERIVED_TAG1(readable_lvalue_iterator, writable_lvalue_iterator) + BOOST_ITERATOR_DERIVED_TAG1(swappable_iterator, readable_writable_iterator) + BOOST_ITERATOR_DERIVED_TAG1(readable_writable_iterator, writable_lvalue_iterator) + + template + struct is_tag_impl + : mpl::or_< + is_tag + , is_tag + > + { + }; + + BOOST_ITERATOR_DERIVED_TAG1(writable_iterator, readable_writable_iterator) + + // Traversal tag relations + BOOST_ITERATOR_DERIVED_TAG1(bidirectional_traversal, random_access_traversal) + BOOST_ITERATOR_DERIVED_TAG1(forward_traversal, bidirectional_traversal) + BOOST_ITERATOR_DERIVED_TAG1(single_pass_traversal, forward_traversal) + BOOST_ITERATOR_DERIVED_TAG1(incrementable_traversal, single_pass_traversal) + +# endif // BOOST_NO_IS_CONVERTIBLE workarounds + +# endif // ndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + template + struct known_tag + : mpl::apply_if, mpl::identity, Else> + {}; + + template + struct max_known_traversal_tag + : known_tag< + Tag, random_access_traversal_tag + , known_tag< + Tag, bidirectional_traversal_tag + , known_tag< + Tag, forward_traversal_tag + , known_tag< + Tag, single_pass_traversal_tag + , known_tag< + Tag, incrementable_traversal_tag + , error_iterator_tag + > + > + > + > + > + {}; + + // Doesn't cope with these odd combinations: readable+swappable, + // writable+swappable. That doesn't matter for the sake of + // new-style tag base computation, which is all it's used for + // anyway. + template + struct max_known_access_tag + : known_tag< + Tag, writable_lvalue_iterator_tag + , known_tag< + Tag, readable_lvalue_iterator_tag + , known_tag< + Tag, readable_writable_iterator_tag + , known_tag< + Tag, writable_iterator_tag + , known_tag< + Tag, readable_iterator_tag + , mpl::apply_if< + is_tag + , mpl::identity + , error_iterator_tag + > + > + > + > + > + > + {}; + + // + // Returns the minimum category type or error_type + // if T1 and T2 are unrelated. + // + // For compilers not supporting is_convertible this only + // works with the new boost return and traversal category + // types. The exact boost _types_ are required. No derived types + // will work. + // + // + template + struct minimum_category + : mpl::apply_if< + is_tag + , mpl::identity + , mpl::if_< + is_tag + , T2 + , error_type + > + > + {}; + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + // Deal with ETI + template <> struct minimum_category { typedef minimum_category type; }; +# endif + + } // namespace detail + +} // namespace boost + +#include + +#endif // BOOST_ITERATOR_DETAIL_CATEGORIES_HPP diff --git a/include/boost/iterator/detail/config_def.hpp b/include/boost/iterator/detail/config_def.hpp new file mode 100644 index 0000000..6789d4a --- /dev/null +++ b/include/boost/iterator/detail/config_def.hpp @@ -0,0 +1,104 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// Permission to copy, use, modify, +// sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. + +// no include guard multiple inclusion intended + +// +// This is a temporary workaround until the bulk of this is +// available in boost config. +// 23/02/03 thw +// + +#include // for prior +#include + +#define BOOST_ITERATOR_CONFIG_DEF // if you get an error here, you have nested config_def #inclusion. + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \ + || BOOST_WORKAROUND(__GNUC__, <= 2 && __GNUC_MINOR__ <= 95) \ + || BOOST_WORKAROUND(__MWERKS__, <= 0x3000) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) +# define BOOST_NO_SFINAE // "Substitution Failure Is Not An Error not implemented" + +# if 0 // test code + template + struct bar + { + typedef int type; + }; + + template <> + struct bar + { + }; + + + template + struct foo : bar<(sizeof(T) == 1)> + { + }; + + template + char* f(int, typename foo::type = 0) { return 0; } + + template + int f(...) { return 0; } + + char* x = f(0); + int y = f(0); + + int main() + { + return 0; + } +# endif + +#endif + +#if BOOST_WORKAROUND(__MWERKS__, <=0x2407) +# define BOOST_NO_IS_CONVERTIBLE // "is_convertible doesn't work for simple types" +#endif + +#if BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(3)) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) +# define BOOST_NO_IS_CONVERTIBLE_TEMPLATE // The following program fails to compile: + +# if 0 // test code + template + struct foo + { + foo(T); + + template + foo(foo const& other) : p(other.p) { } + + T p; + }; + + bool x = boost::is_convertible, foo >::value; +# endif + +#endif + +#if BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) \ + || BOOST_WORKAROUND(__MWERKS__, <= 0x2407) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) +# define BOOST_ITERATOR_NO_MPL_AUX_HAS_XXX // "MPL's has_xxx facility doesn't work" +#endif + +#if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_IS_CONVERTIBLE_TEMPLATE) +# define BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY +#endif + +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +# define BOOST_ARG_DEPENDENT_TYPENAME typename +# else +# define BOOST_ARG_DEPENDENT_TYPENAME +# endif + +// no include guard multiple inclusion intended diff --git a/include/boost/iterator/detail/config_undef.hpp b/include/boost/iterator/detail/config_undef.hpp new file mode 100644 index 0000000..f58df62 --- /dev/null +++ b/include/boost/iterator/detail/config_undef.hpp @@ -0,0 +1,26 @@ +// (C) Copyright Thomas Witt 2002. +// Permission to copy, use, modify, +// sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. + +// no include guard multiple inclusion intended + +// +// This is a temporary workaround until the bulk of this is +// available in boost config. +// 23/02/03 thw +// + +#undef BOOST_NO_SFINAE +#undef BOOST_NO_IS_CONVERTIBLE +#undef BOOST_NO_IS_CONVERTIBLE_TEMPLATE +#undef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY +#undef BOOST_ARG_DEPENDENT_TYPENAME + +#ifdef BOOST_ITERATOR_CONFIG_DEF +# undef BOOST_ITERATOR_CONFIG_DEF +#else +# error missing or nested #include config_def +#endif diff --git a/include/boost/iterator/detail/enable_if.hpp b/include/boost/iterator/detail/enable_if.hpp new file mode 100644 index 0000000..d939fbb --- /dev/null +++ b/include/boost/iterator/detail/enable_if.hpp @@ -0,0 +1,88 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// Permission to copy, use, modify, +// sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef BOOST_ENABLE_IF_23022003THW_HPP +#define BOOST_ENABLE_IF_23022003THW_HPP + +#include +#include + +#include + +// +// Boost iterators uses its own enable_if cause we need +// special semantics for deficient compilers. +// 23/02/03 thw +// + +namespace boost +{ + + namespace detail + { + // + // Base machinery for all kinds of enable if + // + template + struct enabled + { + template + struct base + { + typedef T type; + }; + }; + + // + // For compilers that don't support "Substitution Failure Is Not An Error" + // enable_if falls back to always enabled. See comments + // on operator implementation for consequences. + // + template<> + struct enabled + { + template + struct base + { +#ifdef BOOST_NO_SFINAE + + typedef T type; + + // This way to do it would give a nice error message containing + // invalid overload, but has the big disadvantage that + // there is no reference to user code in the error message. + // + // struct invalid_overload; + // typedef invalid_overload type; + // +#endif + }; + }; + + + template + struct enable_if +# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE) + : enabled<(Cond::value)>::template base +# else + : mpl::identity +# endif + { +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + typedef Return type; +# endif + }; + + } // namespace detail + +} // namespace boost + +#include + +#endif // BOOST_ENABLE_IF_23022003THW_HPP