[boost] Re: Re: Re: Re: Optional, tie, and iterator_adaptor
[Fernando Cacciola] > I'm saying that the choice made by variant<> in this regards is to the > code using get<> as hopeless as undefined behaviour. I don't think that > preconditions (and exceptions thereof) should be used to arbitrarily > make the illusion of giving meaning to an operation that is undefined at > the conceptual level. For myself, and I think also for Joel, "nil" is a fully legitimate value, not a hopeless, meaningless, conceptually undefined value. It's quite clear that you don't share this view. The conceptual divide here is surprisingly large. I'm surprised to find myself suggesting this, but perhaps instead of debating this issue further I and like-interested people should create and submit a high-quality implementation of nilable.hpp to Boost. If accepted, people could then choose whichever best meets their needs/expectations. 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: generic uses of optional
[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( nilable(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 nilable Can I have my cake and eat it too? ;-) Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: generic uses of optional
> [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 optional 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 nilable can take. This means that when we want to write generic code it is sufficient to support nilable: with an implicit conversion from T to nilable, 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 nilable 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 nilable 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] generic uses of optional
> Here's a (contrived) example of how the implicit conversion breaks > generic code: > [example snipped] > > The point is that optional is not a T, and most notably, a template > function will never perform the coercion. Replace the lines like >B b = get<2>(args); > in your example with real calls to, e.g. >do_something( get<2>(args) ) > and do_something() is likely to fail if it's a template function > (expecting a T and not an optional). Okay, you've demonstrated that it may not be possible to drop-in optional 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 #include #include template 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 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::vector v; v.push_back(1); v.push_back(2); output(v); try { nilable< std::vector > nv(v); //output(nv); // true, this fails output(std::vector(nv)); // but this succeeds! nilable< std::vector > nv2; output(std::vector(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
[boost] Re: Optional, tie, and iterator_adaptor
> template > class nilable { Was that small enough to be considered not copyrightable, warrantable, etc. ? If so, fine. Otherwise I guess I have to disclaim any warranty, etc. Boost Public Licence? Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Optional, tie, and iterator_adaptor
> Right now I am questioning whether the > pointer-like semantics is worth it to me. I would probably prefer that > clients type more to test whether a value is initialized so that they > can type less to call a function that takes an optional as a parameter > when they have a value to pass in. Sorry if this has already been > covered, but here my question is: Have you experimented with a variant > of optional that drops the pointer-like semantics, allowing implicit > construction and disallowing implicit safe-bool conversion, and if so > what did you learn that made you favor the current set of tradeoffs? I've never been comfortable with the pointer-like semantics of optional. If you don't need an industrial-strength solution like Fernando's, perhaps something simple like the below would be sufficient? (Also, feel free to suggest improvements.) Dave template class nilable { public: nilable(void) : nil_(true) {}; nilable(const T & value) : value_(value), nil_(false) {}; // rely on default destructor, copy constructor, and assignment operator bool nil(void) const { return nil_; }; operator T(void) const { if (nil_) boost::throw_exception(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 bool operator! (const nilable & a) { return (a.nil() || !a.unsafe_reference()); }; template bool operator< (const nilable & a, const nilable & b) { if (b.nil()) return false; if (a.nil()) return true; return (a.unsafe_reference() < b.unsafe_reference()); }; template std::ostream & operator<< (std::ostream & out, const nilable & value) { if (value.nil()) { out << "nil"; } else { out << value.unsafe_reference(); }; }; // TODO: add input from std::istreams. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Fw: boost::filesystem file restrictions
--> portable_path("/foo/bar") <- throws on Windows --> --> Not sure why this would throw, what is the purpose of --> portable_path? "/foo/bar" is perfectly reasonable on Windows. -> -> It's perfectly reasonable but it doesn't have a portable meaning. -> It -> is a relative path w.r.t. the drive of the current directory. > > Almost all paths are relative w.r.t. something, the current users > filesystem mapping, the computer, the network. ---> ---> I find that somewhat compelling... but in the end it doesn't hold up. ---> > I don't see how > leaving out the drive makes it less portable then leaving out the > computer name. ---> ---> It's less portable because how it is to be interpreted *with respect ---> to the filesystem* can change dynamically. Remember the name of this ---> library, "filesystem"? ;-> ---> ---> Filesystems belong to computers. A computer's filesystem is accessed ---> via an infinite tree of names (**). How those names which correspond ---> actual storage are mapped can be modified dynamically in any number of ---> ways: you can have symbolic and hard links, mount drives, remote ---> computers can come online or go away, non-storage devices can be ---> mounted at locations in the tree etc. The one constant is the ---> structure of the tree of names which allows us to access a virtual ---> location in the filesystem (as opposed to physical). ---> ---> A path is a set of instructions for traversing the name tree. By any ---> reasonable definition, an absolute path identifies a single virtual ---> location in a filesystem's name tree, not one that can change based on ---> the process state. A path on windows that starts with '/' is a set ---> of instructions which begins: "go to the root of the current ---> directory path". --> -->Correction. It does not mean that. It means go to the root directory of the -->current drive. It is still not an absolute path since the current drive -->changes. If one specified 'a:/', then that is an absolute path as defined -->under Windows. Even if 'a:' were a removable disk, and thus could be -->physically changed, it would be considered an absolute path. -> -> I see you don't perceive changing a removable medium with changing the -> "state" of the machine (interesting perception of state). > > That changes the physical file(s) associated with certain paths, just > like deleting and creating files or creating symlinks. It does not > change where those paths refer to in the filesystem. I think lack of agreement of a common vocabulary may be hampering the discussion of boost::filesystem, and that this might stem from different conceptual notions of what we are speaking of. For example, while it is possible to think of all drives on an MS Windows machine as being part of a single filesystem, an individual using NTFS on C:, FAT32 on D:, FAT16 on E:, and FAT12 on A: reasonably would not. It is unquestionable that NTFS and FAT are different filesystems. Now, one can choose to use NTFS for both C: and D:, but that does not make C: and D: together a single filesystem. On UNIX and UNIX-like systems, it is quite natural to have multiple drives with possibly different filesystems and to think of their conglomeration to be a single filesystem, but this is just a UNIXism. It is neither natural for members of other communities (MS Windows, VMS, etc.) to view file access in this manner, nor desirable to force them to do so. Other comments (e.g. re: "basename") also served to remind me that this entire discussion would best have taken place during the Boost review for the filesystem library. (Indeed, it would surprise me if "basename" was not both brought up and criticized during the review, notwithstanding POSIX's endorsement, but the issue doesn't interest me enough to go and search for it. FWIW, I'm happy with root/branch/leaf.) Mainly I think that if boost::filesystem was deeply flawed, it would not have been accepted to Boost. It is not as if some startling new, unforeseen issues have arisen that Beman and others had never considered before. Current usage is clear and not particularly problematic, so I feel it ought to be left well enough alone. As a tangential comment, I agree that boost::filesystem should be favoured over boost::fs in sample code in the documentation. I would also suggest that said documentation should contain the #include lines to include the library within the documentation's sample code, at least for the very first example. Fortunatley, it would appear that at the very least some important improvements to the documentation have been made (or will be made) as a result of the discussion. Apologies in advance if the quote at the top is too long -- I thought it was best left in here. On first send, the email was apparently automatically rejected for this reason, so I altered the quoting characters. Dave ___ Unsubscribe & othe
[boost] boost::array
> The problem is that boost::array is not a wrapper around an > existing array, it IS an array. This implys making a superfluous > copy of the array in some cases. > > Given an simple C array, I want a wrapper which will supply an > iterator interface so that I can do something like. > > const in array{] = {1, 2, 3, 4}; > boost::array ba(array); > std::copy(ba.begin(), ba.end(), std_ostream_iterator(std::cout)); > > Is there already a way to do this? Or is there some reason why > one would never want to do this? AFAICR boost::array allows initialization. I would try const boost::array ba = {1, 2, 3, 4}; std::copy(ba.begin(), ba.end(), std_ostream_iterator(std::cout)); Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: boost::array
dave> > const in array{] = {1, 2, 3, 4}; dave> > boost::array ba(array); dave> > std::copy(ba.begin(), ba.end(), std_ostream_iterator(std::cout)); dave> > dave> > Is there already a way to do this? Or is there some reason why dave> > one would never want to do this? dave> dave> AFAICR boost::array allows initialization. I would try dave> dave> const boost::array ba = {1, 2, 3, 4}; dave> std::copy(ba.begin(), ba.end(), std_ostream_iterator(std::cout)); > > But he doesn't want coping. There's the simple solution > > const int array[] = {1, 2, 3, 4}; > std::copy(array, array + 4, ...); > > and also there's the array_traits in the sandbox. > > However, did he want the exact interface as boost::array? If so, I'd say > we need a new class called ptr_array that adapts a pointer and a size > into an array. Is this a copy, or an initialization? > const in array{] = {1, 2, 3, 4}; Is this a copy, or an initialization? > const boost::array ba = {1, 2, 3, 4}; Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] RE: Re: Filesystem: create_directories
> > > > create_directory > > > > and > > > > create_directories > > > > > > Another option might be: "create_directory_and_parents" > > > That name is longer than "create_directories" although it better > > > describes the function. > > > > I like "create_directory_path" > > That one's good, and captures the essential distinction well. Other > possibles: "create_full_directory," or "create_rooted_directory." > Dunno. On whole, I might prefer your choice. Although it again > lengthens the name, "create_directory_and_path" captures another minor > piece of the distinction. You could also play with the distinction (none > save semantic in most file systems) between "pathname" and "filename;" a > filename is usually just the thing at the leaf-terminal end of the path > (and needn't be a "file," save as a directory is often actually > implemented as such), while the pathname is the full Monty. > > In the original scheme, I would think the problem with > "create_directories" is that it would seem to imply (to me, at any rate) > the creation of multiple directories at the same depth in the file > system. Anyway, them's my kibitz's. Ah, naming again. My favourite. :-) I like create_path_and_directory. I prefer this order of the two terms because logically the path exists before the directory itself does. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Re: Re: Formal Review Request: circular_buffer [long]
> > > > 3. cb_iterator: is the m_end value needed? > > > > > > > >It can be computed using 'm_it == m_buff->m_last' in > > > >those few (~2) places it is needed and if eliminated, > > > >iterator will get smaller (by 30%) and simpler. > > > > > > Yes, the m_end member is needed. Suppose the circular_buffer is full. > > > Then m_buff->m_first == m_buff->m_last. If there is no m_end variable > > > how would you recognize that the iterator points to the beginning or > > > end? > > > > 30% is a lot. Would it make sense to always allocate one extra element, > > so that this equality can never occur? > > 1) This is is not true. The members of the iterator are: > const Buff* m_buff; > pointer m_it; > bool m_end; > > At Windows based systems sizeof(m_buff) == 4, sizeof(m_it) == 4 and sizeof(m_end) > == 1. It is not 30%. 30% was the number given by another poster. I merely referenced their number. On most 32-bit platforms, including Windows on x86, sizeof(structure with those 3 fields only) is 12, not 9. 30% is actually somewhat generous, because it slightly underestimates the relative space allocated due to the presence of the bool. > 2) Suppose you are storing elements of size 1000 bytes. By allocating one more > extra element ... To me, this seems significantly less likely than storing elements of size 1, 2, 4, or 8 (values of small concrete types, or pointers to larger types). Even if you are storing value types of 1000 bytes directly, if you're allowing space for 1000 of those then the extra kilobyte is still not a big deal. I would expect the combination of large-sized type and low permitted count to be infrequent, and implement accordingly. However, should that expectation be incorrect, there is likely a way to represent an empty circular buffer differently by using the value 0 in a judicious manner somewhere in your code, so that when the equailty is being tested and holds it is always intpretable as that the buffer is full. By such a mechanism the bool would still be avoidable, for the cost of a slight increase in code complexity. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] boost::signal patch
At the top of signal.hpp: namespace boost { #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION namespace BOOST_SIGNALS_NAMESPACE { namespace detail { template struct real_get_signal_impl; MSVC 7.1 complains: warning C4099: 'boost::signals::detail::real_get_signal_impl<0,T1,T2,T3,T4,T5>' : type name first seen using 'struct' now seen using 'class' at several later points in the same file. These can all be removed by changing struct to class in the declaration quoted above. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] minor nitpick: why signal.hpp instead of signals.hpp? (notext)
___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] regex possible bug
Thanks for the quick fixes on the other bug reports, John. Here is what might be a new one. The code below indicates that no match was found, but I was expecting it to indicate that a partial match was found beginning at 'a'. If I don't push the space on beforehand, I do get a partial match. Have I overlooked something? #include #include #include int main(void) { typedef char value_type; typedef std::vector container_type; typedef container_type::iterator iterator_type; boost::regex find_this("ab"); container_type search_this; search_this.push_back(' '); search_this.push_back('a'); boost::match_results< iterator_type > what_matched; bool match_found(boost::regex_search(search_this.begin(), search_this.end(), what_matched, find_this, boost::match_default | boost::match_partial)); if (match_found) { if (what_matched[0].matched) { std::cout << "Full match found." << std::endl; } else { std::cout << "Partial match found." << std::endl; }; } else { std::cout << "No match found." << std::endl; }; }; ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] regex documentation bug
http://www.boost.org/libs/regex/template_class_ref.htm#partial_matches There are two examples given. Though the examples are different, in both cases, the "example" links to a complete implementation of the first example. This likely was a cut-and-paste error. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] boost::regex opeartor+= bug report
The file "boost/regex/v4/perl_matcher_non_recursive.hpp" includes statements such as end += std::min((unsigned)re_detail::distance(position, last), desired); operator+= is appropriate for random-access iterators, but not for merely bidirectional iterators such as std::list::iterator, which is what I was using when I came across the problem. [I don't have a copy of the C++ standard, but I did check sections 2.3.4, 2.3.5, and 3.1.4 (which is of especial relevance) of Generic Programming and the STL by Matt Austern.] I received compilation errors using both g++ 3.3 and intel c++ for linux 7.1, but oddly enough, MSVC 7.1 compiles the code without complaint. (Non-compliance issue, or superior QoI?) I believe that consistent use of std::advance would solve the problem. Or would this change be so costly that I ought to use vector or deque? Unfortunately, doing so would cause me other problems such as iterator invalidation. :-/ Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Review Request: cyclic_buffer
-- Date: Thu, 12 Jun 2003 02:36:10 +1000 From: Nigel Stewart <[EMAIL PROTECTED]> To: [EMAIL PROTECTED] Subject: [boost] Re: Review Request: cyclic_buffer Message-ID: <[EMAIL PROTECTED]> In-Reply-To: <[EMAIL PROTECTED]> References: <[EMAIL PROTECTED]> <[EMAIL PROTECTED]> <[EMAIL PROTECTED]> <[EMAIL PROTECTED]> <[EMAIL PROTECTED]> <[EMAIL PROTECTED]> <[EMAIL PROTECTED]> <[EMAIL PROTECTED]> <[EMAIL PROTECTED]> Content-Type: text/plain; charset=us-ascii; format=flowed MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Precedence: list Message: 15 > This strikes me as a good compromise. For one thing, it leaves the > door open to inserting in a manner that resizes the capacity. (Except > for the problem that if the buffer is full, every insert will require O(n) > time) I later realised an important point: insert will be O(n) anyway, given the need to make room for the inserted items. So, it seems that allowing automatic resizing in this case does not cost anything in terms of performence implications. Every insert will *not* require O(n) time, unless the implementation is, to quote another poster, "brain-damaged". Is there a compelling use case for a circular buffer that resizes? Why is a deque inadequate? IME circular buffers are constant-sized. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] full cyclic_buffer
> Instead of dropping elements when the buffer is full, we might also > consider waiting or throwing a failure. I consider "dropping elements" to be surprising behaviour. If there's no policy stuff, then either decide that it will throw, or leave what happens to be implementation-defined. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: spirit 1.6 parsing question
> Spirit-devel mailing list > [EMAIL PROTECTED] Thanks, Joel. I've investigated further, learned something, and posted a modified message there. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] spirit 1.6 parsing question
When I define rules x, y, and z such that x = ch_p('a'); y = ch_p('a'); z = !x >> y; it appears to operate the same as if z were defined to be z = (ch_p('a') | epsilon_p) >> 'a'; which accepts "aa", but rejects "a". On the other hand, if I define z as z = (epsilon_p | ch_p('a')) >> 'a' then "a" is accepted, but "aa" is rejected. (These are, of course, not the actual rules I am interested in, but a vast simplification of them, focusing on the point of interest.) My original expectation had been that first the choice on the left side of the or operation would be attempted, but when ultimately failing to match the entire string later on, to then backtrack and attempt matching via the choice on the right side of the or. How can I achieve this behaviour? In the real problem the semantic actions associated with x and y are different, but the inputs they match individually have significant overlap, and where they do overlap, I need y to be matched rather than x. On a related note, when I defined BOOST_SPIRIT_DEBUG before #including the core, and specified BOOST_SPIRIT_DEBUG_RULE(test); in my grammar I received the following error message using g++-3.2.2 on linux-i686: test_grammar.hpp:45: ISO C++ forbits declaration of `get_node_registry' with no type test_grammar.hpp:45: invalid use of `::' test_grammar.hpp:45: syntax error before `.' token Any idea what I might be doing wrong? Also, please let me know if I should be asking this on a spriit-specific list rather than boost's. Thanks, Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: boost::optional feature request.
> It would be nice if boost::optional had operator< defined whenever > operator< was defined for T. This would allow us to use optional > as the key of an associative container. I suggest the following > semantics: > > bool operator<(optional const &x, optional const &y); > > Returns: If y is uninitialized, false. If y is initialized and x is > uninitialized, true. If x and y are both initialized, (*x < *y). > > This results in a strict weak ordering with uninitialized optional > objects being sorted first. Yes, I previously implemented this functionality -- exactly in the manner you described -- in my nilable implementaton. It's quite useful to have. (If anyone is curious, nilable was inspired by optional, though the implementation is not derived from optional's. The main differences are that nilable doesn't use pointer deferencing for access to the internal value. Instead, it provides a direct, checked conversion to T (using boost::throw_exception with a bad cast error when the object obj is nil), obj.nil() returning bool, and obj.unsafe_reference() and obj.unsafe_value() for when one has previously ensured obj.nil() is false and want to make further accesses without that being tested repeatedly.) Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: bad_lexical_cast
> Even a simple overloading of two functions (if we don't want to > disturb reference binding) seems to put it in serious trouble: > > > void f(int) { something... } > void f(short) { something else... } > > int main() { > int i = 0; > f(i); > } int and short do not have an is_base_and_derived relationship. This thread is getting off-topic, so I'll stop here. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: bad_lexical_cast
> > Since you advocate elsewhere that exception classes be derived > > from std::exception, the answer is because otherwise LSP would > > be violated. > > You can't access the derived class' assignment operator through a > pointer/reference to a polymorphic base, so that point is moot. Well, you're the expert on this. (I thought you could catch a reference to an exception, dynamic_cast it downwards, then use the assignment operator. Sure, this would be a stupid thing to do, but if possible I certainly can imagine some few misguided souls who haven't yet grokked C++ exception handling doing so.) > LSP is weird anyway. What's the point of polymorphism if you're not > going to change the behavior of the class in some observable way? If > the derived class were transparently substitutable for the base class > it wouldn't be much good, would it? I disagree here; "transparently substitutable" != "observable behaviour is identical". Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] bad_lexical_cast
>>>Yes. Since type_info objects can't be copied, one might instead store >>>pointers or references to them. >> >> Pointers would be better because, for better or for worse (mostly for >> worse), standard exceptions support assignment as part of their >> interface. > >Why should boost exception classes behave like std:: exception >classes in this regard? Since you advocate elsewhere that exception classes be derived from std::exception, the answer is because otherwise LSP would be violated. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] spirit documentation bug
Section "Portability" > 8. Intel 7.0VisualAge C++ 5.02 should be split into two lines. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] spirit documentation bug
Page "Subrules": > ... yields a complex type. Thus, while it is easy to write: > > int r = i | j >> k; // where i, j, and k are ints > > Forget rules for a second. Expression templates... The sentence seems to be cut off in the middle. I'm not sure what the repair should be. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] spirit documentation mini-bug
The navigation arrows at the bottom of each page do not have textual aliases for non-graphical browsers (e.g. lynx, or browsers on some WAP devices). Other graphics sometimes also do not have textual aliases. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] tracing / logging library
Just curious if anyone's doing something along these lines. A quick google search on boost turned up only Boost.Test, which (I think?) is something quite different. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] lexical_cast and boost-1.30
> Here is the current list: > > It looks to me like we should hold the lexical_cast changes until the > next release. There are really two issues IIUC - some wide-character > support problems and VC++ 6.0 support. While the wide-character problems > might be possible to resolve quickly, VC++ 6.0 support is going to take > some time to work out. Thus I think we should revert the RC_1_30_0 > branch and move on. > I am biased anyway, but I would vote for reverting the lexical_cast > changes in RC_1_30_0. I would vote to fix lexical_cast before release. I've already been waiting months for 1.30 to have the space problem fixed, I really don't want to wait months more. I know that I'm not the only one with this problem also. Frankly, wchar_t support in lexical_cast isn't as important as fixing the space problem, I'd rather the fix go in even if it regresses in this area -- unless someone pipes up to say they are actually USING wchar_t and lexical_cast on a compiler that won't grok the new code. And if there is such a person, then I'd appreciate the ugly hack of including both versions with #ifdefs. [In general, I do agree with the fellow who recommended bug-fixes-only after the branch. I consider the lexical_cast space problem a serious bug, that's all. ;-] Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] lexical_cast(Was: FYI)
> > Hi, > > > > Yes, the whitespace problem is fixed in the forthcoming version. > > What's "forthcoming version"? Is this forthcoming Boost release? > Then I don't see any changes to lexical_cast.hpp at all. Or > lexical_cast update will be committed later? Yeah, I was aware that work had been done on it, but as of a couple of days ago CVS had no change to lexical_cast.hpp, which is what prompted me to write my original query. Could whoever did the update please commit it to CVS? Thanks, Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] will lexical_cast improvements be in 1.30.0?
http://lists.boost.org/MailArchives/boost/msg36221.php references an improved lexical_cast. Will it or a similar improvement will be included in the 1.30 release? Specifically, I'm looking for point 2: casting between C-style strings and std::strings that accepts spaces within the text instead of emitting the bad lexical cast error. Dave -- Dave Gomboc M.Sc. Student1-41 Athabasca Hall Department of Computing Science Edmonton, Alberta, University of AlbertaCanada T6G 2E5 ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: resource manager naming
> > *laugh* I was thinking exactly the opposite. To me, the resource > > itself > > is clear from the template parameter -- it's the management that > > needs to > > be indicated. > > > > +1 for managed<>. > > What template parameter? That's not a part of the name. > Template parameters, just like function arguments are never > a part of the name. You do not need to read the header file > to get the essence. The name itself should indicate the function > of the class without looking elsewhere. It does! In this case, the function of the template class is to *manage*, not to "resource". > managed<>? What is managed? ... answer: take a look at > the template parameter and you'll see what I mean. I'm > sorry, that doesn't make sense. I don't understand what doesn't make sense about it. managed indicates that T is managed, for whatever T might happen to be. (If you prefer a noun, manager suffices.) This is analogous to optional or list. You always have to look at the template parameter to see the type that is being managed, is considered optional, or that is being held in the list for any particular instantiation. By contrast, resource doesn't tell me anything -- T is always a resource, or it wouldn't exist in my program. Anyway, if (inexplicably to me) this turns out to be a large bone of contention, it's probably best to drop back to managed_resource (or resource_manager), which while wordier will be sufficiently obvious to all concerned. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: resource manager naming
> > So then reverse resource_manager and get managed_resource<>, or just > > managed<>. > > Why not just resource<>? Management is implied anyway; that's the > reason for the existence of the class. *laugh* I was thinking exactly the opposite. To me, the resource itself is clear from the template parameter -- it's the management that needs to be indicated. +1 for managed<>. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] resource manager naming
> I would be searching namely for smart_ptr. I know that smart pointer is > the name for the resource management idiom. But those that don't would look for "resource_manager" or "resource_mgr" (and might even find "res_mgr"). The smart_ prefix is quite useless in this context, there isn't an old resource manager that is being replaced. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: is_class
> > No, I would prefer > > > > #if BOOST_WORKAROUND(__HP_aCC, <=33900) || > > BOOST_WORKAROUND(__VisualAge, <=12345) > > template struct enable_if; > > #else > > template struct enable_if; > > #endif > > > > I already explained the reason: C++ compiler vendors use Boost with > > BOOST_NO_CONFIG for conformance testing. I'd rather see broken > > compilers get fixed than developers forever spending time finding > > workarounds. > > OK, agreed. Given that we use another approach for static constants, > what do you think about: > > template< BOOST_UNUSED_TEMPLATE_PARAMETER( bool, cond ), > BOOST_UNUSED_TEMPLATE_PARAMETER( typename, T ) > > struct enable_if; > > Or should we instead replace BOOST_STATIC_CONSTANT by a #ifdef, too? Or > is BOOST_STATIC_CONSTANT different, probably because there is no "right" > code and a workaround, but there are two equally good ways to declare > static constants? Yes, I think a distinction can be drawn between the declaration of integer constants and the present issue. As I was recently reminded in another thread, Boost uses BOOST_NO_... for all defects, so the name you propose is perhaps not the most suitable. The construct itself seems satisfactory, I don't have a firm preference between the two forms. Anyway, let's not get stuck in the bicycle shed. ;-) Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: is_class
> So you would prefer > > #if BOOST_WORKAROUND(__HP_aCC, <= 33900) > template struct enable_if; > #elif BOOST_WORKAROUND(__VisualAge, <= 12345) // Dummy values > template struct enable_if; > #else > template struct enable_if; > #endif > > over > > template struct enable_if; > > If that is the case, then we disagree. Do you have any reason to prefer > the first version? No, I would prefer #if BOOST_WORKAROUND(__HP_aCC, <=33900) || BOOST_WORKAROUND(__VisualAge, <=12345) template struct enable_if; #else template struct enable_if; #endif I already explained the reason: C++ compiler vendors use Boost with BOOST_NO_CONFIG for conformance testing. I'd rather see broken compilers get fixed than developers forever spending time finding workarounds. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: is_class
> See also the discussion about a "general coding guideline" to "always > provide a name for template parameters". Here, the maintainer already > did the right thing when he received the patch. If the maintainer hid the compiler brokenness completely, then they did the wrong thing. If they didn't, they used an #ifdef (via BOOST_WORKAROUND). Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Patch for function/function_base.hpp
> Ah, that's the reason. But given my recent discomfort about > unmaintainable code, look at it again: > > # if BOOST_WORKAROUND(__HP_aCC, <= 33900) > template struct enable_if; > # else > template struct enable_if; > # endif > > Does this really makes sense? Shouldn't we just keep one version with > names for template parameters? AFAICS this should work for all compilers > and it could be a general boost coding guideline to always provide names > for template parameters. Comments? Nah, the vendors will never fix problems that we hide. In some regular code I might just switch it, but since some vendors _are_ using Boost to test their compiler conformance, we should leave the HP workaround in (and use the same or a new workaround for VisualAge also). That way, when they compile with BOOST_NO_CONFIG they will see the problem. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Fix for some Interval library tests
> > > I suggest adding another boost defect: BOOST_BROKEN_ADL (or similar) > > > > How about BOOST_LIBRARY_IMPL_VULNERABLE_TO_ADL? It's not that the > > compiler's ADL implementation is broken, it's that the library > > implementation isn't protected against ADL lookups where it needs > > to be. > > > > Dave > > Sorry, but what is adl? (I tried google on this one, but since > there is a c++ variant called adl, there was a lot of noise). > I hope I don't misunderstand your sentence: it seems it's not > the compiler which is broken but the library. So could you > explain a bit more? We have tried to make the library compliant > and I don't want to leave such a fault in it. ADL is "argument dependent lookup", a.k.a. "Koenig lookup". My original explanation was ambiguous: it's not your library that is at fault, it is the implementation of the standard library that the compiler is using that is defective. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Fix for some Interval library tests
> I suggest adding another boost defect: BOOST_BROKEN_ADL (or similar) How about BOOST_LIBRARY_IMPL_VULNERABLE_TO_ADL? It's not that the compiler's ADL implementation is broken, it's that the library implementation isn't protected against ADL lookups where it needs to be. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: (corrected) review of optional library
I missed Alberto's post, so I'll reply to this one. -- Date: Sat, 14 Dec 2002 22:46:27 -0300 From: "Fernando Cacciola" <[EMAIL PROTECTED]> [snip] > "Alberto Barbati" <[EMAIL PROTECTED]> escribió en el mensaje > atf8kh$gvr$[EMAIL PROTECTED]">news:atf8kh$gvr$[EMAIL PROTECTED]... [some examples snipped] > > Those are interesting examples! Thanks. [snip] > If I can say it, I don't think that they are really good examples. Sorry, those were from my originally private email to Fernando, I forgot to review that message more carefully for defects before posting it here. > > The proposed signature of set::insert is a downgrade and not an > > improvement. Even if the element is not inserted, I still may want to > > have the iterator. In order to perform its operation, insert() will > > have to compute such iterator, so what's the point in discarding it? > > > You're right here. > The iterator is always valid so it is useful on itself. Hmm, so it is. For some reason I use find, then if the find fails, use insert with the find as a hint, so I never noticed! The examples were unrelated to my main point, which I've discussed at length elsewhere already. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: (corrected) review of optional library
> > Conversion from T' to T is straightforward except when the value of > > type T' is nil. In this case, the developer may want to throw, > > default-construct the value of T, or assert. Template policy choice? > > (Perhaps that's overkill.) > > > As Peter said, default-construct T undermines the whole purpose of > optional. The best is, IMO, to leave it undefined in that case. Myself, I'd prefer int x(5); optional y; ... x = y; to throw when the assignment happens. However, sometimes people don't want that (e.g. those compiling with BOOST_NO_EXCEPTIONS). In a debug compile, an assert is possible, but what to do in a release compile? I suppose aborting is possible, but highly unfriendly. Instead, either your suggestion of leaving the value alone (which means it would be uninitialized if it hadn't been previously set) or setting it to the default value make sense to me. I thought that the latter would give more consistent behaviour so that it would be easier to debug, but I'm not wedded to the idea. I do agree that these other options are undesirable to the extent that they work against the purpose of optional<>. That aside, the big issue remains whether people consider the "nil" value to be truly exceptional, versus it being just another possible value. I think that your view is the former, and that this is reflected in your interface design. It really does highlight attention on the fact that there's this "extra" possibility, and that one shouldn't forget to deal with it. It's screaming, "Hey! Don't forget about the nil value!", and I can understand why you view this as very positive. It's just as visible from my comments that my view is the latter. If you treat nil as just another acceptable value, instead of the absence of one, then the algebra works completely, and also quite usefully (e.g. consider relational algebra). So why wouldn't I want to do just that? "nil" doesn't have to mean 'invalid', or 'uninitialized', or 'danger, danger' ;-) in any particular circumstance -- of course it _can_ mean those things, depending on what you're using it for. But it might simply mean there was nothing to return, nothing to pass, nothing to inspect, nothing to whatever. The asymmetry between the "nil" value and the other values in the proposed interface really bothers me _because_ to me "nil" is just "nil", and it's only of specific interest in the same manner that zero might be of specific interest in some other circumstance. Sometimes you want to test for zero, so it's handy to have a shortcut for it, but much of the time it's just an integer. I would guess (handwaving alert ;-) that the traditional mechanism for indicating an "optional" value uses a pointer because that was more convenient than passing a separate flag alongside the value. Let's not forget that this practice predates data structures, never mind object-orientation -- a pointer is a legacy interface for this job. Now that the extra bool can be wrapped and hidden away, there's no longer a need for pointer-like treatment. And I'd argue (granted, perhaps unsuccessfully ) that the interface is counter-productive, because people won't ever really become comfortable working with "nil-ness" as long as the interface promotes it as being a special case. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] (corrected) review of optional library
Adjusted at five points; please ignore the previous one. -- Forwarded message -- At this point in time, I vote to reject the library. My vote is based upon a review of the interface and implementation in optional.hpp of the zip file I downloaded from the link posted by Fernando on Dec. 12, and following the discussion via the mailing list digests. I will qualify my vote by indicating that this is my first review for boost. The interface is undergoing a considerable amount of flux during the review period, and I think that significantly more change is still required before I would vote for its inclusion. The operators that (unsuccessfully) attempt to provide pointer semantics are misleading, and should be removed. To me, appeals to optional being a container (or giving it pointer semantics, as if it were an iterator!) are misguided. In my opinion, optional [which perhaps ought to be may_be or maybe, as an earlier poster suggested, also see below] works best as denoting a type T', whose assignable values are the legal values for type T unioned with the value "nil", or "nothing" (as in Haskell). (It shouldn't be called "uninitialized", because that would be misleading. "nil" is a perfectly valid value for a variable of type T' to take.) Because "nil" is just another value, operator== can be defined straightforwardly. If both are "nil", return true; if exactly one is, return false; otherwise the normal comparison value is returned. operator< could be left undefined, but it is simple enough to arbitrarily choose that "nil" is strictly less than every other value. I don't see a downside to this, and it would ensure that T' is a strict weak ordering whenever T is, which is useful for STL usage. The operators !=, >, <=, and >= directly follow from definitions of the above two operators. Conversion from T' to T is straightforward except when the value of type T' is nil. In this case, the developer may want to throw, default-construct the value of T, or assert. Template policy choice? (Perhaps that's overkill.) One could possibly provide a test for the nil state by declaring an enum (in some scope) that defined some (arbitrary) value to "nil", then providing an operator== that allowed comparisons on that enum type, to allow code such as: using boost::may_be; ... may_be blah(void) { may_be x(5); // x is constructed to value 5 may_be y;// y is default-constructed to value nil ... if (y != nil) { ... }; ... x = nil; ... return std::max(x, y); // defined since std::less uses operator< }; It is possible, but not necessarily desirable, to include "is_nil()" or "is_not_nil()" functions. operator!() already exists in Fernando's code as the equivalent to "is_nil()"; a double invocation (e.g. "!!x") would be equivalent to "is_not_nil(x)". I suspect it is probably not worth fattening the interface for them, but this may be a matter of taste. (Also, below is a message I had sent to Fernando already, but I suppose it might as well be sent to boost also.) Dave -- Forwarded message -- "Maybe" is a built-in type constructor in Haskell, which AFAIK is the most widely used functional programming ("FP") language. It is used to denote exactly what your suggested optional is. (Which is why I am recommending use of "maybe" or "may_be" instead of optional.) An example in Haskell syntax: safe_division :: Float -> Float -> Maybe Float safe_division x y = if y == 0 then Nothing else Just (x/y) Consider this Haskell declaration: get_maximum_value :: BTree Int -> Maybe Int The equivalent (free function) declaration in C++ would be: may_be get_maximum_value(const BTree &); Yet another function prototype: get_cached_value :: a -> [(a, b)] -> Maybe b which can return Nothing if the function does not have "a" as the first item of any of the pairs in the list. Maybe is defined in Haskell as data Maybe a = Nothing | Just a deriving (Eq, Ord, Read, Show) (here "a" is an arbitrary type; "Nothing" is like "nil", "NULL", "uninitialized", or whatever you want to call it.) As an example, currently the C++ standard includes T & stack::top(), with precondition !(stack.empty()). Instead, it could be may_be & stack::top(); // no precondition required could be improved also, instead of: pair set::insert(const value_type & x) we would use may_be set::insert(const value_type & x) where the return value is initialized to the place of insertion if x was inserted, or is uninitialized if x was not inserted. Of course, it is possible to use variables of type may_be: int blah(int x) { may_be y; // default-constructed to uninitialized, right? . . . // expressions involving y here are okay instead of invalid. . . . }; (The use as an optional function parameter is no doubt what you had in mind in the first
[boost] review of optional library
At this point in time, I vote to reject the library. My vote is based upon a review of the interface and implementation in optional.hpp of the zip file I downloaded from the link posted by Fernando on Dec. 12, and following the discussion via the mailing list digests. I will qualify my vote by indicating that this is my first review for boost. The interface is undergoing a considerable amount of flux during the review period, and I think that significantly more change is still required before I would vote for its inclusion. The operators that (unsuccessfully) attempt to provide pointer semantics are misleading, and should be removed. To me, appeals to optional being a container (or giving it pointer semantics, as if it were an iterator!) are misguided. In my opinion, optional [which perhaps ought to be may_be or maybe, as an earlier poster suggested, also see below] works best as denoting a type T', whose assignable values are the legal values for type T unioned with the value "nil", or "nothing" (as in Haskell). (It shouldn't be called "uninitialized", because that would be misleading. "nil" is a perfectly valid value for a variable of type T' to take.) Because "nil" is just another value, operator== can be defined straightforwardly. If both are "nil", return true; if exactly one is, return false; otherwise the normal comparison value is returned. operator< could be left undefined, but it is simple enough to arbitrarily choose that "nil" is strictly less than every other value. I don't see a downside to this, and it would ensure that T' is a strict weak ordering whenever T is, which is useful for STL usage. The operators !=, >, <=, and >= directly follow from definitions of the above two operators. Conversion from T' to T is straightforward except when the value of type T' is uninitialized. In this case, you may want to throw, default-construct the value of T, or assert, depending on what behaviour a developer wants. Template policy choice? (Perhaps that's overkill.) One could possibly provide a test for the uninitialized state by declaring an enum (in some scope) that defined some (arbitrary) value to "nil", then providing an operator== that allowed comparisons on that enum type, to allow code such as: using boost::may_be; ... may_be blah(void) { may_be x(5); // x is constructed to value 5 may_be y;// y is default-constructed to value nil ... if (y != nil) { ... }; ... x = nil; ... return std::max(x, y); // defined since std::less uses operator< }; It may (or may not) be desirable to have "is_nil()", or "is_not_nil()". operator!() already exists in Fernando's code as the equivalent to "is_nil()", so a double invocation (e.g. "!!x") would be eqivalent to "is_not_nil(x)". So these are not really necessary, and it is unclear to me whether it is worth fattening the interface for them. (Also, below is a message I had sent to Fernando already, but I suppose it might as well be sent to boost also.) Dave -- Forwarded message -- "Maybe" is a built-in type constructor in Haskell, which AFAIK is the most widely used functional programming ("FP") language. It is used to denote exactly what your suggested optional is. (Which is why I am recommending use of "maybe" or "may_be" instead of optional.) An example in Haskell syntax: safe_division :: Float -> Float -> Maybe Float safe_division x y = if y == 0 then Nothing else Just (x/y) Consider this Haskell declaration: get_maximum_value :: BTree Int -> Maybe Int The equivalent (free function) declaration in C++ would be: may_be get_maximum_value(const BTree &); Yet another function prototype: get_cached_value :: a -> [(a, b)] -> Maybe b which can return Nothing if the function does not have "a" as the first item of any of the pairs in the list. Maybe is defined in Haskell as data Maybe a = Nothing | Just a deriving (Eq, Ord, Read, Show) (here "a" is an arbitrary type; "Nothing" is like "nil", "NULL", "uninitialized", or whatever you want to call it.) As an example, currently the C++ standard includes T & stack::top(), with precondition !(stack.empty()). Instead, it could be may_be & stack::top(); // no precondition required could be improved also, instead of: pair set::insert(const value_type & x) we would use may_be set::insert(const value_type & x) where the return value is initialized to the place of insertion if x was inserted, or is uninitialized if x was not inserted. Of course, it is possible to use variables of type may_be: int blah(int x) { may_be y; // default-constructed to uninitialized, right? . . . // expressions involving y here are okay instead of invalid. . . . }; (The use as an optional function parameter is no doubt what you had in mind in the first place, and where you got the "optional" name from.)
[boost] Re: Possible Submissions
> If people are interested I would like to present several possible > additions to the Boost library. I will be willing to answer questions > about my code but won't be willing to modify my code to boost standards as > I simply don't have the time. In that case, maybe the best thing to do is contribute them to the boost sandbox. Others could then pick up whichever balls they are interested in and run with them. I'm not sure exactly how to go about having something added to the sandbox, but I'm sure someone else can chip in with that. :-) Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost