Re: [boost] Cannot build static library with latest CVS on Linux
[2003-08-30] Jeff Garland wrote: Just did a CVS update and I am now unable to build date_time. This is on Linux. I'm looking at the CVS check-ins, but maybe someone workon on the build stuff might know right away what's wrong bjam from libs/date_time/test results in: [snip] /usr//bin/ar /usr/bin/ar ru -^^^ That duplication is strange -- I've now done a fix for that posibility. But you may want to investigate why ar is showing up twice in your PATH. Something funky with your file system? -- grafik - Don't Assume Anything -- rrivera (at) acm.org - grafik (at) redshift-software.com -- 102708583 (at) icq ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Cannot build static library with latest CVS on Linux
[2003-08-30] Jeff Garland wrote: Replies to self... Just did a CVS update and I am now unable to build date_time. This is on Linux. I'm looking at the CVS check-ins, but maybe someone workon on the build stuff might know right away what's wrong Had to roll back the lastest change in gcc-tools.jam to fix this (back to 1.73) Latest change was: 3 days grafik Fix for when AR is distributed as part of the compiler (ex. mingw, cygwin) Yea, I definately broke it :-) I'm trying to figure out how though... -- grafik - Don't Assume Anything -- rrivera (at) acm.org - grafik (at) redshift-software.com -- 102708583 (at) icq ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: [boost.variant] It is possible to make a variantLessThanComparable
David Abrahams wrote: Eric Friedman [EMAIL PROTECTED] writes: Ultimately, I do not believe any ordering scheme will provide meaningful, straightforward semantics. Assuming I am correct, I propose that the variant library offer your ordering scheme -- but only as an explicit comparison function, calling it variant_less. This would allow, for instance: std::set my_variant, boost::variant_lessmy_variant I'd appreciate feedback. I had the same thought myself, though I'd be inclined to spend a little time searching for a better name than less, since it doesn't really mean that. Maybe variant_before, using type_info::before as a precedent? If you want a second opinion, I'm in the just provide operator== and operator camp. ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Optional, tie, and iterator_adaptor
Joel de Guzman wrote: Although I don't see this as problematic: optionalint x; if (x) foo(x); Or perhaps: optionalint x; if (!!x) foo(x); We already have an implicit conversion to safe_bool and an operator ! anyway. Keep it. There's nothing wrong with it: operator unspecified-bool-type() const; bool operator!() const; IMHO, there is something terribly wrong here because now optionalT has two interfaces. The interface of optional itself and the interface of T. If you think that optionalT can be used like T (having the value-interface), you are immediately fooled by if(x) as it doesn't check T's value. A pointer-interface is much cleaner as it gives the user a hint that he is using a wrapper and in practice, I always prefer to be a little more explicit on these things (even at the cost of an occasional * here and there) than to have silent bugs. Regards, Daniel -- Daniel Frey aixigo AG - financial training, research and technology Schloß-Rahe-Straße 15, 52072 Aachen, Germany fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99 eMail: [EMAIL PROTECTED], web: http://www.aixigo.de ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: 1.30.0-1.30.2: no more thread support for Linux?
Threading support is on when BOOST_HAS_THREADS is defined, and off when it's not, or forced off by defining BOOST_DISABLE_THREADS, you'll find both of these mentioned in the configure generated user.hpp (and in the config docs). So if I my program runs only on systems that I know support threads, and I want shared_ptr to use threading support, my program can guarantee this by defining BOOST_HAS_THREADS? No matter whether the user's Boost install is - 1) Simply extracted from the tarball 2) Configured without thread support 3) Configured with thread support And I don't need to define anything about the platform thread library being used, like BOOST_HAS_PTHREADS? OK lets start with Linux and gcc as a specific and special case - in this case I think that will work - BOOST_HAS_PTHREADS will be defined anyway, but remember that your std lib will not be thread safe unless you define _REENTRANT, and if you do that then BOOST_HAS_THREADS will get defined anyway by the config system (either the out-the-box version or the configure'd one). Of course the user could always manually configure boost in some obscure way, or deliberately disable thread support with BOOST_DISABLE_THREADS, but if they've done that then you should probably be emitting a #error not trying to work around it. In the general case though, we're back to the situation that your code will not be thread safe unless you invoke your chosen compiler with some magic special flag (or in the case of IBM Visual Age use a different compiler front end altogether), and if you do that then Boost.config will detect it's presence by whatever macros it sets (usually but not always _REENTRANT) and turn on BOOST_HAS_THREADS. You should always regard BOOST_HAS_THREADS as *information*, not as something you set yourself, in 99% of cases if you find it's not set, then it's because the compiler in it's current mode isn't capable of producing thread safe code. Note for example that Boost.config explicitly defines BOOST_DISABLE_THREADS for gcc on some platforms because we know that gcc isn't capable of producing thread safe code on those platforms yet (even though they do have a perfectly good pthread lib). Finally if you're configuring your program via autoconf then there are some nice looking autoconf macros on the net, for example: http://ac-archive.sourceforge.net/Installed_Packages/acx_pthread.html. Sorry to make this complicated, but threads _are_ complicated John. ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: [boost.variant] It is possible to make a variant LessThanComparable
David Abrahams [EMAIL PROTECTED] wrote Eric Friedman [EMAIL PROTECTED] writes: std::set my_variant, boost::variant_lessmy_variant I had the same thought myself, though I'd be inclined to spend a little time searching for a better name than less, since it doesn't really mean that. Maybe variant_before, using type_info::before as a precedent? Maybe std::lessT is a precedent too? Nearly everyone I know has written a small, little wrapper around type_info to make it useable in the associative containers (and the default std::lessT). Dirk ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: [boost.variant] It is possible to make a variant LessThanComparable
Hello Eric, Eric Friedman [EMAIL PROTECTED] wrote Dirk Schreib wrote: [...] In this example typedef boost::variantT1, T2, ..., TN V; V v1 = T1( x ); V v2 = T2( y ); V v3 = T1( z ); v1 v2 should always be true. And v1 v3 should be the same as T1( x ) T1( z ). For starters, I agree that v1 v3 should be the same as x y. Ok. I'm not so sure about v1 v2, though. I'm inferring that you believe that operator should be implemented as follows: template typename T1, ..., typename TN bool operator( const variantT1,...,TN lhs, , const variantT1,...,TN rhs ) { if (lhs.which() == rhs.which()) ... // compare using underlying operator else return lhs.which() rhs.which() } This is exactly what I want. While this certainly solves the problem of storing variants in associative containers by establishing an ordering, the ordering is rather arbitrary and potentially confusing. Consider the following: typedef variantint, double var; bool result1 = int(3) double(2.0); // false bool result2 = var(3) var(2.0); // true On first glance, IMO most users would expect result1 == result2. With your ordering scheme, this would be untrue. Unfortunately, I do not believe the problem is specific to your ordering scheme. Trying to establish an ordering between unrelated types where each type does not fall into it's own category is very difficult. My ordering scheme is very easy and simple because you never have to compare two different types. Alternative solution would be to use typedef variantT1, T2 var; bool operator( T1 const lhs, T2 const rhs); which usually does not exist. Even if it is possible to compare two different types with integral promotion or user defined conversion operators it will impose problems on asymetry and transitivity. typedef variantdouble, std::string, int var; bool result1 = var(3.0) var(2); // false or true? bool result2 = var(3.0) var(2.5); // false or true? bool result3 = var(2.5) var(2); // false or true? // if (result2 result3) == result1 = true. Ultimately, I do not believe any ordering scheme will provide meaningful, straightforward semantics. Assuming I am correct, I propose that the variant library offer your ordering scheme -- but only as an explicit comparison function, calling it variant_less. This would allow, for instance: std::set my_variant, boost::variant_lessmy_variant The default comparison operator for std::setT is std::lessT (which just uses operator() ) and I would like this to work with variant too. If there are no meaningful, straightforward semantics the user will not put a variant into a set. If my ordering scheme is the only one offered by variant, it can be the default too. P.S. The issue of equality comparison between variants is a bit more straightforward. However, we still have the following potentially confusing situation: typedef variantint, double var; bool result3 = (int(3) == double(3.0)); // true bool result4 = (var(3) == var(3.0)); // false I need exactly this behaviour... Thus, perhaps a boost::variant_equal comparison function is also in order. ...and don't have a need for this ;-) Dirk ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Regression test page broken
Jeff Garland wrote: The regression test page seems to be on a diet http://boost.sourceforge.net/regression-logs/ You can find some of the other results at http://boost.sourceforge.net/regression-logs/release However, I'm not sure wether that is official already. Regards, m ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Optional, tie, and iterator_adaptor
In this post I will put forward a use-case or two to help see whether something a little different then the current version of optional might be useful. I also begin making a case that a Concept like PossiblyUninitializedVariable might be more generally useful than OptionalPointee. As I mentioned in the post that started this thread, I am writing a library that makes heavy use of using boost::graph and boost::tie. In the implementation of my library there is plenty of code that looks like this: //... typedef /*details ommitted*/ Iter; typedef /*details ommitted*/ Vertex; typedef /*details ommitted*/ Graph; std::pairIter, Iter out_edges(Vertex, Graph); //... Iter begin, end; Graph g(/*...*/); //... boost::tie(begin, end) = out_edges(v,g); It bothers me somewhat that begin and end are sitting there in an (implicitly) uninitialized state. Maybe during later maintenance of this code a new control path could get added and begin or end might be used without first being set. So I thought I'd try to see whether I could make the code more robust using boost::optional. I imagined following a convention along the lines of Initialize all local variables where declared, or when that is impossible use optional to protect against their inadvertent uninitialized use. But it turns out the optional doesn't really work with tie. Here's what I thought would be possible: //... same as first version typedef /*details ommitted*/ Iter; typedef /*details ommitted*/ Vertex; typedef /*details ommitted*/ Graph; std::pairIter, Iter out_edges(Vertex, Graph); //... boost::optionalIter begin, end; //now use optional Graph g(/*...*/); //... boost::tie(begin, end) = out_edges(v,g); //sorry, doesn't work After reading the documentation more carefully I learned that optional models pointer behavior. I spelled out how the code might look: boost::tie(*begin, *end); //sorry, ASSERT looks too strange Wow, that looked strange to me. I don't think of begin and end as pointers at all here. I just want to model values that haven't been initialized, and I maintain that initialized/unintialized is the concept worth modeling (I'm not sure what its name ought to be, so for now I'll just refer to it as the PossiblyUninitialized Concept). Such a concept might perhpaps embody notions of initialization via construction or assignment, testing whether the model has been initialized, etc. It may (or may not) also be true that there is some use in thinking of pointer/NULL as model of PossiblyUnintialized variables, but seems to me that the current version of optional has it backwards: I don't want to model all cases of possibly unininitialized behavior as OptionalPointees. So here's my wishlist for an optional-like facility: * I want instances to model PossiblyUninitialized (not OptionalPointee), e.g. optional sans pointer interface. * It want to be able to write functions that accept PossiblyUninitialized variables as parameters. But I want it to be easy for clients to call such routines with intialized values. That is I want to write: void foo(optionalBar); //... Bar b(/*details ommitted*/); foo(b); // Ok: passing in a valid Bar foo(optionalBar()); //Also ok, passing in uninitialized Bar This was one reason why I speculated that implicit construction might be useful here. * I want to be able to use optional and tie together as in the beginning of this post or pssibly using some additional syntax: tie(begin.uninitialized_ref(), end.uninitialized_ref()) = //... if I really have to. It may be that some of these wishes are ill-concevied or impractical. But the fact that optional models OptionalPointee instead of something like PossiblyUnitinitialized leaves me looking for alternatives, especially if that's what is preventing me from having other items on my wish list. - Mat ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Optional, tie, and iterator_adaptor
Daniel Frey wrote: Fernando Cacciola wrote: My main argument is that if those were allowed, you could write: optionalint opt ; opt = 1 ; int i = *opt ; and the assymetry didn't look right to me. I agree that this looks wrong. What about this syntax: optionalint opt; *opt = 3; int i = *opt; opt-foo(); This was exactly the way the originally submmited optional worked. I dropped it becasue reviweres thought that (*opt)=3 would lead to undefined behaviour just as if *opt were an rvalue. I realized that with true pointers, for instance, (*opt)=3 is in fact undefined behaviour, so I replace it with .reset() Fernando Cacciola ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Optional, tie, and iterator_adaptor
So I completely disagree that optionals should mix the interfaces of optional and the wrapped object into one. I think there should be an explicit unwrapping operation. But this is just my opinion, based on no practical evidence/experience, and I'm sure there are trade-offs either way. I'll explain the crux of my own reasoning below. On Sun, Aug 31, 2003 at 11:59:42PM +0800, Joel de Guzman wrote: It's really strange (and hard to explain) that you have to dereference optionalB. Example: F(tupleA, optionalB, C args) { A a = get1(args); B b = *get2(args); // strange! C c = get3(args); } I don't think it's strange at all; an optionalB is not a B! Not only is it strange, it complexifies the code a lot when the code is automatically generated by some meta-program. Example: template class A, class B, class C F(tupleA, B, C args) { A a = get1(args); B b = get2(args); C c = get3(args); } Whoops, have to do a special case IFF B is an optional! Well, no. B==optionalBprime via template unification, right? If you want to do something with a Bprime, then yes, you have to special-case it, as you should. Here's a (contrived) example of how the implicit conversion breaks generic code: template class Container void contrived( Container c ) { c.begin(); } ... vectorint v; contrived(v); // fine optionalvectorint ov( v ); contrived(ov); // fails The point is that optionalT is not a T, and most notably, a template function will never perform the coercion. Replace the lines like B b = get2(args); in your example with real calls to, e.g. do_something( get2(args) ) and do_something() is likely to fail if it's a template function (expecting a T and not an optionalT). As another example, FC++ lists support conversion-to-bool as a test for NIL: fcpp::listint l = NIL; if( l ) // if l not empty cout head(l); // print first element Clearly if 'l' were an optional, the if test would have a different meaning. I know you've been supporting a separate way to do the test (with ==none), but I think that's completely arbitrary. The two issues are both really the same issue, in my mind. Of all the types involved in the passing of arguments to the semantic actions, the optional doesn't fit nicely because it is the only one that has mixed value/pointer semantics. I am tempted to not use optionalT because of this and instead use variantT, none, but I hate to miss the performance advantage of optional vs. variantT, none. I have not used variant and know little about it, but I imagine you have to explicitly tell a variant which type you expect to get out of it. I think the same is true of optional; the call to operator*() (or whatever) says I want the T type (rather than the 'none'). My two cents. Again let me stress I'm arguing based on no practical experience working with any of these datatypes. -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Optional, tie, and iterator_adaptor
--On Sunday, August 31, 2003 10:29 AM -0400 Brian McNamara [EMAIL PROTECTED] wrote: On Sun, Aug 31, 2003 at 12:34:39AM -0700, Mat Marcus wrote: In this post I will put forward a use-case or two to help see whether something a little different then the current version of optional might be useful. I also begin making a case that a Concept like PossiblyUninitializedVariable might be more generally useful than OptionalPointee. As I mentioned in the post that started this thread, ... std::pairIter, Iter out_edges(Vertex, Graph); boost::optionalIter begin, end; //now use optional Graph g(/*...*/); boost::tie(begin, end) = out_edges(v,g); //sorry, doesn't work boost::tie(*begin, *end); //sorry, ASSERT looks too strange ... First off, let me say I do think this is a compelling use-case. (As an aside, this is exactly why people in functional languages love pattern-matching; it's a general facility for deconstructing data into its constituents, where each portion is a new, named variable.) I missed the beginning of this thread, but I imagine the motivation is to avoid having to say std::pairIter,Iter p = out_edges(v,g); Iter begin = p.first; Iter end = p.second; each and every single time you call out_edges(). IIUC, you are saying that you don't find the use of tie with pairs very compelling. Fair enough. Of course tie is more generically useful with arbitrary tuples and multi-value returns. I was just trying to present a small familiar example of such usage. As I think someone else in the thread mentioned, there has to be some explicit call to turn an optionalT into a T, or else the two interfaces get muddled together. In general I'm not a fan of implicit conversions or constructors. However one of my goals is to be able to easily/readably move code from using raw variables to use PossiblyUnitinitializedVariables instead. So.. The same would be true of PossiblyUninitializedVariable. You've also mentioned that you think operator*() is inapproprate/ugly for this use. So, here's an idea for something completely new which maybe helps fit your requirements. I start with the motivating example: PossUninitVarIter begin, end; tie( +begin, +end ) = out_edges(v,g); for( Iter i = ~begin; i != ~end; ++i ) ... (Effectively operator~() fetches the value (or asserts if there is none), whereas operator+() returns a reference to the yet-nonexistent value so it can be filled in by someone else.) ... here I like the + or something like it begin.reference_to_uninitialized(). That is I don't mind when users have to be a little more explicit in the dangerous/uncommon case. ~ is also interesting, although I think that readability suffers. I'd give up bool conversion and operator! to avoid the need for ~ if that would reasonably solve the muddling issues. But perhaps there would be too many other problems -- I haven't explored this deeply yet. Now here's a (sloppy, partial) summary of the interface, along with some of the implementation: template class T struct PossUninitVar { PossUninitVar() : init(false) {} PossUninitVar( const T x ) : init(true) { new (raw_storage) T(x); } operator bool() { return init; } Proxy operator +() { return unsafe_get(); } T operator~() { return get(); } private: bool init; Something raw_storage; // array of bytes with right size/alignment T get() { if(!init) assert; else /* returns T from raw storage */ } Proxy unsafe_get() { return Proxy(this); } class Proxy { PossUninitVar* puv; public: T operator=( const T x ) { new (puv-raw_storage) T(x); puv-init = true; return puv-get(); } }; }; Hopefully you get the idea. I think this meets your wish list. Making tie() interact properly with the Proxy might be hard. Just some ideas; refine, reject, whatever, as you please... -- -Brian McNamara ([EMAIL PROTECTED]) Thanks for the ideas, and for your functional programming explanations. - Mat ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Regression test page broken
[2003-08-31] Jeff Garland wrote: On Sun, 31 Aug 2003 09:59:26 +0200, Martin Wille wrote Jeff Garland wrote: The regression test page seems to be on a diet http://boost.sourceforge.net/regression-logs/ You can find some of the other results at http://boost.sourceforge.net/regression-logs/release However, I'm not sure wether that is official already. Thanks, it looks like the main page is better now as well. When I looked at it there were only results for SGI... SF somehow deleted the contents of the regression-logs directory early Saturday... I could only restore the empty index itself. But I see new tests have run already :-) -- grafik - Don't Assume Anything -- rrivera (at) acm.org - grafik (at) redshift-software.com -- 102708583 (at) icq ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Any interest in a string literal selector helper library?
Hi all, I have written a relatively small library which I've found pretty useful in my own projects. I have to deal with std::basic_string objects a lot in my applications, and I almost always write template code so that the same code works with both std::string and std::wstring types. The only problem which cannot be directly solved with existing language construct is handling string literals. To make myself clear, the below code will only work for f char (): template typename char_type void f() { std::basic_string char_type str( hello ); } What is needed here is some facility which selects either hello or Lhello based upon char_type. Now, using my library, the above code can be fixed like this: template typename char_type void g() { std::basic_string char_type str( TextAutoSelect( char_type, hello ) ); } Nearly all the job is done at compile-time, and the only runtime cost would be that of a one-line inline function (which can be optimized away using compiler optimizations, like the VC++ compiler does.) I would like to know if there is any interest for this tiny library to be submitted to Boost. Thanks for your consideration, - Ehsan Akhgari List Owner: [EMAIL PROTECTED] [ Email: [EMAIL PROTECTED] ] [ WWW: http://www.beginthread.com/Ehsan ] ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Optional, tie, and iterator_adaptor
Daniel Frey [EMAIL PROTECTED] wrote: Joel de Guzman wrote: Although I don't see this as problematic: optionalint x; if (x) foo(x); Or perhaps: optionalint x; if (!!x) foo(x); We already have an implicit conversion to safe_bool and an operator ! anyway. Keep it. There's nothing wrong with it: operator unspecified-bool-type() const; bool operator!() const; IMHO, there is something terribly wrong here because now optionalT has two interfaces. The interface of optional itself and the interface of T. If you think that optionalT can be used like T (having the value-interface), you are immediately fooled by if(x) as it doesn't check T's value. A pointer-interface is much cleaner as it gives the user a hint that he is using a wrapper and in practice, I always prefer to be a little more explicit on these things (even at the cost of an occasional * here and there) than to have silent bugs. If you really want it to be explicit, the first version, which I prefer (and you snipped ;-) is so much better: optionalint x; if (x != none) foo(x); Who's fooling who? You said 2 interfaces, the current optionalT is actually the one with the 2 interfaces. In some ways, it has a value interface (construction, reset , ==, !=) and pointer interface on some (*, -, get). What I am trying very hard to say is to stick to only *ONE* interface and one concept. Syntactically, there's nothing inherently wrong with: if (x) foo(x); We see it all the time with ints: int x; if (x) foo(x); Yet, I have to admit that after thinking about it some more, I realized an ambiguity when T is bool. Example: optionalbool x; if (x) foo(x); That is why I really prefer the more explicit syntax: optionalint x; if (x != none) foo(x); A small price to pay, considering the advantages. 1) Unification of the optional and variant where optionalT -- variantT, none_t. 2) Only one underlying semantics (value-semantics) as opposed to (sometimes value, sometimes pointer semantics) and 3) Plays well with generic code (I'll give another use-case in addition to Mat's). -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Compile problem with Spirit CodeWarrior
On Aug 31, 2003, at 7:45 AM, Hartmut Kaiser wrote: Please have a look at the FAQ here: http://www.boost.org/libs/spirit/doc/faq.html#scanner_business This should solve your problem. Thanks, that helps, but I still have a question or two. The FAQ says it is best to avoid rules as arguments to the parse functions, but then what are rules good for? How else am I going to do any nontrivial parsing? I've been looking at the Spirit article in the C/C++ Users Journal. It contains a code example that defines rule expression, and later says if (parse( str, expression, space ).full)... I supposed that space was a typo for space_p. How do you reconcile that code sample with the FAQ? -- http://www.jwwalker.com/ ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Optional, tie, and iterator_adaptor
--On Sunday, August 31, 2003 1:35 PM -0400 Brian McNamara [EMAIL PROTECTED] wrote: So I completely disagree that optionals should mix the interfaces of optional and the wrapped object into one. I think there should be an explicit unwrapping operation. But this is just my opinion, based on no practical evidence/experience, and I'm sure there are trade-offs either way. I'll explain the crux of my own reasoning below. On Sun, Aug 31, 2003 at 11:59:42PM +0800, Joel de Guzman wrote: It's really strange (and hard to explain) that you have to dereference optionalB. Example: F(tupleA, optionalB, C args) { A a = get1(args); B b = *get2(args); // strange! C c = get3(args); } I don't think it's strange at all; an optionalB is not a B! That doesn't make it a pointer to B! I think the above code is strange for two independent reasons. First, as I said before I think that though pointers may model possibly uninitialized variables, the converse does not always hold. Second, I think that it might be useful to treat variables and possibly uninitialized variables uniformly as much as possible (except where it overly compromises safety). I hold strongly to the first argument, though I admit that the second one may not stand up in the end. Not only is it strange, it complexifies the code a lot when the code is automatically generated by some meta-program. Example: template class A, class B, class C F(tupleA, B, C args) { A a = get1(args); B b = get2(args); C c = get3(args); } Whoops, have to do a special case IFF B is an optional! Well, no. B==optionalBprime via template unification, right? If you want to do something with a Bprime, then yes, you have to special-case it, as you should. Here's a (contrived) example of how the implicit conversion breaks generic code: template class Container void contrived( Container c ) { c.begin(); } ... vectorint v; contrived(v); // fine optionalvectorint ov( v ); contrived(ov); // fails The point is that optionalT is not a T, and most notably, a template function will never perform the coercion. Replace the lines likeB b = get2(args); in your example with real calls to, e.g. do_something( get2(args) ) and do_something() is likely to fail if it's a template function (expecting a T and not an optionalT). As another example, FC++ lists support conversion-to-bool There's conversion-to-bool again. I still wonder whether dispensing with this would open the door to implicit conversions. as a test for NIL: fcpp::listint l = NIL; if( l ) // if l not empty cout head(l); // print first element Clearly if 'l' were an optional, the if test would have a different meaning. I know you've been supporting a separate way to do the test (with ==none), but I think that's completely arbitrary. The two issues are both really the same issue, in my mind. I'm still not clear as to why. Of all the types involved in the passing of arguments to the semantic actions, the optional doesn't fit nicely because it is the only one that has mixed value/pointer semantics. I am tempted to not use optionalT because of this and instead use variantT, none, but I hate to miss the performance advantage of optional vs. variantT, none. I have not used variant and know little about it, but I imagine you have to explicitly tell a variant which type you expect to get out of it. I think the same is true of optional; the call to operator*() (or whatever) says I want the T type (rather than the 'none'). My two cents. Again let me stress I'm arguing based on no practical experience working with any of these datatypes. -- -Brian McNamara ([EMAIL PROTECTED]) - Mat ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
RE: [boost] Compile problem with Spirit CodeWarrior
James W. Walker wrote: Thanks, that helps, but I still have a question or two. The FAQ says it is best to avoid rules as arguments to the parse functions, but then what are rules good for? How else am I going to do any nontrivial parsing? Use grammars (see here: http://www.boost.org/libs/spirit/doc/grammar.html). This is the best way to implement non-trivial parsers with Spirit. I've been looking at the Spirit article in the C/C++ Users Journal. It contains a code example that defines rule expression, and later says if (parse( str, expression, space ).full)... I supposed that space was a typo for space_p. How do you reconcile that code sample with the FAQ? The article describes Spirit V1.2 (it was written nearly two years ago). Spirit has undergone some minor interface changes since then (all predefined parser objects have a '_p' appended). Another change was a slight change of the scanner idiom, which lead to the subtleties you've encountered. Generally the CUJ article is a good starting point, but nevertheless you should have a look at the current doc's and, may be, at the samples contained with Spirit. HTH Regrads Hartmut ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Optional, tie, and iterator_adaptor
Joel de Guzman [EMAIL PROTECTED] writes: What I am trying very hard to say is to stick to only *ONE* interface and one concept. Optional is a container. I've never seen a container in C++ which didn't have both a value interface and an element-access interface. How do you propose to achieve that with optional? -- Dave Abrahams Boost Consulting www.boost-consulting.com ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Optional, tie, and iterator_adaptor
Joel de Guzman [EMAIL PROTECTED] writes: Hi, Here's another use-case... We are working on an alternative semantic action scheme with Spirit that will be a lot more easier to use than the current scheme. With this scheme, the signature of the semantic action will be dependent on the rule where it is attached to. This is similar in some sense to YACC. For instance (I'll write in plain EBNF): r ::= a b c The attached semantic-action to this rule will have a signature: F(tupleA, B, C) Another example: r ::= a | b | c The attached semantic-action to this rule will have a signature: F(variantA, B, C) Now, unlike YACC, Spirit has iteration (kleene, plus, optional) Here's a more or less the complete suite of patterns and the corresponding semantic-action signatures: r ::= a b-F(tupleA, B) r ::= a | b -F(variantA, B) r ::= a* -F(vectorA) r ::= a+ -F(vectorA) r ::= a? -F(optionalA) This is somewhat OT, but I want to suggest you consider something else. I did this in a parser generator system I wrote, and it worked out really well. If the rule is x - a b | c d c Then the way you refer to the semantic value associated with the a symbol is by writing, simply, 'a'. The way you refer to the semantic value of the first c symbol is by writing c[0], and you refer to the 2nd one as c[1]. I'm sure you get the idea. Then the user almost never needs to worry about positional associations between grammar symbols and their semantic values. It's actually fairly rare that the same symbol appears twice on the rhs of a rule (especially when rules are reduced to eliminate |) and keeping track of whether it's the first or nth instance of 'X' is much easier than keeping track of precisely where the Xs fall in the sequence of symbols. My system was written in Python, but you might be able to adapt the general idea to C++. -- Dave Abrahams Boost Consulting www.boost-consulting.com ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Boost memory management guidelines
Gregory Colvin [EMAIL PROTECTED] writes: But indeed allocate/construct/deallocate/destroy is more work than ^^^^ Oyeah. These two absolutely don't belong in allocator, period. Do any implementations even use them? Allocators exist to provide a point of customization for users, but you cannot/should not customize these. Conforming containers had better use them. I'm sorry, but I think that's flat wrong. What do you suppose that entry in column 2 of the allocator requirements table (20.1.5) means, after all? And once you are down in the coal mine customizing what a pointer is, I'm not sure you won't need to customize how to construct and destroy. The class getting constructed/destroyed has full control over that or the language is utterly bustificated. Using allocator is even more work than allocating raw memory with malloc and doing placement new and explicit destruction, then freeing the raw memory. That's my biggest complaint. It's new/delete T* p = new T(); ... delete p; versus malloc/free T* p = (T*)malloc(sizeof T); When you need malloc(sizeof(T) + N) Allocators get a lot harder to use. new(p) T(); ... p-~T(); free(p); versus Boost UserAllocator T* p = (T*)user_allocator::malloc(sizeof T); new(p) T(); ... p-~T(); user_allocator::free(p); versus standard Allocator Allocator::pointer p = allocator.allocate(sizeof T); allocator.construct(p,T()); ... allocator.destroy(p); allocator.deallocate(sizeof T); Oops! There's a pointer missing here. Just a small example of why I'm saying it's a harder interface. Allocator has strange requirements, like p shall not be null. If I need to build a custom one I have to navigate rebind and the implications of allocator inequality for which the standard provides little guidance. -- Dave Abrahams Boost Consulting www.boost-consulting.com ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: [boost.variant] It is possible to make a variantLessThanComparable
Peter Dimov [EMAIL PROTECTED] writes: David Abrahams wrote: Eric Friedman [EMAIL PROTECTED] writes: Ultimately, I do not believe any ordering scheme will provide meaningful, straightforward semantics. Assuming I am correct, I propose that the variant library offer your ordering scheme -- but only as an explicit comparison function, calling it variant_less. This would allow, for instance: std::set my_variant, boost::variant_lessmy_variant I'd appreciate feedback. I had the same thought myself, though I'd be inclined to spend a little time searching for a better name than less, since it doesn't really mean that. Maybe variant_before, using type_info::before as a precedent? If you want a second opinion, I'm in the just provide operator== and operator camp. But, IIUC, if operator is not provided, you'd oppose a std::less specialization, right? -- Dave Abrahams Boost Consulting www.boost-consulting.com ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Optional, tie, and iterator_adaptor
On Sun, Aug 31, 2003 at 10:41:15AM -0700, Mat Marcus wrote: --On Sunday, August 31, 2003 10:29 AM -0400 Brian McNamara First off, let me say I do think this is a compelling use-case. ... I missed the beginning of this thread, but I imagine the motivation is to avoid having to say std::pairIter,Iter p = out_edges(v,g); Iter begin = p.first; Iter end = p.second; each and every single time you call out_edges(). IIUC, you are saying that you don't find the use of tie with pairs very compelling. Fair enough. Of course tie is more generically useful with arbitrary tuples and multi-value returns. I was just trying to present a small familiar example of such usage. Apologies if I was unclear; I _do_ think it's compelling. The syntactic convenience of being able to bind multiple names in one expression is very nice. (Additionally, if you're doing lots of FP stuff (like me), it's a real pain when you have to introduce those nasty _statements_ into your code, when you'd really like to do things all in one big _expression_. :) ) In general I'm not a fan of implicit conversions or constructors. However one of my goals is to be able to easily/readably move code from using raw variables to use PossiblyUnitinitializedVariables instead. So.. I agree that it would be nice for PossiblyUnitinitializedVariables to be able to be included in existing code with a minimum of fuss. I think, perhaps, that that goal is incompatible with avoiding implicit conversions, though. ... here I like the + or something like it begin.reference_to_uninitialized(). That is I don't mind when users have to be a little more explicit in the dangerous/uncommon case. ~ is Indeed (make the easy/common things easy, and make the hard/uncommon things possible). also interesting, although I think that readability suffers. I'd give up bool conversion and operator! to avoid the need for ~ if that would reasonably solve the muddling issues. But perhaps there would be too many other problems -- I haven't explored this deeply yet. Right; to clarify, I don't think the boolean conversion operator is interfering with the implicit conversion to T. Rather I think each is an instance of implicit conversion, and implicit conversions just don't work well with templates in general, in my experience. I chose '+' and '~' simply because they were the two unary operators that sprang to mind (that aren't named '*'). Personally I have no problem with '*'; C++ has a small finite set of operators, and so you are bound to have to overload the conceptual meanings of some operators if you want to use them for useful syntax sugar. The way I see it, the optional interface using '*' is fine, and I think perhaps what people object to is the conceptual notion of optional being 'pointer-like'. The way I choose to see it, optional is just a special kind of container, which happens to use '*' to get at the value in the container, and the fact that '*' is also used to dereference pointers is a mere coincidence of names. But perhaps other operators (like '+' and '~') or named operations would be more generally acceptable. That's fine. My main point in joining this discussion was to emphasize that I think there ought to be an explicit operation to 'get' the value of an optional (as well as to get the location of raw storage to construct a new value). What those operations are named matters much less than simply their existence. -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Optional, tie, and iterator_adaptor
On Sun, Aug 31, 2003 at 11:11:10AM -0700, Mat Marcus wrote: --On Sunday, August 31, 2003 1:35 PM -0400 Brian McNamara On Sun, Aug 31, 2003 at 11:59:42PM +0800, Joel de Guzman wrote: It's really strange (and hard to explain) that you have to dereference optionalB. Example: F(tupleA, optionalB, C args) { A a = get1(args); B b = *get2(args); // strange! C c = get3(args); } I don't think it's strange at all; an optionalB is not a B! That doesn't make it a pointer to B! True. See my message of a moment ago, where I adopt the notion that '*' is just an unfortunate coincidence of names, and that any relationship between optional and pointers is mere happenstance. (This all despite the documentation on optional which explicitly describes the relationship; I am merely trying to present another way of looking at it which may be useful.) As another example, FC++ lists support conversion-to-bool There's conversion-to-bool again. I still wonder whether dispensing with this would open the door to implicit conversions. I think no. I should mention in passing that, while in general I think implicit conversions are bad news and should be avoided whenever reasonable, I do think the conversion to bool is an exceptional case, simply because it is already so deeply ingrained in C++ (and C) language/culture. (Fortunately bool has a very narrow interface, so it doesn't get us into too much trouble. Implicit conversions to user-defined types may create arbitrary interface conflicts/conceptual ambiguities, and this is where the real trouble begins.) -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: [boost.variant] It is possible to make a variantLessThanComparable
David Abrahams wrote: Peter Dimov [EMAIL PROTECTED] writes: If you want a second opinion, I'm in the just provide operator== and operator camp. But, IIUC, if operator is not provided, you'd oppose a std::less specialization, right? Right. When there is one and only one strict weak ordering (equality) for a type, not using operator and operator== because some users might have different expectations is misguided. It is pretty clear what setvariant or find(first, last, v) is supposed to do; variant_less or variant_equal is required boilerplate as Howard says. :-) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: lexicographic: review request?
Brian McNamara wrote: The point is, that Jan proposed to add something which has a hidden overhead and I'm not sure it's a good idea. Instead of nested if-else-cascades, the user could also write: bool operator( const person lhs, const person rhs ) { return lhs.lastname != rhs.lastname ? lhs.lastname rhs.lastname : lhs.firstname != rhs.firstname ? lhs.firstname rhs.firstname : lhs.age rhs.age; } I am (re)appearing mid-thread, so I may have missed something along the way, but... What's with !=? I think lexicographical orderings are built only on the assumptions of operator, yes? For two objects x and y, if neither x y nor y x is true, then they are in the same equivalence class, but this is not the same thing as equality or inequality. I just want to make sure the template parameter constraints (or macro parameter constraints, as the case may be) are the right ones. you are right. lexicographic only needs the operator or the functor. btw. i made some performance checks. for those who are interested the code is in lex_performance_test.cpp in the libs/utility/test in the sandbox. it just sorts a big vector of int for four criteria. the outcome is as follows (linux/g++ 3.2.2, release build): boost::lexicographic, division - 2.11 boost::lexicographic, no division - 1.21 boost::lexicographic emulation, no division - 0.68 if cascade, division - 0.92 if cascade, no division - 0.54 where emulation is the same algorithm as lexicographic, but everything is written inline (by hand). and the diference between division and no division is as follows. division: boost::lexicographic (a / 1000, b / 1000) (b / 100, a / 100) (a / 10, b / 10) (b, a) no division: boost::lexicographic (a, b) (b, a) (a, b) (b, a) the result makes me think, that the comparison code is in fact not really inlined (1.21 with lexicographic to 0.68 with the emulation). and my unexperienced look into the assembly code acknowledges this. maybe someone with a different compiler can run the test. jan -- jan langer ... [EMAIL PROTECTED] pi ist genau drei ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost memory management guidelines
Gregory Colvin wrote: [...] Two small corrections: shared_ptr currently uses std::allocator to allocate counts regardless. No, it uses plain new/delete by default. It is possible to get it to use std::allocator via a #define. [...] versus standard Allocator Allocator::pointer p = allocator.allocate(sizeof T); allocator.construct(p,T()); ... allocator.destroy(p); allocator.deallocate(sizeof T); allocate(1) and deallocate(p, 1) if I'm not mistaken. ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost memory management guidelines
On Sunday, Aug 31, 2003, at 13:13 America/Denver, David Abrahams wrote: Gregory Colvin [EMAIL PROTECTED] writes: But indeed allocate/construct/deallocate/destroy is more work than ^^^^ Oyeah. These two absolutely don't belong in allocator, period. Do any implementations even use them? Allocators exist to provide a point of customization for users, but you cannot/should not customize these. Conforming containers had better use them. I'm sorry, but I think that's flat wrong. What do you suppose that entry in column 2 of the allocator requirements table (20.1.5) means, after all? It means any value returned by construct, destroy, or deallocate goes unused. And once you are down in the coal mine customizing what a pointer is, I'm not sure you won't need to customize how to construct and destroy. The class getting constructed/destroyed has full control over that or the language is utterly bustificated. Yes, but the allocator may want to do something else as well, and construct and destroy serve as hooks for whatever that may be. Using allocator is even more work than allocating raw memory with malloc and doing placement new and explicit destruction, then freeing the raw memory. That's my biggest complaint. It's new/delete T* p = new T(); ... delete p; versus malloc/free T* p = (T*)malloc(sizeof T); When you need malloc(sizeof(T) + N) Allocators get a lot harder to use. Agreed. new(p) T(); ... p-~T(); free(p); versus Boost UserAllocator T* p = (T*)user_allocator::malloc(sizeof T); new(p) T(); ... p-~T(); user_allocator::free(p); versus standard Allocator Allocator::pointer p = allocator.allocate(sizeof T); allocator.construct(p,T()); ... allocator.destroy(p); allocator.deallocate(sizeof T); Oops! There's a pointer missing here. Silly me for not compiling my email. Just a small example of why I'm saying it's a harder interface. Very small. Allocator has strange requirements, like p shall not be null. Another performance optimization. In most cases there is no way that p could be null in the first place, so why waste time checking? If I need to build a custom one I have to navigate rebind and the implications of allocator inequality for which the standard provides little guidance. Agreed. The Boost UserAllocator is easier to implement and to use. ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost memory management guidelines
On Sunday, Aug 31, 2003, at 13:51 America/Denver, Peter Dimov wrote: Gregory Colvin wrote: [...] Two small corrections: shared_ptr currently uses std::allocator to allocate counts regardless. No, it uses plain new/delete by default. It is possible to get it to use std::allocator via a #define. OK. Anyway, the std::allocator interface is adequate for shared_ptr. [...] versus standard Allocator Allocator::pointer p = allocator.allocate(sizeof T); allocator.construct(p,T()); ... allocator.destroy(p); allocator.deallocate(sizeof T); allocate(1) and deallocate(p, 1) if I'm not mistaken. You are not. I shouldn't post uncompiled code late at night. ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Re: [boost.variant] It is possible to make a variantLessThanComparable
Peter Dimov [EMAIL PROTECTED] wrote David Abrahams wrote: But, IIUC, if operator is not provided, you'd oppose a std::less specialization, right? Right. When there is one and only one strict weak ordering (equality) for a type, not using operator and operator== because some users might have different expectations is misguided. It is pretty clear what setvariant or find(first, last, v) is supposed to do; variant_less or variant_equal is required boilerplate as Howard says. :-) Thanks! Full ACK! Dirk ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost