Re: [boost] Compile problem with Spirit CodeWarrior
On Sunday, August 31, 2003, at 11:29 AM, Hartmut Kaiser wrote: Use grammars ... The article describes Spirit V1.2 (it was written nearly two years ago). ... Thanks a lot, that's very helpful. -- http://www.jwwalker.com/ ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Optional, tie, and iterator_adaptor
David Abrahams [EMAIL PROTECTED] wrote: Joel de Guzman [EMAIL PROTECTED] writes: 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++. Hmmm, nice! How does it handle iteration like x - a* and the optional x - a? -- 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] Re: Optional, tie, and iterator_adaptor
Brian McNamara [EMAIL PROTECTED] wrote: 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.) Perhaps, but we were also taught that operator overloading may create arbitrary interface conflicts/conceptual ambiguities, and this is where the real trouble begins ;-) That may be true in some (many?) contexts, but it is not definitely universally true. As I mentioned in another post, I never had, nor seen, any complaints about reference_wrapperT, which incidentally, has an implicit conversion to T. ref(var) has been in extensive use by a lot of libraries for many years now. -- 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] Re: Optional, tie, and iterator_adaptor
Brian McNamara [EMAIL PROTECTED] wrote: On Sun, Aug 31, 2003 at 10:41:15AM -0700, Mat Marcus wrote: 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. It does interfere with the implicit conversion to T. Consider this: optionalbool o; if (o) foo(o); If you choose implicit conversion to T (which is debatable), the implicit conversion to (safe)bool will have to go: optionalbool o; if (o != none) foo(o); But I see now that you are against implicit conversions, in general. Fair enough. FWIW, I never had, nor seen, any complaints about reference_wrapperT, which incidentally, has an implicit conversion to T. In fact, I find the implicit conversion very useful. Anyway... at the very least, I wish this is possible: optionalbool o; if (o) foo(o.get()); But no, here too, we should write: optionalbool o; if (o) foo(*o.get()); Which goes against existing practice in boost. See reference_wrapper::get, tuple::get, variant::get, etc. -- 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] Re: Optional, tie, and iterator_adaptor
On Mon, Sep 01, 2003 at 09:03:17AM +0800, Joel de Guzman wrote: Do it the ref, tuple and variant way: get(). But get(), as an element-access interface, should return a reference, not a pointer, as it does currently. Clearly I had not been paying enough attention earlier in the thread; I was oblivious to the fact that get() was returning a pointer and not a reference. I think get() (or operator*(), or however it ends up being spelled) should indeed return a reference. (Apologies for the confusion.) As for the use-case with the function returning a pair of iterators that we'd like to assign to optionals via a tie(), I think there should also be a different method in the interface which returns the hole in an empty optional where a new value can be constructed. See, e.g., my earlier message which defined an interface with operator+() and operator~(). -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] [Boost-bugs] [ boost-Bugs-798357 ] rational operator canoverflow
Bugs item #798357, was opened at 2003-09-01 02:57 Message generated for change (Tracker Item Submitted) made by Item Submitter You can respond by visiting: https://sourceforge.net/tracker/?func=detailatid=107586aid=798357group_id=7586 Category: None Group: None Status: Open Resolution: None Priority: 5 Submitted By: Derrick Bass (derrickbass) Assigned to: Nobody/Anonymous (nobody) Summary: rational operator can overflow Initial Comment: I recently discovered that the operator for the rational template is prone to overflow. It is noted in the design documentation that some care was taken to prevent overflows for most operators, but apparently not for this one. The basic problem comes from the fact that it checks if n1/d1 is less than n2/d2 by checking if n1 d1 n2 d1. Those products can easily overflow. I suggest an algorithm that first checks the integer parts of the quotients. If they are equal, then the algorithm could be based on the observation: for n1d1 and n2d2 and everything positive and d1d2, then n1/d1 n2/d2 iff n1/d1 n2-n1/d2-d1. So if we write d2 = q d1 + r then n1/d1 n2/d2 iff n1/d1 n2-q n1/r One would then recursively check this inequality. Obviously, a similar observation would have to be made for d2d1. -- You can respond by visiting: https://sourceforge.net/tracker/?func=detailatid=107586aid=798357group_id=7586 --- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf ___ Boost-bugs mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/boost-bugs ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] generic uses of optionalT
Here's a (contrived) example of how the implicit conversion breaks generic code: [example snipped] 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). Okay, you've demonstrated that it may not be possible to drop-in optionalT for T with zero code changes when T is not a scalar type. (Usually, my Ts are! ;-) Nonetheless, it is at least still possible to write generic code that accepts either T or the wrapped T, which is definitely an improvement over writing a whack of special-casing code. Dave // code below compiles, runs cleanly with g++ 3.3 and intel 7.1 on linux #include exception #include iostream #include vector template typename T class nilable { public: nilable(void) : nil_(true) {}; nilable(const T value) : value_(value), nil_(false) {}; // rely on default destructor // rely on default copy constructor // rely on default assignment operator bool nil(void) const { return nil_; }; operator T(void) const { if (nil_) throw std::bad_cast(); return value_; }; const T unsafe_reference(void) const { return value_; }; T unsafe_reference(void) { return value_; }; const T unsafe_value(void) const { return value_; }; T unsafe_value(void) { return value_; }; private: T value_; bool nil_; }; template typename container_type void output(const container_type c) { for (typename container_type::const_iterator i(c.begin()); i != c.end(); ++i) { std::cout *i '\n'; }; }; int main(void) { std::vectorint v; v.push_back(1); v.push_back(2); output(v); try { nilable std::vectorint nv(v); //output(nv); // true, this fails output(std::vectorint(nv)); // but this succeeds! nilable std::vectorint nv2; output(std::vectorint(nv2)); // and this throws as expected. } catch (std::bad_cast) { std::cout Cannot convert from nil to value.\n; }; }; ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] generic uses of optionalT
On Sun, Aug 31, 2003 at 09:12:59PM -0600, Dave Gomboc wrote: 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). Okay, you've demonstrated that it may not be possible to drop-in optionalT for T with zero code changes when T is not a scalar type. (Usually, my Ts are! ;-) Nonetheless, it is at least still possible to write generic code that accepts either T or the wrapped T, which is definitely an improvement over writing a whack of special-casing code. Indeed. [snipped most of code] template typename T class nilable { public: ... operator T(void) const { if (nil_) throw std::bad_cast(); return value_; }; ... I'd add T get() { return T(*this); } // in reality, return T -- using T here just to show the idea ... try { nilable std::vectorint nv(v); //output(nv); // true, this fails output(std::vectorint(nv)); // but this succeeds! As does output( nv.get() ); nilable std::vectorint nv2; output(std::vectorint(nv2)); // and this throws as expected. Again I'd prefer output( nv2.get() ); I was originally arguing with Joel because I thought he wanted to use exactly nv and not anything like nv.get(). I think now that we've cleared up the confusion about get() returning a reference instead of a pointer, we're all back on the same page. -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] [BGL] Patch to add buffer parameter to dfs
Here's a patch to depth_first_search.hpp that allows a buffer parameter to be used with depth_first_search(). I'm also including a patch to depth_first_search.html to update the documentation. The patches apply to CVS revision 1.37 of depth_first_search.hpp, and 1.14 of depth_first_search.html. The patch allows the named parameter version of depth_first_search() to have an optional buffer(Buffer S) parameter included among the other named parameters. Also, the non-named parameter version allows an additional Buffer S parameter. Actually, I was all set to add an overload to depth_first_visit() too, but it seems that to add another parameter after the func parameter, you'd have to pass detail::nontruth2() as the value for func. I'd rather add a Buffer parameter before TerminatorFunc, but that would screw up other people's code. The changes are generally patterned after the way the buffer parameter is handled in breadth_first_search(). I've also create an additional traits class, dfs_buffer_traits, to allow the user to declare the correct value_type for the buffer. If no buffer parameter is used, reallocations of the search stack will be greatly reduced, especially with large graphs. However, if the user happens to know in advance that the search depth will not go beyond a certain point, reallocations can be eliminated by passing in a custom buffer as follows: template typename T struct ReserveStack : public std::stackT, std::vectorT { void reserve(size_type size) { c.reserve(size); } }; int main() { // ... typedef dfs_buffer_traitsGraph::value_type BufferValueType; typedef ReserveStackBufferValueType StackType; const StackType::size_type maxSearchDepth = 100; StackType s; s.reserve(maxSearchDepth); depth_first_search(g, visitor(vis).buffer(s)); // ... } Also, if allocating the entire stack in one block of memory is a bad idea, a deque-based stack could be used instead: int main() { // ... typedef dfs_buffer_traitsGraph::value_type BufferValueType; std::stackBufferValueType s; depth_first_search(g, visitor(vis).buffer(s)); // ... } If the user defines BOOST_RECURSIVE_DFS, the older recursive code is used, but the behavior of the search will have nothing to do with whatever type of Buffer parameter is passed in. So, this could be a source of future unexpected behavior. The modifications to the HTML file includes the addition of the new parameter, a reworking the of the starting vertex parameter to match the actual code, and a few other minor fixes. Bruce Barr, schmoost at yahoo.com, visit ubcomputer.com __ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com depth_first_search.hpp.patch Description: depth_first_search.hpp.patch depth_first_search.html.patch Description: depth_first_search.html.patch ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] generic uses of optionalT
Brian McNamara [EMAIL PROTECTED] wrote: On Sun, Aug 31, 2003 at 09:12:59PM -0600, Dave Gomboc wrote: 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). Okay, you've demonstrated that it may not be possible to drop-in optionalT for T with zero code changes when T is not a scalar type. (Usually, my Ts are! ;-) Nonetheless, it is at least still possible to write generic code that accepts either T or the wrapped T, which is definitely an improvement over writing a whack of special-casing code. Darn! Can't we just overload operator.() operator-dot ? ahemahemcoughcoughcough ;-) I want my proxies! -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: [BGL] Missing open delimiter for HTML tag indijkstra_shortest_paths.html
Janusz Piwowarski wrote: Hi, As in subject: first line, first character. Fixed, thanks! - Volodya ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: generic uses of optionalT
[Dave Abrahans] 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? It darn well shouldn't be a container, it should be a concrete type! ;-) [Joel de Guzman] One can think of an optionalT as conceptually a specialized but nevertheless, *IS-A* T, with the added specialization that it can be in a dead-uninitialized state. Maybe we'll call it a zombie object, undead object, you name it ;-) Indeed. However, I suppose I actually have it backwards, because I'm so used to thinking about T. We know that the set of states T can take is a proper subset of the set of states nilableT can take. This means that when we want to write generic code it is sufficient to support nilableT: with an implicit conversion from T to nilableT, support for T directly will come along for free. (Or is it not possible to create such an implicit conversion?) I've been trying to set things up so that code is written for T that can then also use nilableT seamlessly, but doing things the other way around might be an improvement. [Brian McNamara] I was originally arguing with Joel because I thought he wanted to use exactly nv and not anything like nv.get(). I think now that we've cleared up the confusion about get() returning a reference instead of a pointer, we're all back on the same page. Well, I guess you're still arguing with me ;-) because I _do_ want to use exactly nv and not anything like nv.get(). I don't like get() because I cannot write x.get() when x is a POD. This would mean I have to support nilableT and T with different code, which is exactly what I'm trying to avoid. I do agree that if there's a get(), it should return by reference. Dave ___ 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 wrote: 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. :-) I'm not sure I agree. If the ordering scheme proposed by Dirk were 'natural' in some way (as in the case of arithmetic types, std::string, etc.) then I would offer no objection. But in fact it's quite arbitrary. While it is true that there is one and only one strict weak ordering for variant, it is not true IMO that there is one and only reasonable less-than comparison operation for variant. For instance, in certain contexts, it may make sense to allow comparison only between same types, returning false otherwise. In other contexts, it may make sense to allow comparison between any pair of bounded types of the variant (instead of simply between same types). Still in other cases, it may be desirable to allow comparison between a variant and non-variant type. My point is that different users may reasonably desire differing semantics. Worse still, I imagine many users will not realize their desired semantics are not universally desired, and so they may never think to read the docs for operator(variant,variant). The absence of such an operator forces the user to read the docs. That's my argument for boost::variant_before. It requires the user to demonstrate his/her intent explicitly. Other than the additional typing (the required boilerplate), are there other more fundamental objections? (variant in generic contexts, for instance...?) Thanks, Eric ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: generic uses of optionalT
Dave Gomboc wrote: [snip] I don't like get() because I cannot write x.get() when x is a POD. This would mean I have to support nilableT and T with different code, which is exactly what I'm trying to avoid. Why not overload boost::get again for optional? This would certainly improve consistency with variant. For instance: optionalT opt; ... T r = boost::getT(opt); // throws bad_get if opt empty T* p = boost::getT(opt); // p is null if opt empty In the same line, we could make optional visitable: class my_visitor : public boost::static_visitor { void operator()(boost::empty) const { ... } void operator()(const T operand) const { ... } }; boost::apply_visitor( my_visitor(), opt ); Support for visitation would also allow seamless integration with the typeswitch construct I'm working on: switch_(opt) = case_boost::empty( ... ) = case_T( ... ) ; I don't have experience with boost::optional, so I don't know how any of the above would require changes to its interface or concepts. My two cents, Eric ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: generic uses of optionalT
On Mon, Sep 01, 2003 at 12:13:11AM -0600, Dave Gomboc wrote: I've been trying to set things up so that code is written for T that can then also use nilableT seamlessly, but doing things the other way around might be an improvement. Agreed. [Brian McNamara] I was originally arguing with Joel because I thought he wanted to use exactly nv and not anything like nv.get(). I think now that we've cleared up the confusion about get() returning a reference instead of a pointer, we're all back on the same page. Well, I guess you're still arguing with me ;-) because I _do_ want to use exactly nv and not anything like nv.get(). I don't like get() because I cannot write x.get() when x is a POD. This would mean I have to support nilableT and T with different code, which is exactly what I'm trying to avoid. This is trivial to fix: // Adapters to uniform-ify the interface template class T nilableT adapt( T x ) { return nilableT(x); } template class T nilableT adapt( nilableT x ) { return x; } // generic function template class T void do_something( nilableT x ) { ... } // examples demonstrating how code looks same regardless of type do_something( adapt( 3 ) ); do_something( adapt( nilableint(3) ) ); do_something( adapt( foo ) ); // foo has unknown type -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: variant questions
Eric Friedman wrote: But suppose I have a variant v3, with content of a different type (call it T3). Then the assignment v1 = v3 is far more complicated (we can't use T1::operator=) and, without double storage, far more dangerous. The single storage implementation behaves as follows: destroy v1 content copy v3 content into v1 Assuming that memcpy to new location followed by memcpy back to original allocation is safe, you would do it using two additional storages local to operator= function. Let's call them local1 and local2. memcpy variant storage containing value1 into local1 initialize variant storage with copy of value3 content (may throw) memcpy variant storage containing value3 into local2 memcpy local1 back to variant storage destroy the content of variant storage (value1) memcpy local2 back to variant storage If second line of the algorithm above throws then: memcpy variant storage containing value1 into local1 initialize variant storage with copy of value3 content (throws!) memcpy local1 back to variant storage Too complicated? may be ... -- Alexander Nasonov Remove minus and all between minus and at from my e-mail for timely response ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Help requested for Metrowerks workaround
Howard, Howard Hinnant wrote: [snip] If you will mail me a complete condensed demo, I'll take a look. I downloaded boost 1.30.2 but was unable to find boost/variant. -Howard Thanks for offering your assistance. Variant will make its debut in 1.31. Thus, you'll need to work from Boost CVS for now. I haven't been able to isolate the problem, as CodeWarrior generally seems to handle the overloaded constructors without problems. However, the attached test file exposes the error. Thanks again, Eric begin 666 test.cpp M(VEN8VQU94@(F)O;W-T+W9AFEA;G0N:'!P(@T*(VEN8VQU94@(F)O;W-T M+W1EW0O;6EN:6UA;YH' B#0H-G-TG5C=!U9'0-GL-GT[#0H-FEN M=!T97-T7VUA:6XH:6YT([EMAIL PROTECTED][EMAIL PROTECTED]@( @='EP961E9B!B M;V]S=#HZ=F%R:6%N=#QI;G0^(5M8F5D95D7W9AE]T.PT*( @('1Y5D [EMAIL PROTECTED]W0Z.G9AFEA;G0\=61T+!E;6)E91E9%]V87)[EMAIL PROTECTED] M#0H-B @(!C;VYS=!I;[EMAIL PROTECTED]5S=%]V86QU92 ](#,[#0H@( @=F%R7W0@ M=F%R*'1EW1?=F%L=64I.R O+R!I;7!L:6-I=!C;VYV97)S:6]N('1O(5M M8F5D95D7W9AE]T#0H-B @(!E;6)E91E9%]V87)?=[EMAIL PROTECTED] M=F%R([EMAIL PROTECTED]W0Z.F=E=#QE;6)E91E9%]V87)?=#XH=F%R*3L-B @(!I M;[EMAIL PROTECTED]:6YT([EMAIL PROTECTED]W0Z.F=E=#QI;G0^*5M8F5D95D7W9A MBD[#0H-B @(!3T]35%]#2$5#2R@@96UB961D961?:6YT(#T]('1EW1? [EMAIL PROTECTED]@T*( @(')E='5R;B!B;V]S=#HZ97AI=%]S=6-C97-S.PT* #?0T* ` end ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: variant questions
Alexander Nasonov Eric Friedman wrote: But suppose I have a variant v3, with content of a different type (call it T3). Then the assignment v1 = v3 is far more complicated (we can't use T1::operator=) and, without double storage, far more dangerous. The single storage implementation behaves as follows: destroy v1 content copy v3 content into v1 Assuming that memcpy to new location followed by memcpy back to original allocation is safe, you would do it using two additional storages local to operator= function. Let's call them local1 and local2. [snip] If I understand you correctly, earlier versions of variant did precisely what you describe. Unfortunately, the assumption you make is false in general. See http://aspn.activestate.com/ASPN/Mail/Message/boost/1311813. Eric ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: variant questions
Eric Friedman wrote: If I understand you correctly, earlier versions of variant did precisely what you describe. Unfortunately, the assumption you make is false in general. See http://aspn.activestate.com/ASPN/Mail/Message/boost/1311813. Eric Well, is_polymorphicT based on compiler properties beyond the standrad. Why not optimize variant for compilers which safely memcpy forth and back? -- Alexander Nasonov Remove minus and all between minus and at from my e-mail for timely response ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Optional, tie, and iterator_adaptor
--On Sunday, August 31, 2003 9:56 PM -0400 Brian McNamara [EMAIL PROTECTED] wrote: As for the use-case with the function returning a pair of iterators that we'd like to assign to optionals via a tie(), I think there should also be a different method in the interface which returns the hole in an empty optional where a new value can be constructed. See, e.g., my earlier message which defined an interface with operator+() and operator~(). I agree that it seems reasonable to have something other then get() return the hole. operator+() might be confusing when used with optionalint's or other numeric types, so perhaps something like unchecked_reference(), or unwrap() or any other non-operator() would be best when getting at the hole. - Mat ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: generic uses of optionalT
Eric! You DA Man! -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net Eric Friedman [EMAIL PROTECTED] wrote: Dave Gomboc wrote: [snip] I don't like get() because I cannot write x.get() when x is a POD. This would mean I have to support nilableT and T with different code, which is exactly what I'm trying to avoid. Why not overload boost::get again for optional? This would certainly improve consistency with variant. For instance: optionalT opt; ... T r = boost::getT(opt); // throws bad_get if opt empty T* p = boost::getT(opt); // p is null if opt empty In the same line, we could make optional visitable: class my_visitor : public boost::static_visitor { void operator()(boost::empty) const { ... } void operator()(const T operand) const { ... } }; boost::apply_visitor( my_visitor(), opt ); Support for visitation would also allow seamless integration with the typeswitch construct I'm working on: switch_(opt) = case_boost::empty( ... ) = case_T( ... ) ; I don't have experience with boost::optional, so I don't know how any of the above would require changes to its interface or concepts. ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] [for Win] [was: Re: 1.30.0-1.30.2: no more thread supportfor Linux?]
Hi, I haven't followed this thread completely, but I have a question. I'm working on Win 2k, and I'm using VC++ 7.1. Building boost with this toolset, do I need to specify something to make it thread-safe? TIA, Viv - Original Message - From: John Maddock [EMAIL PROTECTED] To: Boost mailing list [EMAIL PROTECTED] Sent: Sunday, August 31, 2003 12:33 PM Subject: 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 ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: [boost.variant] It is possible to make avariantLessThanComparable
Eric Friedman wrote: Peter Dimov wrote: 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. :-) I'm not sure I agree. If the ordering scheme proposed by Dirk were 'natural' in some way (as in the case of arithmetic types, std::string, etc.) then I would offer no objection. But in fact it's quite arbitrary. It's not arbitrary at all. Ask several randomly selected programmers what operator should do. It is not reasonable to declare the ordering unnatural just because you don't like it. If there is one ordering, then this is the natural ordering, whether we like it or not. While it is true that there is one and only one strict weak ordering for variant, it is not true IMO that there is one and only reasonable less-than comparison operation for variant. For instance, in certain contexts, it may make sense to allow comparison only between same types, returning false otherwise. In other contexts, it may make sense to allow comparison between any pair of bounded types of the variant (instead of simply between same types). Still in other cases, it may be desirable to allow comparison between a variant and non-variant type. My point is that different users may reasonably desire differing semantics. Worse still, I imagine many users will not realize their desired semantics are not universally desired, and so they may never think to read the docs for operator(variant,variant). Note heavy speculation. May make sense in certain contexts. May make sense in other contexts. May be desirable. Users may reasonably desire different semantics. Have you considered the possibility that, in practice, it/they perhaps might not? The absence of such an operator forces the user to read the docs. That's my argument for boost::variant_before. It requires the user to demonstrate his/her intent explicitly. Other than the additional typing (the required boilerplate), are there other more fundamental objections? The fundamental objection is that you should not penalize the majority because someone might need different operator semantics. Provide operator. Wait six months. Collect feedback. If there is evidence that operator is evil, remove it and document why it is not supplied. ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] [for Win] [was: Re: 1.30.0-1.30.2: no more threadsupportfor Linux?]
I haven't followed this thread completely, but I have a question. I'm working on Win 2k, and I'm using VC++ 7.1. Building boost with this toolset, do I need to specify something to make it thread-safe? Actually you need to do more than that - you need to compile Boost against the same runtime library options that you use to build your application - otherwise you will get linker errors at the very least. Relevant options are: threadingmulti : multithreaded builds threadingsingle : single threaded builds runtime-linkdynamic : dynamic runtime runtime-linkstatic : static runtime. The default behaviour is to build against the dynamic (and thread safe) runtime, so if that's what you are using then you're OK, if you want the static runtime library versions as well then: bjam -sTOOLS=vc7.1 -sBUILD=debug release threadingmulti/single runtime-linkstatic will do the job. Oh, and to answer your question: Boost is always as thread safe as the runtime it's built against. John. ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Any interest in a string literal selector helper library?
Subject: [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 ) ); } I've done this before as well. But it's a very simple function. And I assume TestAutoSelect is a macro. Can I take a look at the code? Best, 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 wrote: Dirk Schreib [EMAIL PROTECTED] writes: I would like a variant to be LessThanComparable if all BoundedTypes are LessThanComparable. 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 ). I assume that the resulting variant class will be StrictWeaklyComparable if all BoundedTypes are StrictWeaklyComparable. Sounds like maybe you want dynamic_any. Have you looked at Alexander Nasonov's work? I would like to emphasize one difference with variant library. User should _add_ less operation to the list of supported operations to enable operator. This operator isn't enabled by default. This protects from undesirable effects because if the user added less I can assume that she knows what she's doing. But the problem of different order is still persist. I think we should coordinate our work on variant and dynamic_any library. The discussed problem is one point where coordination is needed. Both libraries work with some set of types by (i) storing value of one selected type and (ii) calling some operation for stored value. This is done with some differences, though. In assumption that typedefs for variant and dynamic_any fixed I can say that: 1. variant operates with _fixed_ set of stored types but with _open_ set of supported operations (through static_visitor) 2. dynamic_any has _open_ set of stored type but _fixed_ set of supported operations There is also some differences in operation support. Variant's operation looks like: struct print : static_visitorvoid { std::ostream out_; print(std::ostream out) : out_(out) {} templateclass T void operator()(const T value) const { out_ value; } }; while dynamic_any operation looks like: struct print : functionprint, void (std::ostream, const anyT) { templateclass T void call(std::ostream out, const T value) const { out value; } }; On one hand, variant uses operator() which is good for anonymous operations (obviously, it's not possible for dynamic_any): variantint, char v(0); // anonymous function is ok apply_visitor(v, std::cout _1); // error, attempt to call std::cout v for_each(v, v + 1, std::cout _1); // ok for_each(v, v + 1, print(std::cout)); On the other hand, dynamic_any has better support for std algorithms, lambda, bind, etc (well, in variant case it's also possible by binding apply_visitor): dynamic_any::anympl::listprint a(0); // ok, direct call print()(std::cout, a); // ok if result of print doesn't contain anyT (void doesn't) // otherwise, bindR is required for_each(a, a + 1, bind(print(), std::cout, _1)); Other advantage of dynamic_any is a possibility to mix normal arguments and anyT-based. Due to nature of dynamic_any it's not possible to call the operation containing two or more anyT-based arguments for arbitrary arguments. Call can be made only if all any arguments hold same type or are derived publicly from one type T stored by one any argument. However, less works fine with arbitrary types because I added call_ex/no_call mechanism to the library. In variant the set of stored types is fixed and all combinations can be considered (be careful, it may cause combinatorial explosion): struct plus : variant::functionplus, variantT (variantT, variantT) { templateclass T1, class T2 typeof(v1 + v2) call(T1 v1, T2 v2) const { // Note that T1 and T2 are in general // different (in opposite to dynamic_any) return v1 + v2; } templateclass T2 std::string call(std::string v1, T2 v2) const { return v1 + lexical_caststd::string(v2); } templateclass T1 std::string call(T1 v1, std::string v2) const { return lexical_caststd::string(v1) + v2; } // ... }; variantstd::string,int,char s(s); variantstd::string,int,char i(0); variantstd::string,int,char s0 = plus()(s, i); // s2 == std::string(s0) -- Alexander Nasonov Remove minus and all between minus and at from my e-mail for timely response ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] adaptable_any vs any_with
I'm asking for voting for the new name of dynamic_any. Please, give you preference. Here is my discussion about the name with Kevlin Henney ( and empty prefix - Kevlin, - me) --- cut --- Have you had any more thoughts on an alternative name? Something like adaptable_any or extensible_any? I really don't like the current name and I don't like the fact that namespace has different name. If I understand meaning of the word, extensible_any is not a right name because when you extend operation list you narrow a set of supported types. Good point! reducible_any ;-) Sometimes this set can be so narrow that I doubt about 'any' in name! adaptable_any is much better. I like it. It seemed to be the best of the rest. Another thought might be to take advantage of the way you might read what is written. Instead of naming the operation list operation_list, name it io_operations. Instead of dynamic_any, or even adaptable_any, use the name any_with. This would give you any_withio_operations, which reads as a perfectly accurate description in English. Kevlin --- end of cut --- -- Alexander Nasonov Remove minus and all between minus and at from my e-mail for timely response ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] [for Win] [was: Re: 1.30.0-1.30.2: no morethreadsupportfor Linux?]
Thanks for your reply. I've created my own vcproj (VC++ 7.1 project) for building the libs that I need, and I've used the /MD flag which is the multithread- and DLL-specific versions flag (used also for my application), which means that everything is fine, right? Thanks a lot, Viv - Original Message - From: John Maddock [EMAIL PROTECTED] To: Boost mailing list [EMAIL PROTECTED] Sent: Monday, September 01, 2003 12:13 PM Subject: Re: [boost] [for Win] [was: Re: 1.30.0-1.30.2: no more threadsupportfor Linux?] I haven't followed this thread completely, but I have a question. I'm working on Win 2k, and I'm using VC++ 7.1. Building boost with this toolset, do I need to specify something to make it thread-safe? Actually you need to do more than that - you need to compile Boost against the same runtime library options that you use to build your application - otherwise you will get linker errors at the very least. Relevant options are: threadingmulti : multithreaded builds threadingsingle : single threaded builds runtime-linkdynamic : dynamic runtime runtime-linkstatic : static runtime. The default behaviour is to build against the dynamic (and thread safe) runtime, so if that's what you are using then you're OK, if you want the static runtime library versions as well then: bjam -sTOOLS=vc7.1 -sBUILD=debug release threadingmulti/single runtime-linkstatic will do the job. Oh, and to answer your question: Boost is always as thread safe as the runtime it's built against. John. ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: [boost.variant] It is possible to make avariantLessThanComparable
Peter Dimov [EMAIL PROTECTED] writes: Eric Friedman wrote: Peter Dimov wrote: 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. :-) I'm not sure I agree. If the ordering scheme proposed by Dirk were 'natural' in some way (as in the case of arithmetic types, std::string, etc.) then I would offer no objection. But in fact it's quite arbitrary. It's not arbitrary at all. Ask several randomly selected programmers what operator should do. It is not reasonable to declare the ordering unnatural just because you don't like it. If there is one ordering, then this is the natural ordering, whether we like it or not. I just started reading this thread, half way through, and so I didn't know what Doug's proposed ordering was until I looked it up. It turns out that his ordering is exactly what I assumed it would be --- if the types are different, then the one which comes first in the list is less than the other; if the types are the same, compare the values. It seems natural to me. My point is that different users may reasonably desire differing semantics. Worse still, I imagine many users will not realize their desired semantics are not universally desired, and so they may never think to read the docs for operator(variant,variant). Note heavy speculation. May make sense in certain contexts. May make sense in other contexts. May be desirable. Users may reasonably desire different semantics. Have you considered the possibility that, in practice, it/they perhaps might not? Indeed, if people need different semantics, they are free to provide a function; they can even supply it to standard algorithms and containers if they wish. The absence of such an operator forces the user to read the docs. That's my argument for boost::variant_before. It requires the user to demonstrate his/her intent explicitly. Other than the additional typing (the required boilerplate), are there other more fundamental objections? The fundamental objection is that you should not penalize the majority because someone might need different operator semantics. Provide operator. Wait six months. Collect feedback. If there is evidence that operator is evil, remove it and document why it is not supplied. I agree with Peter. Anthony -- Anthony Williams Senior Software Engineer, Beran Instruments Ltd. Remove NOSPAM when replying, for timely response. ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] SourceForge CVS performance upgrade
This hasn't happened yet. Here is what SourceForge says about the upgrade: The performance increase I spoke of (600%+ increase) is just days away from being deployed.The new systems are now in place, additional electrical power has been added to our colocation cage, and the Linux boxes are in their final stages of configuration. Hang in there. Help is on the way. --Beman ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Re: Optional, tie, and iterator_adaptor
Joel de Guzman [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] Fernando Cacciola [EMAIL PROTECTED] wrote: Hi Mat, Thanks for the input. optional is now out on the field and it is the only utility of its kind I've ever seen in C++, at least in real use. This has the drawback that there is very little experience with it. Therefore, in a way it is a sort of There's a lot of experience with it in other languages. Why not leverage that? Haskell::Maybe for instance. Do you know of anything else besides Haskell? I don't, and I took the time to investigate Maybe looking at Haskell programs using it. As Brian pointed out, it is not so easy to port Maybe to C++ because its usage is extensively supported by Haskell features that are not present in C++. The most fundamental point is that being Haskell a pure functional language there is no possibly undefined behaviour to worry about, so Maybe doesn't need to address this issue as optional does. experiment, even though it is now a fixed part of Boost. optional will evolve, that's for sure, as user's experience show which design desicions were right and which were wrong. I might even deprecate it and submit a replacement if it becomes clear that a drastic change is neccesary. Right now I still believe that the pointer-like interface is correct, because I add it specifically to solve a real problem and it did solve it. My first optional (named differently then) had the problem that it was really difficult to track which variables were 'optionals' and hence it was easy to forget to make the neccesary steps to mantain integrity (not to use an uninitialized optional). At some point I realized that I needed something at the syntax level that help me keep in mind that those variables are possibly uninitialized, and so I moved from value() member functions to operatos * and - If that's the only rationale for having the pointer-like interface, then pardon me but, I find that very flimsy. There should be other means to attack the problem (if it is a problem) without sacrificing the beauty of the interface. I account the possibly undefined behavior of accesing an uninitialized optional as a real and important problem. From now on I'll refer to this as the Possibly Uninitialized Problem: the PU problem in short. The interface, in one way or another, should address this. The pointer-like interface is just about syntax really. Instead of opt.value() you type (*opt) or opt- This alone shouldn't be a problem. Right. What I think it is a problem are other design descicions that I made in order to make other parts of the interface with the pointer-like interface. Namely, the lack of implicit construction and direct assignment. Sacrificing this in order to track which variables were 'optionals' ?, IMO, is not a good idea. I agree. These two points are raised here by Mat and have been raised by many others in the past. 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. If optional had value semantics, it would be a lot cleaner: optionalint opt; opt = 1; i = opt; First of all, let's not confuse syntax with semantics. optional HAS strict value semantics. If the choice of 'operators *', 'operator -' and 'get()' as value accessors makes the appearance that is has pointer semantics, then it is the documentation that has to be fixed, not the interface. vector::begin returns an object with operators * and -, yet these objects are not pointers, and once that is learned, people do not think they are pointers. Also, let's not think of the pointer-like interface as a unity: there are three items involved, namely *,- and get(). We'll be better off considering them separately. Direct initialization: opt = 1 seems right since this operation is never undefined. This would mirror variant's interface. Direct value accesing via implicit conversion: int i = opt seems wrong because this is the operation that can lead to undefined behaviour. For those concerned about trackability, they can use an easy to grep alternative: optionalint opt; opt .reset(1); i = opt.get(); Addressing the PU problem via a 'get()' function returning a _reference_ seems right, but OTOH, using operator * seems even better because the expressions of the form (*a) have a very familiar meaning and is that meaning _exactly_ what we need here. But don't let the rest of the optional interface get in the way of this argument. If we agree that _some_ explicit function/operator is needed as a value accesor, then in itself, operator* is IMO clearly the best choice. Now I understand that generic uses of optional beg for conventional 'syntax' for assignment and initialization. True! I could drop the pointer-like interface but only if replaced by some member function that aids to
[boost] Re: Re: Optional, tie, and iterator_adaptor
Brian McNamara [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] On Sun, Aug 31, 2003 at 09:58:45AM +0800, Joel de Guzman wrote: Fernando Cacciola [EMAIL PROTECTED] wrote: Hi Mat, Thanks for the input. optional is now out on the field and it is the only utility of its kind I've ever seen in C++, at least in real use. This has the drawback that there is very little experience with it. Therefore, in There's a lot of experience with it in other languages. Why not leverage that? Haskell::Maybe for instance. I feel like Maybe works more smoothly in Haskell than in C++, but I haven't ever really tried to nail down the reasons why. This thread has me thinking about it more, though, so I'll share some general thoughts (as well as some suggestions for optional at the end). Two issues spring to mind immediately: pattern matching and monads. Pattern matching: Haskell's Maybe is a type constructor, and thus the value constructors Just and Nothing can be used in pattern matches. Pattern matching provides a common way to do the test and the unwrap steps. Code like optionalint o; ... if( o ) do_something( *o ); else maybe_do_other(); in C++ sometimes takes a form like o :: Maybe int ... case o of Just x - doSomething x Nothing - maybeDoOther in Haskell. Since this form of using pattern matching to case-ify and deconstruct a datatype is a standard idiom in Haskell, nothing special needs to be done for Maybe. Monads: In addition, Maybe forms a monad, which means that you can use do-notation to string together computations involving Maybes. Code like optionalint x, y, z, result; ... if( x ) { y = foo( *x ); if( y ) { z = bar( *x, *y ); if( z ) result = baz( *x, *y, *z ); else result.reset(); // being more explicit than I have to be } else result.reset(); } else result.reset(); can be written as x, y, z, result :: Maybe int ... do x - x y - foo x z - bar x y result - baz x y z return result in Haskell, which uses the Monad's bind operation to sugarize over all the if-then-else plumbing to push Nothings all the way through the computation. In FC++, we have monad comprehensions, so it could be written as just maybeint x; ... fcomp_mmaybe_m()[ baz[X,Y,Z] | X = x, Y = foo[X], Z = bar[X,Y] ] Comprehensions are unlikely to be used much in normal C++ code, though. In any case, I suppose my point with both of those issues is that Haskell already has some kind of standard/idiomatic way to sugarize over the details of dealing with Maybes. I don't think we have anything equivalent in C++, so it's not clear to me what we can learn from Haskell when trying to design the interface for optional in C++. Hi Brian, thanks fot the input. I've reach a similar conclusion when I looked at Maybe for inspiration. Offhand, the pointer interface for reading the value of an optional seems good to me. Being able to say optionalint x; ... if( x ) foo( *x ); seems like a natural way to sugarize this in C++. Great! That's for I think too. As for the constructors, why not have a separate function for initializing optionals, a la Just/Nothing in Haskell? I am imagining something like this: template class T class optional { optional(); // or maybe public, depending on preference optional( const T ); // private public: optional( const optional );// still copyable, optional operator=( const optional ); // assignable ... operator bool ... operator* }; template class T optionalT just( const T ); // the constructor (a friend) Then you no longer have the issue of optionalint x(3); int r = *x; optionalint y = 4; r = *y; looking funny or unbalanced, because now it's optionalint x( just(3) ); int r = *x; optionalint y = just(4); r = *y; and the just balances out the *, in a way. (This is similar to what we do with maybeT in FC++, though we don't have the op-bool/op-* sugar for reading maybes. In FC++, the constant NOTHING can also be used to initialize an empty maybe.) I'm not so sure anymore if the unbalance really needs to be addressed. Solutions like the one you propose above do certainly add 'purity' to the interface, but OTOH makes it harder to use. I stress as fundamental the fact that initialization and assignment is always defined, so I'm not sure if special syntax is really needed since there is nothing to protect against. Sure, the concept may be confusing _at first_, but once the user learns it, she can leverage the power of a terser syntax. So in this regard I prefer the variant way: support implicit
[boost] Re: Re: Optional, tie, and iterator_adaptor
Joel de Guzman [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] Brian McNamara [EMAIL PROTECTED] wrote: Offhand, the pointer interface for reading the value of an optional seems good to me. Being able to say optionalint x; ... if( x ) foo( *x ); seems like a natural way to sugarize this in C++. IMO, this is better: optionalint x; if (x == none) foo(x); Although I don't see this as problematic: optionalint x; if (x) foo(x); Or perhaps: optionalint x; if (!!x) foo(x); I see the implicit value access (in foo(x)) as problematic for the reasons I gave before. 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; Yes, I think this should be kept. There is a special section on the documention dealing with the specific case of optionalbool just in order to support these _very_ idiomatic operations. Perhaps it's just me, but I really dislike the * syntax. Why make optional pretend that it is a pointer when it's clearly not! Then, we go on and give it value semantics! C'mon! The * syntax is not supposed to make optional pretend it is a pointer. It is clearly not and the documentation says so quite clearly, I think. And if it doesn't, then it is the documentation that needs to be fixed. Fernando Cacciola ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Optional, tie, and iterator_adaptor
Fernando Cacciola [EMAIL PROTECTED] wrote: First of all, let's not confuse syntax with semantics. optional HAS strict value semantics. No it does not. The accessors have pointer behavior! -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Re: Optional, tie, and iterator_adaptor
Joel de Guzman [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] 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); safe_bool conversion wasn't part of the original submision. I was against it for the reasons you give, but at some point I was conviced that the expressive power of the highly idiomatic implicit boolean evaluation was worth it. So many objects provide boolean evaluation through implicit conversion that it is nowaday the most common interface for this operation. 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's wrong operators * and -? Iterators use them, and they're not pointers. If the problem is that it makes optional appear as a pointer, then it is the documentation job to avoid it. What I am trying very hard to say is to stick to only *ONE* interface and one concept. How does the presence of operator* and - makes two interfaces? optional has only one interface and one concept. It just happen to use the ubiquitous * and - syntax to express the same notion that is expressed through those operators when they're used with pointers and iterators, but this doesn't mean that optional pretends to be a pointer or an iterator. 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); Implicit safe_bool was supported becasue it is extremely idiomatic. A small price to pay, considering the advantages. 1) Unification of the optional and variant where optionalT -- variantT, none_t. variant doesn't support implicit conversion to any of its bounded types. It does support implicit construction and direct assignment, as I've proposed for optional at my first post in this thread. variant has get() as a value accessor. optional has operator*() with the same semantic (forget about optional's get() now) 2) Only one underlying semantics (value-semantics) as opposed to (sometimes value, sometimes pointer semantics) There is just one underlying semantic in optional: value semantics. and 3) Plays well with generic code (I'll give another use-case in addition to Mat's). This can be addressed by fixing optional::get() to return a reference instead of a pointer. (more on this on another post) Fernando Cacciola ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Optional, tie, and iterator_adaptor
Fernando Cacciola [EMAIL PROTECTED] wrote: vector::begin returns an object with operators * and -, yet these objects are not pointers, and once that is learned, people do not think they are pointers. Huh? pointer semantics (behavior) does not mean that they have to be pointers. -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Re: Optional, tie, and iterator_adaptor
Brian McNamara [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] On Mon, Sep 01, 2003 at 09:03:17AM +0800, Joel de Guzman wrote: Do it the ref, tuple and variant way: get(). But get(), as an element-access interface, should return a reference, not a pointer, as it does currently. Clearly I had not been paying enough attention earlier in the thread; I was oblivious to the fact that get() was returning a pointer and not a reference. I think get() (or operator*(), or however it ends up being spelled) should indeed return a reference. operator*() does indeed return a reference, and I agree that operator get() should too. Anyway, there is a pragmetic advantage in having a function return a pointer. It allow us to mix test+access with one call, as in: if ( T* p = opt.get() ) but this functionality can be provided but a separate methods called get_ptr() given the expected meaning of a method named get() for something that is a value container. Fernando Cacciola ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Optional, tie, and iterator_adaptor
Fernando Cacciola [EMAIL PROTECTED] wrote: Joel de Guzman [EMAIL PROTECTED] wrote in message There's a lot of experience with it in other languages. Why not leverage that? Haskell::Maybe for instance. Do you know of anything else besides Haskell? No. I don't, and I took the time to investigate Maybe looking at Haskell programs using it. As Brian pointed out, it is not so easy to port Maybe to C++ because its usage is extensively supported by Haskell features that are not present in C++. The most fundamental point is that being Haskell a pure functional language there is no possibly undefined behaviour to worry about, so Maybe doesn't need to address this issue as optional does. Agreed. -- 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] Re: Re: Optional, tie, and iterator_adaptor
Fernando Cacciola [EMAIL PROTECTED] wrote: Joel de Guzman [EMAIL PROTECTED] wrote in message Direct initialization: opt = 1 seems right since this operation is never undefined. This would mirror variant's interface. Ok. Direct value accesing via implicit conversion: int i = opt seems wrong because this is the operation that can lead to undefined behaviour. Doesn't have to be undefined behaviour. Aren't you throwing an exception or something? variant throws throws a bad_get exception when you get a reference to a T which is not the held type. I don't see a problem why you can't do something similar. -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Re: Optional, tie, and iterator_adaptor
Mat Marcus [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] 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. [snip use case] FWIW, your use case of pretty common to me. I've used optional precisely as you did many times. In fact, I often found mayself adding optional to a local variable just because the flow changed and now the variable may reach a point being uninitialized. 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); file://sorry, ASSERT looks too strange Wow, that looked strange to me. I don't think of begin and end as pointers at all here. Right, they're not pointers and you shouldn't see them as such. I think that your report is very important because it shows me that while one may expect the need for special constructs in order to 'access' an optional value, such need isn't there when one wants to initialize or assign an optional. It was very reasonable to expect optional to work with tie as that is just assignment and assignment is always defined. 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). I agree here. Such a concept might perhpaps embody notions of initialization via construction or assignment, testing whether the model has been initialized, etc. Right. 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. I think that OptionalPointee's documentation failed its purpose. That concept is intended to be exactly what you proposed, except that I left initialization/assignment aside. The concept just explains that the operator * and - syntax is used to access the a value that is possibly uninitialized, WITHOUT implying that a model of this concept IS a pointer. The concept was invented precisely to allow the same syntax to be used with entities that are NOT pointers. The particular choice of operators is to allow pointers to be models of the concept. Perhaps it is the name which is misleading. It can be renamed as PossiblyUninitialized if that helps. And it should incorporate initialization and assignment. Anyway, both concepts are 'conceptually' the same. Fernando Cacciola ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Re: Optional, tie, and iterator_adaptor
Brian McNamara [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] On Sun, Aug 31, 2003 at 12:34:39AM -0700, Mat Marcus wrote: [snipped] 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.) My original submission used a proxy operator*() to allow assignment in the same way you do here with operator+(). During the review I removed it because if expressions (*opt) implied possibly undefined behaviour when used a rvalues so should when used as lvalues. Yet assignment is always defined so be changed it by reset(). It didn't ocurred to me though to use _another_ operator instead, and so allow the definitely useful lvalue expressions. Right now however, I'm inclined toward direct assignment, ala variant, because the only problem with this is the potential conceptual confusion (since this operation is always defined), and I prefer to address this problem at the documentation level. Fernando Cacciola ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Re: Optional, tie, and iterator_adaptor
Brian McNamara [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] 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. In a way you're right. My original optional submision followed this rule. safe-bool was added because of the ubiquitousness of the implicit boolean evaluation idiom. Implicit construction and direct assignment was left out precisely in order to keep both interfaces separated. 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! Right. Just like any XYZB is not an B, so the middle line should have the cannonical form: XYZB b = get2(args).get(); Therefore, it is optional::get() that needs to be fixed, not optional::operator*(), and not adding an implicit conversion to T. Fernando Cacciola ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Re: Optional, tie, and iterator_adaptor
Joel de Guzman [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] 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. One can think of an optionalT as conceptually a specialized but nevertheless, *IS-A* T, with the added specialization that it can be in a dead-uninitialized state. Maybe we'll call it a zombie object, undead object, you name it ;-) Theoretically, yes. But there are practical barries here. Unfortunately, in C++ subclassing is the only subtying mechanism, but you can't subclass a non class type, so you can't subtype an arbitrary T. IOWs, there is no way to completely implement an optionalT which *IS A* T. The closer we could get is to have an implicit ctor and and implicit conversion to T, but that would only take us half the way, so there is little practical sense in approaching the problem this way. 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! Even if I agree with you that an optionalT should not be a T, an optionalT is definitely not a pointer to T. Definitely! If HTML had blinking banners I think I'd use one to state this :-) Yet iterators are not pointers either but they do use operators * and - 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'). Right. In fact, looking at it more closely, I *could* almost agree with you that an optionalT is not a T. There is in fact a getter function (get). In fact all three (tuple, optional and variant) have a get function. That's fine, yet, here again, the optional does not jive well because it returns access *by pointer* whereas both tuple and variant return access by reference. This get() issue we agree should be fixed. Fernando Cacciola ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: generic uses of optionalT
Eric Friedman [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] Dave Gomboc wrote: [snip] I don't like get() because I cannot write x.get() when x is a POD. This would mean I have to support nilableT and T with different code, which is exactly what I'm trying to avoid. Why not overload boost::get again for optional? This would certainly improve consistency with variant. For instance: This was my intention from the very beginning. I was just waiting for variant to be out there. In the same line, we could make optional visitable: And so about this. Fernando Cacciola ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Optional, tie, and iterator_adaptor
--On Monday, September 01, 2003 2:57 PM -0300 Fernando Cacciola [EMAIL PROTECTED] wrote: Mat Marcus [EMAIL PROTECTED] wrote in message [snip] 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); file://sorry, ASSERT looks too strange Wow, that looked strange to me. I don't think of begin and end as pointers at all here. Right, they're not pointers and you shouldn't see them as such. I think that your report is very important because it shows me that while one may expect the need for special constructs in order to 'access' an optional value, such need isn't there when one wants to initialize or assign an optional. It was very reasonable to expect optional to work with tie as that is just assignment and assignment is always defined. Yes, it seems like optional is just the sum (disjoint union) of nil and T, so why not allow implicit construction and assignment from T. Of course, I realize that there may be technical obstacles to getting optional to work transparently with tie in this way(doesn't tie normally create a tuple of references?). [snip] I think that OptionalPointee's documentation failed its purpose. That concept is intended to be exactly what you proposed, except that I left initialization/assignment aside. The concept just explains that the operator * and - syntax is used to access the a value that is possibly uninitialized, WITHOUT implying that a model of this concept IS a pointer. The concept was invented precisely to allow the same syntax to be used with entities that are NOT pointers. The particular choice of operators is to allow pointers to be models of the concept. Perhaps it is the name which is misleading. It can be renamed as PossiblyUninitialized if that helps. OptionalPointee is a bit misleading for me. Also I work in a group that is ultimately responsible for transferring our technology to the product teams, so I need to be able be convince others that my code will be maintainable. I will probably choose to avoid the pointer-like operator interface since I think it makes optional harder to use/explain. I'm not sure that PossiblyUninitialized is the best name for the concept, but it works a bit better for me since it's more about Optional and less about (the arguably distracting) Pointee. And it should incorporate initialization and assignment. [snip] Great. This should definitely help with my use cases. I'm still curious whether there will be a recipe to use optional with tie. And if there is such a recipe I wonder whether pointer will still be a model of the Concept. - Mat P.S. Doesn't ML have offer an option type? Haven't had a chance to look into this yet. ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Optional, tie, and iterator_adaptor
On Monday, Sep 1, 2003, at 11:31 America/Denver, Joel de Guzman wrote: Fernando Cacciola [EMAIL PROTECTED] wrote: vector::begin returns an object with operators * and -, yet these objects are not pointers, and once that is learned, people do not think they are pointers. Huh? pointer semantics (behavior) does not mean that they have to be pointers. But would the following hold if p and q are optionlint? *q = 1; p = q; *p = 2; assert(*q == 2); ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Reducing template compile-times
Template libraries, especially those employing expression templates, take a long time to compile. As an example, one of the example files for FC++ (parser.cpp) takes about 10 minutes to compile on a blazingly fast machine with tons of RAM. I would like to reduce the compile-time. I solicit any help/advice on the topic; I am hoping some of the Boost contributors will have run into this same problem with their own libraries, and have found some ways to address it. Here is what I have already figured out. First off, in FC++, there are a number of templates whose sole purpose is to provide better compiler diagnostics (along the same general lines as concept_checks). I rewrote the library code so that these checks are only enabled when a certain preprocessor flag is defined. Turning off these checks reduced the compile-time of parser.cpp from 10 minutes to 8 minutes--a significant speedup. That was the most obvious piece of low-hanging fruit; since the code to produce the compile-time diagnostics doesn't do anything at run-time, it was straightforward to just have a switch to turn it on and off. I imagine there are other things I can do to rewrite some of the library templates that are doing real work so that they compile faster. Specifically, I imagine that some templates can be rewritten so that they cause fewer auxiliary templates to be instantiated each time the main template gets instantiated. However there are two issues that make this hard to do: (1) Knowing which templates to focus on. That is, which templates are effectively the inner loops in the compilation process, and thus deserve the most attention when it comes to optimizing them? (2) Knowing how to rewrite templates to make them faster. I imagine that fewer templates instantiated will mean faster compile times, but I don't actually know this for sure. I have no window into what the compiler is actually doing, to know what takes so long. Maybe it's the template instantiation process; maybe it's all the inlining; maybe it's the code generation for lots of tiny functions. I don't know. I have made some headway with (1): the unix utility nm lists all the symbols compiled into an executable program, and by parsing the output, I am able to determine which templates have been instantiated with the most number of different types. My little script yields output like ... 313 boost::fcpp::lambda_impl::exp::Value 314 boost::fcpp::lambda_impl::BracketCallable 606 boost::fcpp::lambda_impl::exp::CONS 609 boost::fcpp::full1 610 boost::intrusive_ptr 670 boost::fcpp::lambda_impl::exp::Call which tells me that the Call template class has been instantiated 670 different ways in parser.cpp. This at least gives me some idea of which classes to focus my optimizing attention on. However a drawback of using the nm approach is that it only shows templates with run-time storage. There are tons of template classes which contain nothing but typedefs, and I imagine they're being instantiated lots of ways too, and I don't know if this slows stuff down significantly too. As to (2), I know nothing, other than the speculation that fewer instantiations is better. So, that's where I am. Help! :) -- -Brian McNamara ([EMAIL PROTECTED]) ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Optional, tie, and iterator_adaptor
Fernando Cacciola [EMAIL PROTECTED] wrote: Even if I agree with you that an optionalT should not be a T, an optionalT is definitely not a pointer to T. Definitely! If HTML had blinking banners I think I'd use one to state this :-) Nor should it model a pointer. That was my point and the point of others who dislike *opt. Yet iterators are not pointers either but they do use operators * and - Iterators are not pointers, but they model the pointer. Right. In fact, looking at it more closely, I *could* almost agree with you that an optionalT is not a T. There is in fact a getter function (get). In fact all three (tuple, optional and variant) have a get function. That's fine, yet, here again, the optional does not jive well because it returns access *by pointer* whereas both tuple and variant return access by reference. This get() issue we agree should be fixed. Agreed. If there's a way to get at the values through a generic get function that unifies the access of optional with variant such that I can think of optional as an optimized specialization of variantT, none, I would be very happy. With such an interface, I can simply ignore the pointer-like interface, if you wish to keep it ;-) Thanks you very much! And BTW, kudos for such a well engineered library! Spirit has been using it since v1.7 and I am very happy with it. The comments I gave so far are merely my opinion. You are of course free to have your own preferences :-) Keep up the good work! Regards, -- 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] Re: Re: Optional, tie, and iterator_adaptor
Gregory Colvin [EMAIL PROTECTED] wrote: On Monday, Sep 1, 2003, at 11:31 America/Denver, Joel de Guzman wrote: Fernando Cacciola [EMAIL PROTECTED] wrote: vector::begin returns an object with operators * and -, yet these objects are not pointers, and once that is learned, people do not think they are pointers. Huh? pointer semantics (behavior) does not mean that they have to be pointers. But would the following hold if p and q are optionlint? *q = 1; p = q; *p = 2; assert(*q == 2); No, because the model is half-baked, which is exactly the reason for my dislike. -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Re: Re: Optional, tie, and iterator_adaptor
Joel de Guzman [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] Fernando Cacciola [EMAIL PROTECTED] wrote: Joel de Guzman [EMAIL PROTECTED] wrote in message Direct value accesing via implicit conversion: int i = opt seems wrong because this is the operation that can lead to undefined behaviour. Doesn't have to be undefined behaviour. Yes it does. Accesing a value that isn't there is by all means undefined behaviour. Aren't you throwing an exception or something? This doesn't define the access value operation. It just defines the function that is used to implement it. But defining such a call doesn't help much from the POV of the operation. i.e., you cannot get the value if it isn't there and an exception here is no better at it than a core dump. Therefore, the operation is flaged as possibly undefined. Whether to detect and throw, or assert, or do nothing is QoI issue. If optional were to be someday standarized, implementators would decide how to deal with the undefined behaviour here. variant throws throws a bad_get exception when you get a reference to a T which is not the held type. I don't see a problem why you can't do something similar. Doing something similar as an implementation detail is fine. Currently, I use BOOST_ASSERT, which allows the end user to control how to deal with it. Doing it as part of the interface, that is, contracting that accesing an uninitialized optional throws an exception has performance and portability problems. In most typical usages, you don't really need a runtime check to get always in the way of getting the value. In fact, the pointer like syntax is there precisely to help you be confident that an explicit check is not needed since the access syntax lends itself to well written code were uninitialized access is properly guarded in the client code, allowing you to leverage the speed of unguarded access while giving you at the same time the idiomatic power of a familiar syntax to access possibly uninitialized values. Fernando Cacciola ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Boost memory management guidelines
Gregory Colvin [EMAIL PROTECTED] writes: 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. Regardless, there is absolutely _nothing_ in the standard AFAICT which indicates the containers must use the allocator's construct and destroy, and several implementations in fact do not. -- Dave Abrahams Boost Consulting www.boost-consulting.com ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: xml library
I've just uploaded the preliminary version of my XML library to Yahoo files section as xml_library.zip. Comments are welcome. I think it's very nice, and I can already think of some code that could be made much clearer using this... ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Reducing template compile-times
Brian McNamara [EMAIL PROTECTED] writes: Template libraries, especially those employing expression templates, take a long time to compile. As an example, one of the example files for FC++ (parser.cpp) takes about 10 minutes to compile on a blazingly fast machine with tons of RAM. Which compiler? Have you seen http://users.rcn.com/abrahams/instantiation_speed/index.html? I would like to reduce the compile-time. I solicit any help/advice on the topic Switching compilers may be your best bet. I am hoping some of the Boost contributors will have run into this same problem with their own libraries, and have found some ways to address it. Generally speaking, the key is to reduce the number of template instantiations, but it's also a good idea to eliminate unused computations... avoid traits blob templates since all the nested definitions need to be evaluated if you want to use just one; use mpl::apply_if and logical operators and_/or_ to avoid needless evaluations. Here is what I have already figured out. First off, in FC++, there are a number of templates whose sole purpose is to provide better compiler diagnostics (along the same general lines as concept_checks). I rewrote the library code so that these checks are only enabled when a certain preprocessor flag is defined. Turning off these checks reduced the compile-time of parser.cpp from 10 minutes to 8 minutes--a significant speedup. That was the most obvious piece of low-hanging fruit; since the code to produce the compile-time diagnostics doesn't do anything at run-time, it was straightforward to just have a switch to turn it on and off. I imagine there are other things I can do to rewrite some of the library templates that are doing real work so that they compile faster. Specifically, I imagine that some templates can be rewritten so that they cause fewer auxiliary templates to be instantiated each time the main template gets instantiated. Good plan. On all but the most-recent EDG compilers the nestedness of symbol names generated may have a significant impact on compile times. However there are two issues that make this hard to do: (1) Knowing which templates to focus on. That is, which templates are effectively the inner loops in the compilation process, and thus deserve the most attention when it comes to optimizing them? Heh. Welcome to the black box of C++ metaprogramming. (2) Knowing how to rewrite templates to make them faster. I imagine that fewer templates instantiated will mean faster compile times, but I don't actually know this for sure. I have no window into what the compiler is actually doing, to know what takes so long. Maybe it's the template instantiation process; maybe it's all the inlining; maybe it's the code generation for lots of tiny functions. I don't know. Yep, it's a nasty problem. I suggest some experimentation. I have made some headway with (1): the unix utility nm lists all the symbols compiled into an executable program, and by parsing the output, I am able to determine which templates have been instantiated with the most number of different types. My little script yields output like ... 313 boost::fcpp::lambda_impl::exp::Value 314 boost::fcpp::lambda_impl::BracketCallable 606 boost::fcpp::lambda_impl::exp::CONS 609 boost::fcpp::full1 610 boost::intrusive_ptr 670 boost::fcpp::lambda_impl::exp::Call which tells me that the Call template class has been instantiated 670 different ways in parser.cpp. This at least gives me some idea of which classes to focus my optimizing attention on. However a drawback of using the nm approach is that it only shows templates with run-time storage. There are tons of template classes which contain nothing but typedefs, and I imagine they're being instantiated lots of ways too, and I don't know if this slows stuff down significantly too. It does; see the link at the top of my reply. Also, if you're using something called CONS you're probably also using hand-rolled metaprograms. MPL contains some interesting techniques designed to reduce the stress on compilers (e.g. compile-time recursion unrolling, lazy evaluation); you might try using the high-level interface of MPL to see if it improves things. As to (2), I know nothing, other than the speculation that fewer instantiations is better. So, that's where I am. Help! :) You're on the right track. -- Dave Abrahams Boost Consulting www.boost-consulting.com ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Re: Deprecation/removal of libraries
On Thu, 28 Aug 2003 16:19:24 +0200, Douglas Gregor wrote: On Thursday 28 August 2003 08:20 am, Daniel Frey wrote: utility/tie was moved to tuple, so should we remove the obsolete docs/references in utility now? Please do. Done. I also updated the Revisited ..., but there is some checksum in the HTML-source. I have no clue what it's good for, so if I broke it, please fix it and tell me how to avoid it next time :o) Regards, Daniel ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: variant questions
Alexander Nasonov wrote: Eric Friedman wrote: If I understand you correctly, earlier versions of variant did precisely what you describe. Unfortunately, the assumption you make is false in general. See http://aspn.activestate.com/ASPN/Mail/Message/boost/1311813. Eric Well, is_polymorphicT based on compiler properties beyond the standrad. Why not optimize variant for compilers which safely memcpy forth and back? I'm not sure how we would know... It seems to be a very bad idea to simply guess. Plus, for compilers where it is in fact not allowed, we still need a workable, defined solution. Eric ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: generic uses of optionalT
[Eric Friedman] Why not overload boost::get again for optional? It might be a good idea for other reasons, but it doesn't solve the problem I'm trying to solve. [Brian McNamara] do_something( adapt( 3 ) ); do_something( adapt( nilableint(3) ) ); do_something( adapt( foo ) ); // foo has unknown type But I'd like to write do_something(3); do_something(foo); // of type T do_something(bar); // of type nilableT Can I have my cake and eat it too? ;-) Dave ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: optional, tie, and iterator_adaptor
[Fernando Cacciola] The most fundamental point is that being Haskell a pure functional language there is no possibly undefined behaviour to worry about, so Maybe doesn't need to address this issue as optional does. ... and later ... I account the possibly undefined behavior of accesing an uninitialized optional as a real and important problem. You can get rid of the possibly undefined behaviour by defining it! Throw an exception when there's an attempted coercion from nil/undefined to a normal value. [Fernando Cacciola] First of all, let's not confuse syntax with semantics. optional HAS strict value semantics. If the choice of 'operators *', 'operator -' and 'get()' as value accessors makes the appearance that is has pointer semantics, then it is the documentation that has to be fixed, not the interface. .. and later ... The * syntax is not supposed to make optional pretend it is a pointer. It is clearly not and the documentation says so quite clearly, I think. And if it doesn't, then it is the documentation that needs to be fixed. No, the interface should be changed, because it _looks_ like it has pointer semantics. If the semantics of optional can be clear before reading the documentation then they should be. Face it, it's wishful thinking to assume that documentation will solve the problem. [Fernando Cacciola] vector::begin returns an object with operators * and -, yet these objects are not pointers, and once that is learned, people do not think they are pointers. But they are iterators, and random-access iterators exhibit pointer semantics. That's the reason iterators use operator* and operator- in the first place! Dave ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Re: Re: Optional, tie, and iterator_adaptor
Joel de Guzman [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] Fernando Cacciola [EMAIL PROTECTED] wrote: Even if I agree with you that an optionalT should not be a T, an optionalT is definitely not a pointer to T. Definitely! If HTML had blinking banners I think I'd use one to state this :-) Nor should it model a pointer. It tries not to model a pointer at least. The OptionalPointee concept was coined to stress this fact, by formalizing the syntatic meaning of operators * and - independently of pointers. What I'm defending here is the idea of giving operators * and - a meaning on their own: the possibly undefined value of its operands. That this choice of operators still makes the appearance that optional models a pointer I need to address on the documentation by a better formalization of the concept. That was my point and the point of others who dislike *opt. Yet iterators are not pointers either but they do use operators * and - Iterators are not pointers, but they model the pointer. Right. In fact, looking at it more closely, I *could* almost agree with you that an optionalT is not a T. There is in fact a getter function (get). In fact all three (tuple, optional and variant) have a get function. That's fine, yet, here again, the optional does not jive well because it returns access *by pointer* whereas both tuple and variant return access by reference. This get() issue we agree should be fixed. Agreed. If there's a way to get at the values through a generic get function that unifies the access of optional with variant such that I can think of optional as an optimized specialization of variantT, none, I would be very happy. With such an interface, I can simply ignore the pointer-like interface, if you wish to keep it ;-) All right, we're settled then! Thanks you very much! And BTW, kudos for such a well engineered library! Spirit has been using it since v1.7 and I am very happy with it. The comments I gave so far are merely my opinion. You are of course free to have your own preferences :-) Keep up the good work! Thank you! Fernando Cacciola ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost