RE: [boost] OutFmt library implementation questions

Use the ex< DelimiterType > variant on the innermost construct.
This is unacceptable and does not follow standard practice.
The new version templates that are templatized on character type are also templatized on the format object that they use (to render their elements).
You keep repeating that you have some completely reworked version. Well let's see it next time. Then I will be able to comment on it.
7. What deducer is supposed to deduce? I couldn't get IMO all that you needed is function overloading. I don't see a place for all these deduce/trats staff.
Consider the pair format object (pair renderer): how do you render each pair type. Using function overloading, you would have:
class basic_pair { public: OutStream & write( OutStream & os, const std::pair< T1, T2 > & p ){ ... } OutStream & write( OutStream & os, const boost::compact_pair< T1, T2 > & p ){ ... } OutStream & write( OutStream & os, const std::complex< T > & p ){ ... } OutStream & write( OutStream & os, const boost::math::interval< T > & p ){ ... } };
But this would add dependencies on those libraries. Also, it is not extensible: how do you add support for boost::rational< T >, for instance?
I am not sure I understand what you writing here. What I meant is something trivial like this: Template<typename C> ContanerFormatter<C> Foo( C const& ); // this together with ContanerFormatter is defined in pair general header Template<...> PairFormatter<..> Foo( pair<...> const& ); // this together with PairFormatter is defined in pair specific header Template<...> RationalFormatter<..> Foo( pair<...> const& ); // this together with RationalFormatter is defined in boost:: specific header And so on. Why wouldn't it work?
Using the deduction mechanism, I implement the output using boost::io::detail::getval< n >( pair_type ). Input is more complex because you need to distinguish between types that you can get the elements separately (e.g. std::pair) and types that you need to set both values together (e.g. boost::math::rational): the former uses refval< n >( type ) and the latter uses assignval( type, first, second ).
How would function overloading solve this? (Note, function overloading is used for getval, refval and assignval).
For containers, you need to use a different function/function arguments to insert an element depending on whether the container is sequential, associative or a set.
If you need to handle input then in addition you would add Template<typename T> VectorFormatter<T> Foo( std::vector<T> const& ); // this together with VectorFormatter is defined in vector specific header
My library provides a description of the types that it can render (e.g. separable pairs, 4-ary types, associative containers) without saying what these types are. The stl and boost directories in my library then tell my library that a std::vector is a sequential container. My library then knows how to handle a std::vector. Doing this, I can separate the dependencies on external libraries and allow it to be extended to support other sequential containers, pairs, etc.
I don't see ANY need for all this complex staff when simple overloading/partial ordering will do the trick.
formatob_t::format returns *this because the FormatObject (Renderer) that it inherits returns a value of type FormatObject. Thus, if you didn't have these overloads, then:
std::cout << formatob( vec ).format( " + " );
would not work, since it will try to output a containerfmt() type.
Your code : inline formatob_t & format( format_type s) { FormatObject::format( s ); return( *this ); } formatob( vec ).format( " + " ) has the same type as formatob( vec ) What are you talking about? Why would you bother what FormatObject::format is returning?
Regards, Reece
Gennadiy.

formatob( vec )
What are you talking about? Why would you bother what FormatObject::format is returning?
So that you can manipulate the formatob() object multiple times, like: formatob().do_this().do_that().and_that_too(); And because it's what needs to be written/read to the stream. Best, John -- John Torjo -- john@torjo.com Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.4 - save_dlg - true binding of your data to UI controls! + easily add validation rules (win32gui/examples/smart_dlg)

"John Torjo" <john.lists@torjo.com> wrote in message news:4152776F.8040303@torjo.com...
inline formatob_t & format( format_type s) { FormatObject::format( s ); return( *this ); }
formatob( vec ).format( " + " )
has the same type as
formatob( vec )
What are you talking about? Why would you bother what
FormatObject::format
is returning?
So that you can manipulate the formatob() object multiple times, like: formatob().do_this().do_that().and_that_too();
[I don't know why you removed original code. Let see it again.] You must be joking. Do you think I can't read code?? formatob().format() return *** *this **** NOT FormatObject::format(); So my question still stand.
And because it's what needs to be written/read to the stream.
Best, John
Actually I just implemented, as a prove of concept, small (~250 lines) header that conceptually does ALL (not 100% sure but it seems like it) that submitted library do in regards to output. It even more flexible and safe. It does not use any deducer. And it does not require any hierarhy of formatters. See also atached example. It compiles and works under VC7.1 Gennadiy. begin 666 OutFrmt.rar M4F%R(1H'`,^0<P``#0````````#6870@D"H`W@(``*$*```"CS-^9@9N-S$= M,P4`( ```&$N8W!P`/ F^BT,&5#,C3T8%7OJ5\':*E9)M$(*MO20!+?![UE% M$R#-C+/RI^"VZ:>[U*%IH2%QMPD90TT)5O6^B/\YG'S.8\8>-9F<;S]/F-?? M<YTYQ+/!.HKK+<>(@JP[#3[];IZ!3VU'JV[=S*1F)Z"\GI,ZQ]'R:-*\X-TK MX:>EAB@CE")EZ-V(D K8G7F)1ZM .*4SON9D<3/OJK>R?&J*R+5,V?IZ$,F5 MXN(4)'Q@\R\U[,OBMVW@$D&YUB-@$L#T[H):(S7+GP77TRXJ`$T#C[<OB7#' M5V6^RKOO)"0M.6B,$;E7P>.3(=Z..ZMEX'**7U#7'@7L[#D;!(&ORI$AR.(> M&: 179T97UOG722+GIM2&G!%*,="6ILATQ3EFNS'CC05JZ,&\H_)Q2RT. /F MV+J'_,W3T9+CG>2POP!!BJ&*U+*:U"-^"B$<:VY5Z6G8+"07#>#\*T3SHQPM M/>6$<)#:"H<NLRU1MA"\X]S[ZK#;+^7>)V!2S>SFSIT"\XG9ILEX'1U!_DB\ ME>U8V<J])H,X<'_&;N@J'!YC<D\+'<HJ%N!M7MB)>!LFEO[K,GN\" T'`(:\ M9NF2W;*X'S8WW!<'<;9/*&P_'"TQA&SXZ_M6;/8$-K\=V9DQ3\*24-:_VX!7 M1*F,%K4X`"-8@)"7]$E5W?Y&CZV229)'[A=HH +Y<&Z:/M+'(<-20D*8Q&7D M`=P<3&K-MD9-T.2PF!$M1*!'<3:_*O%?<IS?-3C ;Y7-3W4Q#-?YUS58N4^K M52!C[^M/$C#XRA#^U,CVV E/NQ\S21+QTWN+J2F4>]HKH#W]\,:^B, >CCSK M$_ 3&7S#.BAVV?6_Y00=)+" CE;&\:M@$3"0A+$J@_C#Y2L$'N;'./96&/'H M[]%$?)'B1^YO!U$CM3/2NXK\`RKA8D1:J8'SF*.:E5QY3\V54D=%?%4(62ET M+!4G_N4YMF(/JH'<_65;^M84??CZ*.!T5D-0_\L^J+@@=""0*@`.!@```2$` M``(*HG[=_&TW,1TS!0`@````82YH<' `L(=OB@P!3,S-%;R4$;?@&?AU\*!> MR7'V46[(W8!>VWH%T44#,FS ()''+']V>#$;DF403_OT#')9&TV4DUX/PGA; M7<[FA:9(D3Q%$\**47Y<^B)7"2.$(G0B2B"4.+2AR-XF<&6ZT)AO&Z]D:MX; M'S^7(B\"ZVOR?34.?G_GW-H?$!GFL+F"WL6'O-QK$.P<5E9'V[6F<>2#/3#+ MLV-NZ*Z:X:M-8(;PC>=J"B0NUZ\C5<HB?1880H38M8V[,LD%/=C%JC-T>D(+ M7:TH3U@R]FA$O"#32VIMB)Z^VZ*VR]EMX,'G%I?QY<$1%R.+RC%:R-LCRV+K M<4 ),1@L[<)-A$O_@KP-S;Q0P[,<`Q4O$0PT0RTX\'SA<A6W<@<1'9%R?/M? M_\L80AIM#=CS%M<``\L$6TW>`/0([#4R=L(]FWOG\E8HB$9,^'PD&2W9LF8L MV#P29X$)B9P."]-7".4"$YD4GX@PJB.F(<P?VB".H:-:XUY1Q5*J^\2WQ=?T M'R5/:ESWVXSZA G_W45$JBD97>$QS FGR^2S=Z"?I]% 5.$8'=:<ME8<P&A1 MIIDPB8S97HU(C?/<QGZ%D_?II2.D;[>1@!H:"([.>SF:<K7AE.I?%NW>;H"A M@&6W:<GCGO/$+1K%`[X4+685.NDG?X8!`P9=;.9;F!MFN9L-?AP/PV\E%J%$ MM_)IU)O*E4Y::XL-I\'V/!C,P0L%U=0E"*=@KBS*=[(V0U,R)CAI*F&*.-*& MO'8V\ N8.5DTD@I4.KUE60;]H9J5*..M[+DQ%6$R.F^D!6WB;H:IEZ-IN&\2 MK/;2LX,*\W^%"NJ8D^08V5 .79J?K.Y;TL/(T0.)O, 1)'Q5J#V5=3(M3F]* MD(=Z0[R]+'B!M,H_!8L9\B!B430*_L+'=5+?_JF9Y.WH4MBJR=SY_.F?_/C: MHO:#7## OX]%<4@//FU[@B/9#\6)>42HST96CK1X%D2CL%(5022%G8PB.IOP M7^)VC;ZTK5!28%U2XI6$1IN6W6V4E/HC5,OY' ->FY#;`Z4[\V1I8RS.L_6! M#G^QIS\\DZU/",FY<B]?<<Y(?(JJ!.!T&IUC4Y0Q.U2L(D9%77-)V94;84^% MGACNMCI:R6-P_<^.?0"%OZ-C6MN#(\X.YB\FRJ4]7$S1S)+94F9W&+BXJ;;? MA9E5^3UTY*C]?V"<Y%/#!UE9!6K VYM/<@!:<1_+H)T>DO%Z^.1(W1$<"1): MB29*4JI2=3D:A0U"0Z+G]>/C]K-KTNNSW]EKK^WV[OK9&%<QAI:.-MVTZ#1L M( +2]EHNG)U<WAMW408)9!/EE8^K%:V:[NCV*!).9P4@V5/V#L1(E)>?EVFQ M@BL@_31-<4S?&O8D4*J^Y3LY%*T\54SO[?#44_#H4Y;OATIH?\,FT@.%GAN- MAVW5Z,"[0[?[-&90+X-(@Y%'7<2$2'7G98Q(,K*HY^5[RR'U.>O)?=F3L3C2 M\'(@W;3<H.$$6SQ\0PKS!BFWCZQLKFU[/<O8%7ENS8GM4 ``05A#S\Y$"B?Z M$41PSN%R/SM-4M0R!@F&Z#=#B!*AL#>TO G'%/X,)F\-)2KH-@-*GRD/WNH/ M$9H]/,J2O*P^G\S(;=36X!$F*IK +U-\T+D";<'Y"[>[L\?KUV?3M>'CV]_] M]_=]8H2NO51<*WWH^.U8$_D^\SCT"Y.0S"!\VGIQ6*%&L&"-`O?V?25V]*'+ M>!R:0_NN.$$-EFMX,K50M[HTB]DQD]]"3+BX\(*>'KCU+ZH>]L^U&\61UR^J MWIXA(?LBI"WZ&0!?]G"0LXD(UF:&05CU&G^MCT]ZE7B)0M5&BEXY255=SIXL MVR^_"--+L8^1IR%75[.%Y_]_VO9N-QZ=]L7I.=^)@+B]P$(YYV<Z$OJAS\W- MSTMPG:'A,(Z:"=@W<;ME#?*\?0E0/8FU6@.,42O7]=4:%H)^:RG5Y%U)IA:? MBG&&['ZE'%F >_<28)_3N&-W&'RI@#Y#6K_DH_'?$\<9/\^Q+F9_':?&E>+W M*\'U3R[\F[7OA(OC?O^CRM)C(5] W@ZJX'GU4>O$Y%43XH*8]0W+B)_*///) *!7^HQ#U[`$ '```` ` end

Gennadiy Rozental wrote:
"John Torjo" <john.lists@torjo.com> wrote in message news:4152776F.8040303@torjo.com...
inline formatob_t & format( format_type s) { FormatObject::format( s ); return( *this ); }
formatob( vec ).format( " + " )
has the same type as
formatob( vec )
What are you talking about? Why would you bother what
FormatObject::format
is returning?
So that you can manipulate the formatob() object multiple times, like: formatob().do_this().do_that().and_that_too();
[I don't know why you removed original code. Let see it again.]
You must be joking. Do you think I can't read code?? formatob().format() return *** *this **** NOT FormatObject::format();
So my question still stand.
FormatObject is conceptually defined as: class FormatObject { inline FormatObject & format( const DelimiterType & s ) { // ... return( *this ); } } I *know* it is not defined like that (it is defined in formatter_t), but that is how it *behaves*. This works since formatter_t takes a ReturnType template parameter that tells formatter_t what to return so you don't need to forward the functions in FormatObject. The formatob_t class - to which you refer to - does need to forward the 'format' functions because it is defined as: template< class FormatObject > class formatob_t: public FormatObject { inline formatob_t & format( const DelimiterType & s ) { FormatObject::format( s ); // return type == FormatObject return( *this ); } }; However... I have just had a brainwave, utilizing a technique like std::allocator::rebind< T >::type. template< typename CharT, class RetType > struct wrapper_decorators { decorator< CharT, 2 > separator; template< class RetType2 > struct rebind { typedef wrapper_decorators< CharT, RetType2 > type; }; inline RetType & decorate( const value_type & s ) { separator = s; return( *static_cast< RetType * >( this )); } }; This would allow: template< typename CharT, class FormatObject > class formatob_t: public FormatObject::rebind< formatob_t< CharT, FormatObject >::type { }; But then this does not address the fact that you can't do: template< typename CharT, class RetType = wrapper_decorators< CharT, RetType > > struct wrapper_decorators; since wrapper_decorators is an incompletly defined type at the point when the default for RetType is defined in the template arguments. This issue can be solved using the current work around. The question is whether: public FormatObject::rebind< formatob_t< CharT, FormatObject >::type will work as expected. It should set the return type for 'decorate' to formatob_t; it should also allow calls to 'read' and 'write' to properly delegate to FormatObject. I have not yet tested whether this works. I should know in a few days. Regards, Reece

The formatob_t class - to which you refer to - does need to forward the 'format' functions because it is defined as:
template< class FormatObject > class formatob_t: public FormatObject { inline formatob_t & format( const DelimiterType & s ) { FormatObject::format( s ); // return type == FormatObject return( *this ); } };
Why do you bother what FormatObject::format( s ) returns? It may as well be void for what I care. Above method format implementation will allow you to chain format calls in any case. It's so obvious that I feel like there is some miscommunication here. Gennadiy.

Gennadiy Rozental wrote:
"John Torjo" <john.lists@torjo.com> wrote in message news:4152776F.8040303@torjo.com...
inline formatob_t & format( format_type s) { FormatObject::format( s ); return( *this ); }
formatob( vec ).format( " + " )
has the same type as
formatob( vec )
What are you talking about? Why would you bother what
FormatObject::format
is returning?
So that you can manipulate the formatob() object multiple times, like: formatob().do_this().do_that().and_that_too();
[I don't know why you removed original code. Let see it again.]
You must be joking. Do you think I can't read code?? formatob().format() return *** *this **** NOT FormatObject::format();
So my question still stand.
sorry - I misread your question. Yes, your question stands. Best, John -- John Torjo -- john@torjo.com Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.4 - save_dlg - true binding of your data to UI controls! + easily add validation rules (win32gui/examples/smart_dlg)
participants (4)
-
Gennadiy Rozental
-
John Torjo
-
Reece Dunn
-
Rozental, Gennadiy