Re: [boost] Re: Re: Re: GUI/GDI template library
From: Rob Lori [EMAIL PROTECTED] E. Gladyshev wrote: --- Edward Diener [EMAIL PROTECTED] wrote: As you have pointed out in the rest of your post, it may prove more worthwhile to work with the developers which already exist for a free cross-platform framework like wxWindows, in order to encourage them to use more modern C++ idioms I agree with this suggestion. I am wondering how realistic would it be? As I quoted from their roadmap, there are plans to do this - at least changing the components used to standard components, such as changing wxString to std::sstring. After all, the library originated long before there was a standard, and a standard string. Personally I'm not certain I like that idea. WxWindows is much more than just multi-platform GUI. This means when you only need the GUI you'll be linking to everything else in their library, which increases your code size. I'm aware of that. However, with boostification/transforming it to use modern C++ idioms, one might also change it to use existing standard components for these, or Boost components. One might also omit parts not strictly belonging to a GUI library, such as database access. Or one could include it, if no Boost library supports that at the time. Make no mistake - this is a lot of work, too. However, it may be much less work than creating one from scratch. What do we want - vaporware of a Boost GUI library coming real soon now, perhaps not appearing for many years, if ever, due to the amount of work, or adapting an existing solution and being able to use it here and now, with a boostified version to come? Anyway, it was just a thought. wxWindows is already tested and debugged - and has been used in real-world projects. It's shown its worth. By the way, dynamic layout have been mentioned (like layout managers in Java), and wxWindows support these, as well. As Alec Ross pointed out, there's also an XML-based portable resource format (XRC) (http://www.wxwindows.org/manuals/2.4.0/wx478.htm), and a resource editor for it. Besides, I believe it would take more effort to change all the existing WxWindows code to use modern C++ techniques (which they would probably be against for backwards compatibility reasons) than it would to create one from scratch. This might also be. It is something to consider. My goal was to include existing libraries in the discussion, and that has been met. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] date_time, lexical_cast and MSVC 7.0
From: Philip Miller [EMAIL PROTECTED] Now, the reason for my posting. I am using MSVC 7.0 and am unable to compile the date_time library tests. Compiling time_parsing.hpp gives me an error in lexical_cast, where there is no output operator for the lexical_castunsigned short compiled for the function parse_delimited_time_duration.But the test regression results for date_time indicates that all tests pass for MSVC 7.0. What am I doing wrong? It could be a couple of things going wrong. First, there were some problems with lexical_cast that were discovered after 1.30 was shipped, so they are fixed in the CVS, but not in the file release. Unless you've done it, I suggest getting the latest file from the CVS. Secondly, unless you already have it, try enabling wchar_t as an intrinsic type (option Zc:wchar_t). Otherwise, it will treat unsigned char and wchar_t as synonyms. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Math Constants Formal Review
From: Daniel Frey [EMAIL PROTECTED] On Sun, 22 Jun 2003 03:32:52 +0200, Terje Slettebø wrote: --- Start --- #include iostream #define BOOST_DEFINE_MATH_CONSTANT(name)\ const struct name##_type\ {\ name##_type() {}\ templateclass T\ operator T() const;\ } name; #define BOOST_MATH_CONSTANT_VALUE(name, type, value)\ template\ name##_type::operator type() const { return value; } --- End --- My question is: Is there any reason why it can't be done this simple? Yes. AFAICS wrong use of your constants with unsupported types is only cought at link-time, not at compile-time. This is IMHO a big problem, big enough to reject this approach. Ok. So maybe an extra level of indirection, as in your code (and Kenniston's) may be preferable. I was wondering what was the point with it. :) Another thing, are the ADD_OPERATOR macro in your code necessary? It compiles fine without it on Intel C++ 7.1. Also, I'm not sure whether it's standard compliant code. I think it is. It specialises a member. What could be the problem with this? As you say, errors are caught at link time. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Math Constants Formal Review
From: Daniel Frey [EMAIL PROTECTED] On Sun, 22 Jun 2003 22:01:19 +0200, Terje Slettebø wrote: Another thing, are the ADD_OPERATOR macro in your code necessary? It compiles fine without it on Intel C++ 7.1. The GCC doesn't work without the operators, as it doesn't implicitly tries to satisfy float*pi_t by casting pi_t to float to use float*float. I think this is OK as the language can go for two ways: a) define float*float and use a promotion/conversion for, say, float*int. b) define several operators float*float, float*int, ... if it's b), the compiler cannot cast pi_t to float as it doesn't know whether to select float*float or float*int, thus it fails. Maybe a question for the language lawyers over at csc++ to find out what's correct. It's an odd thing, anyway. Both g++ 3.2 and MSVC 7.1 complains that there's no matching operator*. Also, I'm not sure whether it's standard compliant code. I think it is. It specialises a member. What could be the problem with this? As you say, errors are caught at link time. I think that you have to declare the specialization in the class' definition, not just outside. But I may be wrong here and I haven't checked it. I don't think so. I tried that, and it gave the error: error: explicit specialization is not allowed in the current scope Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Question about lexical_stream::operator and
(Because this reply is so late, I cc it, as well) Sorry for the late reply. I #included gregorian\greg_date.hpp and gregorian\parsers.hpp in my code, and they indirectly #include lexical_cast.hpp. Here is the warning I get from the compiler (I am using MS Visual C++ 6): * d:\documents and settings\administrator\desktop\dev\boost_1_30_0\boost\lexical_cast.hpp(147) : warning C4800: 'void *' : forcing value to bool 'true' or 'false' (performance warning) d:\documents and settings\administrator\desktop\dev\boost_1_30_0\boost\lexical_cast.hpp(146) : while compiling class-template member function 'bool __thiscall boost::detail::lexical_streamint,class std::basic_stringchar,struct std::char_tr aitschar,class std::allocatorchar ::operator (const class std::basic_stringchar,struct std::char_traitschar,class std::allocatorchar )' and others like this * And here is the line that causes this warning. First off, it's not clear why the return should be a bool, and if that was indeed the author's intention, the conversion between the ( stream input ) which normally should return a stream, and bool, does not seem to make sense (for one thing the return will never be false). ** bool operator(const Source input) { return stream input; } ** Could somebody clarify this. First, the above warning has been fixed in the latest CVS version (this issue was brought up a while ago, too). The function is now defined as: bool operator(const Source input) { return !(stream input).fail(); } This removes the warning, and does the same as the implicit conversion to bool did. The reason the implicit conversion to bool works is that std::stringstream has an implicit conversion to void *, to give the stream's state. It returns zero for fail(), and non-zero otherwise, so converted to bool, it becomes the same as !fail(), as shown above. Conversion to void *, rather than the apparently more obvious bool is to avoid the possibility of it being erroneously used in arithmetic expressions that way, such as: int value=cin + cout; There's also a safe bool technique, which avoids the possibility of the conversion to void * being used for something else, like delete cout;. That technique is used in Boost (safe_bool). Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Any interest in a member function pointer - function pointerconverter? (a la boost::function)
In this comp.lang.c++.moderated thread (http://www.google.com/groups?selm=2045294.t6ppZr3Erj%40technoboredom.net), there was the following request: --- Start quote --- For some reason (I want to pass function pointers to certain libraries) I'd like to convert a member function into a real function pointer. gcc has an extension which can do that, but for portability I came up with this solution: [...] // use it class A { public: int a_member(int k) { return k*k; } }; int main() { int (*fn)(A*, int)=bmfhelper(A::a_member).getfunA::a_member(); A a; int r=fn(a, 3); // sets r to 9 } The duplication of A::a_member as a function *and* a template parameter looks awkward to me, but I can't figure out a way to avoid this. I somehow need that bmfhelper function call to make the template value parameter possible. Has anybody a better idea? --- End quote --- I immediately thought of boost::function, and suggested that. Then you could write it like this: int main() { boost::functionint (A*, int) fn=A::a_member; // The rest the same A a; int r=fn(a, 3); // sets r to 9 } However, it turned out that this couldn't be used for OP, as a real function pointer, not a function object, was needed. That's understandable, if you want to pass it to libraries that take a function pointer (for example callbacks). After some experimentation, for Hiram Berry and I, in the thread, we finally arrived at a way it could be done, which may be used in practically the same way as boost::function. It can be used like this: int main() { function_ptrint (A*, int), A::a_member fn; // The rest the same A a; int r=fn(a, 3); // sets r to 9 } It creates a function object, but it has an implicit conversion to a function pointer of the specified type, which calls the member function, using the given object and any parameters. Could there be any interest in this? For cases where a function pointer, rather than function object, is required. I've attached a version that has been tested on Intel C++ 7.1 and g++ 3.2, and it includes a test. The current version handles from 0 to 2 parameters, but can be extended arbitrarily. It should probably handle the same number of arguments as boost::function. Alternatively, this capability might be incorporated into boost::function, if possible. For a comparison between function objects and function pointers, see (http://www.boost.org/doc/html/function.misc.html). Since the member function is called from the function, it still requires two calls through function pointers, like boost::function. However, the pointer itself only takes up the size of one pointer, and it may be used with libraries requiring function pointers, as mentioned. Feedback is welcome. Regards, Terje #include iostream namespace detail { /// // function_ptr_baseN /// templateclass R, class C, R (C::*pmf)() struct function_ptr_base0 { public: typedef R (*ftype)(C *); operator ftype() { return f; } private: static R f(C *c) { return (c-*pmf)(); } }; templateclass R, class C, class A1, R (C::*pmf)(A1) struct function_ptr_base1 { public: typedef R (*ftype)(C *, A1); operator ftype() { return f; } private: static R f(C *c, A1 a1) { return (c-*pmf)(a1); } }; templateclass R, class C, class A1, class A2, R (C::*pmf)(A1, A2) struct function_ptr_base2 { public: typedef R (*ftype)(C *, A1, A2); operator ftype() { return f; } private: static R f(C *c, A1 a1, A2 a2) { return (c-*pmf)(a1, a2); } }; /// // function_ptr_impl /// templateclass T struct function_ptr_impl; templateclass R, class C struct function_ptr_implR (C*) { typedef R (C::*type)(); templatetype pmf struct base : function_ptr_base0R, C, pmf {}; }; templateclass R, class C, class A1 struct function_ptr_implR (C*, A1) { typedef R (C::*type)(A1); templatetype pmf struct base : function_ptr_base1R, C, A1, pmf {}; }; templateclass R, class C, class A1, class A2 struct function_ptr_implR (C*, A1, A2) { typedef R (C::*type)(A1, A2); templatetype pmf struct base : function_ptr_base2R, C, A1, A2, pmf {}; }; } // namespace detail /// // function_ptr /// templateclass T, typename detail::function_ptr_implT::type pmf struct function_ptr : detail::function_ptr_implT::basepmf {}; /// // Test
Re: [boost] Exception handling... it's time to fix thehttp://www.boost.org/more/error_handling.html
From: Alexander Terekhov [EMAIL PROTECTED] Terje Slettebø wrote in message [EMAIL PROTECTED]: why shouldn't std::exception use std::strings? See here (http://www.boost.org/more/error_handling.html). You should perhaps point out that this is from a comp.lang.c++.moderated posting, and not a Boost posting, or it could be confusing. You give a link at the end, but it's not obvious. http://groups.google.com/groups?threadm=3EC0ECAA.6520B266%40web.de (Subject: Exception handling... it's time to fix the standard) Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Quantity library: any interest?
From: [EMAIL PROTECTED] Even if angle is added as a dimension, to an implementation using an integer vector, it still wouldn't accommodate any other dimensions added later, without rewriting the library and unit definitions. how about having the basic SI dimensions and a couple of extra to-be-defined-by-the-developer dimensions. In that case, full SI compliance and for those who want something extra they can have it. I saw one of the discussed unit libraries provided something like a dimension to be defined by the user/developer. I think I know a way this may be done, now: Default parameters. There's several ways of specifying a unit; one is to use a typelist, such as typedef mpl::vector_c1,0,0,0,0,0,0 kg (Dave Abrahams also showed this approach at the recent ACCU conference), or use template parameters for the dimensions. In both ways, defaults may be used (it's used internally for mpl::vector, anyway). In fact, all could be defaulted (like mpl::vector), giving in this case a dimensionless unit. Named template parameters could be a possibility, as well, so you could do typedef unitkg, m, s-2 newton. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] quantity.hpp uploaded into files section
If one were to implement currency conversion, how might that be done, in general? Does one need to store the conversion rates between any two currencies (giving an N^2 size table), or might it be possible to convert any currency to some universal currency, and from that again to any other, and still getting the right values (giving a 2N table)? Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Quantity library: any interest?
From: David Abrahams [EMAIL PROTECTED] These are my (only slightly informed) opinions. I've heard Walter Brown talk about angle in this context, which was a big influence. Terje Slettebø [EMAIL PROTECTED] writes: Regarding this angle dimension, should it be treated like the other SI-dimensions? That is, say that you represent an SI quantity/unit with an integer vector giving the exponents: templateint kg,int m,int s,int A,int K,int mol,int cd,int angle class quantity; If you multiply two quantities, you multiply the value and add the exponents, so quantity0,1,0,0,0,0,0,0(10) * quantity0,1,0,0,0,0,0,0(10) = quantity0,2,0,0,0,0,0,0(100) (m * m = m^2) Would this hold for angle, as well? Yes. Angle is a dimensionless scalar (length/length). All its exponents are zero. Yes, Renej (in the posting I replied to) also pointed out that angle is a dimensionless quantity. However, in their real-life experience, they found it useful not to have it dimensionless, but instead having it as an additional dimension, to be able to distinguish things like velocity and angular velocity. It was in this context that I wondered how angle - as a dimension - should be treated. That is, does it make sense to say angle * angle = angle^2? Probably not, but only because angle * angle doesn't make much sense. Does that ever come up in real life? If it's a dimensionless quantity, it wouldn't matter (all exponents would still be zero). However, as a dimension, it would give angle^2. That's what I wondered about. I understand that e.g. angle/s (angular velocity) makes sense, but should a library allow any combination with angle and the other dimensions? Not arbitrarily: I meant - should it allow the same combinations as the other dimensions are allowed. That is (simplified, using only one dimension): quantityd1 * quantityd2 = quantityd1+d2 quantityd1 / quantityd2 = quantityd1-d2 quantityd + quantityd = quantityd quantityd - quantityd = quantityd angle(pi/2) / mass(40); // OK angle(pi/2) + mass(40); // error Let's again cast it in the quantity example template I gave in the last posting, to examine it. Let's say that the angle is expressed in radians. We then have: templateint kg,int m,int s,int A,int K,int mol,int cd,int rad class quantity; typedef quantity1,0,0,0,0,0,0,0 mass; typedef quantity0,0,0,0,0,0,0,1 angle; angle(pi/2) * mass(40) = quantity1,0,0,0,0,0,0,1(pi/2*40) (rad * kg) angle(pi/2) + mass(40) The last one will be an error, as you said. I'm guessing that the answer to my question is, yes, angle, when expressed as a dimension, may be treated like the other dimensions. There's also a question of what then if someone would like to add a money dimension, to avoid having money be interchangeable with dimensionless quantities. However, in this case, multiplying currencies with each other really doesn't make any sense (e.g. USD(10)*USD(10) = USD^2?), which _would_ be allowed, if it used the same framework as above. Therefore, maybe money is better treated in a different way, than with an exponent. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Quantity library: any interest?
From: [EMAIL PROTECTED] we use the int-based template approach for a couple of years now in our AGV controller software. We actually sometimes reach the stage that it works when succesfully compiled and linked. Since our control software is physics throughout (field of robotics), the type safety is very important. However, besides the basic SI units we also have 'angle' as a dimension which allows us to distinguish 'velocity' and 'angular velocity' for example. Hence, from out 'real user' experience (engineering point of view) it would be a necessity to add 'angle' as a dimension without breaking already defined quantities. Most (all?) units libraries already define 'angle' to be dimensionless, which is true in scientifically spoken, but pragmatically (engineering ;-) less handy. There's another question. If we add angle as a dimension, then what kind of angle is it? There are several kinds of angles, such as radians (plane angle) and steradians (solid angle). If both were represented by the same angle dimension, then it probably wouldn't make much sense to add radians and steradians (and what would be the resulting quantity?), yet, the library would allow it. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: class proposal
From: Justin M. Lewis [EMAIL PROTECTED] As for a function returning a single param, I agree, normally you'd just return it, UNLESS it's some big structure you don't want being copied all over the place, then passing it by reference to a function makes more sense. The compiler may elide such copy, even if the temporary being returned is a named variable, and several compilers (such as g++ and the EDG based ones), does this optimisation (RVO). For example: class big_class { ... }; big_class f(...) { big_class temp; ... return temp; } // Only the constructor is called, here, no copy constructor big_class value = f(...); Also, if you want to return multiple values, std::pair or boost::tuple may be used for that, as Noel Yap pointed out. I understand the motivation is to transform a lot of existing code into something that may be more easily understood. However, an alternative to your method is to use techniques that has been proposed in this thread. For example: int return_value = f(type may_change, const type may_not_change); // Current function int return_value = fA(c_outtype may_change, const type may_not_change); // Your method boost::tupleint, type fB(const type may_not_change); // Alternative Use: type value; int return_value = fA(out(value), const_value); // Your method int return_value; boost::tie(return_value, value) = fB(const_value); Also, you may enforce that the parameters aren't changed, by using const: const type const_value = ...; fA(const_value, ...); // Error, can't bind to non-const reference This may be a larger refactoring than adding out() and in_out(), though, especially for a large code base, as you mention. I'm just concerned with that out() and in_out() isn't a very common way to do it, so it may be best to do it in an idiomatic way, to begin with. Also, statements like: boost::tie(return_value, value) = fB(const_value); stands out in the code, rather than being more hidden with an out(). Thus, they may have a better chance of being possibly further refactored. Say that the return code says whether or not a valid object is returned. This may be changed to: boost::optionaltype result = fB(const_value); Or maybe throwing an exception would be more appropriate: type value = fB(const_value); // Throws on failure The point really is the same as with your proposal - making it explicit in the code what is happening. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: class proposal
Just to add some to my previous posting. Also, from a maintenance POV, having variables that doesn't change throughout a function (or program), tends to make it easier to understand. Having functions which change their arguments goes rather against that. One exception is input stream operators, where it's really no other way of doing it than first declaring a variable, then streaming into it. For example: const some_type valueA=...; const some_type valueB = f(valueA); // Possibly many lines of code here // What is valueA and valueB here? Answer: The same as when they were declared. Yes, I know it may be a massive undertaking to start making a program, which wasn't designed that way, const correct. However, it may be one of the better refactorings to do. It also highlights all the points where something may be changed, and where further refactorings (such as those in the previous posting) may be appropriate. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: class proposal
From: Justin M. Lewis [EMAIL PROTECTED] Well, I guess, based on all the code I've been reading at work it didn't seem so small, chasing down all kinds of functions across 100's of files to see why exactly values are changing mid function I'm looking at without warning. Anyway, this would allow for stronger enforcement of the rule that changing params should be marked somehow. As the programmer of a library people are using, I can force them to mark the params they're passing as out or in_out, so in 5 years when someone else comes along and has to debug it, it's all clear what's happening. Why not use T if the function may change it, and const T if it won't? Simple and clear. No need to use pointers, to differentiate between it. An advantage with references is that you may pass by value, or const reference, and to the caller, it's called in the same way, so the pass by value or const reference may be an implementation detail. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Passing template-ids as macro parameters
From: Paul Mensonides [EMAIL PROTECTED] Terje Slettebø wrote: Is there some way (using PP-lib, or whatever), to pass a template-id with more than one parameter (thus, it contains at least one comma), to a macro? E.g.: #define TEST(a) testa t; TEST(std::pairchar,int) // Won't work Maybe some sort of variation of BOOST_PP_IDENTITY: #define BOOST_PP_IDENTITY1(a) a #define BOOST_PP_IDENTITY2(a,b) a,b #define BOOST_PP_IDENTITY3(a,b,c) a,b,c etc. TEST(BOOST_PP_IDENTITY2(std::pairchar,int)) // Now ok I'll answer all three of these emails at once, since they are about the same thing. First, the above will cause problems, specifically problems like this: #define T1(a) T2(a) #define T2(a) testa t; #define IDENTITY2(a, b) a, b T1(IDENTITY2(std::pairchar, int)) // error I.e. by the time that T2 is invoked, IDENTITY2 has already expanded, which yields too many arguments to T2. Right. However, for simple use (only one level of macro expansion), this works, and has the advantage of being simple and non-intrusive to use. What we need is a general solution and a set of conventions for passing types. This is difficult without variadics to do with the preprocessor itself. Specifically, you have to use the core language: templateclass T struct wrap { typedef T type; }; templateclass T struct wrapvoid (T) { typedef T type; }; #define TYPE(x) wrapvoid x::type TYPE((int)) // okay TYPE((std::pairchar, int)) // okay However, this has its own problems. Specifically, it is using function types to store the type--which is inside parentheses and therefore protected from the preprocessor. The use of function types with cause certain things to error: TYPE(( void )) // error TYPE(( int (int, int) )) // function type altered to pointer-to-function TYPE(( int[2] )) // array altered to pointer Right. It's similar to Aleksey's round lambda. There is only one other language construct that might be of use here: pointers-to-members. Specifically, it is parenthesized, yet does not undergo promotion/alteration when used in a parameter list. However, it is intrusive: templateclass struct wrap; templateclass T struct wrapvoid (T::*)(void) { typedef T type; }; #define TYPE(x) wrapvoid T(void)::type TYPE(( std::pairint, int::* )) ^^^ Also, this cannot be used for non-class types--which can still have commas in them: templateclass T, class U struct typelist { typedef T head; typedef U tail; }; TYPE(( typelistint, nil::head::* )) // error So, without variadic macros, there is no good solution. Instead, you have to resort to hacks that require you to know the number of unbound commas in the type: #define IN(s, x) (s) x #define OUT(x) BOOST_PP_TUPLE_REM x #define M1(type) M2(type) #define M2(type) OUT(type) MACRO( IN(2, (std::pairint, int)) ) I'm not sure how this latter solution could be used. How could MACRO retrieve the type being passed? Thanks. :) Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] bad_lexical_cast
From: Alisdair Meredith [EMAIL PROTECTED] I see that this has been the topic of much discussion lately, but just confirming this little warning from the regressions has not snuck by unnoticed: # 'boost::bad_lexical_cast::what()' hides inherited virtual function 'std::exception::what() const' [const missing, to state the obvious] This apparently only affects 3 compilers on Windows, haven't cross-checked the other platforms. Thanks for pointing this out. It's fixed now. Yeah, oddly enough, this gave no warning, even when running on the highest warning level, and strict mode, on Intel C++ 7, and MSVC 6/7. Also, the tests only checks that the exception is thrown when it's supposed to, it doesn't check what(). Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: io operations for stl containers?
From: Jason House [EMAIL PROTECTED] I had 2 thoughts today... 1. Is it at all useful/possible to use a lambda-like notation? In what way? Could you have given a rough syntax-example? An example in BLL is: std::for_each(v.begin(), v.end(), std::cout _1 '\n'); In the past, I've liked the look of that a lot. (the comments about alternate notation made me think of it) 2. Why are we restricting the output to strings? That _is_ a natural question, isn't it? :) Couldn't the types of the 3 delimiter strings actually be implicit template parameters? (the char/wchar versions made me think of that) Yes, that is how it currently works; it deduces the types passed to the format function template, and returns an object of type format_type (analogous to many cases, such as bind1st/binder1st). Since all the string parameters have default to empty string, this is done by having three overloads of the format function template - for std::basic_string, const char * and const wchar_t *. That way, you can use , L, etc. as appropriate, for the default. As mentioned in some previous postings, a possibility for generalising the formatting could be to pass a visitor object to the format-function, instead of the strings, which is then invoked at the specific times during output (begin/end sequence, etc.). One could then also support things like line numbers and indentation, without hardcoding how this is done. It would also be possible to make a visitor object which took strings in the constructor, and gave the current semantics. This approach seems to require dynamical allocation of the format data, and virtual functions, though. Since this means quite a bit of change, I haven't done it so far, but I'm open to the possibility. An example of its use: // Line numbering visitor (could be included in the library) // // All virtual functions are included for illustration. In practice, the once with empty body could be omitted. templateclass T, class CharType, class CharTraits class numbering_type : public visitor_base { public: explicit numbering(int ln) : line_number(ln) {} virtual void start_sequence(std::basic_ostreamCharType,CharTraits stream) {} virtual void end_sequence(std::basic_ostreamCharType,CharTraits stream) {} virtual void element(std::basic_ostreamCharType,CharTraits stream, const T element) { stream line_number ' ' element '\n'; ++line_number; } private: int line_number; }; // The numbering function template returns a numbering_type object typedef std::vectorchar vector; vector v; // Fill vector std::cout formatvector(numbering()) v; Output: 1 - A 2 - B 3 - C etc. Thanks. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: io operations for stl containers?
Hi. I've now uploaded the latest version of the composite stream operators library at Yahoo Files (http://groups.yahoo.com/group/boost/files/composite_stream_operators/) and the Sandbox (boost/io/format/ and libs/io/format).. Since the libraries in the Sandbox use the boost namespace, this one does the same. All components are in the boost::io namespace. There are no docs, yet, but there are several test programs, illustrating use for all supported types (the list of these are given below). I also include information here. Feedback is welcome. Examples of use: std::vector --- #include boost/io/format/std/vector.hpp std::vectorint v; // Fill vector // Output (using user-changeable default format) std::cout v; Output: [1,2,3,4,5,6,7,8,9,10] std::map #include boost/io/format/std/map.hpp typedef std::mapint,char map; typedef map::value_type value_type; map values; // Fill map std::cout formatvalue_type([, ]\n, = ) formatmap(,,) values; Output: [1 = A] [2 = B] [3 = C] Array --- #include boost/io/format/array.hpp int array[]={1,2,3,4,5,6,7,8,9,10}; std::cout array '\n' format_ ()[N](, , \n) array; Output: [1,2,3,4,5,6,7,8,9,10] 1 2 3 4 5 6 7 8 9 10 Here is a synopsis -- namespace boost::io - format - Set output formatting == Type options -- _ - Any type N - Any size (for array) template_name_ - Any instantiation of the given template (may need more _s, one for each parameter without default) Syntax -- formatType(start sequence, end sequence, delimiter, [start element, end element])[.set_default_format()] formatType(set/unset format) If set_default_format() is used, it may be used without a stream, and it then sets the format for all streams. Examples -- stream formatstd::vectorint (...) // Set format for std::vectorint stream formatstd::vector_ (...) // Set format for any instantiation of std::vector stream format_(...) // Set format for any type stream formatstd::vectorint (false) // Unsets format for std::vectorint It checks for format settings, going from the most specific to the most general, stopping when it has found a set format. E.g. for the above example, this means checking in the following order: std::vectorint std::vector_ _ _ (any stream) The library sets the following default for all streams (the last format checked), which may be changed by the user. This default is set rather arbitrarily, and is open to change. This is so that no formatting is needed to be set, to get useful output: format_([, ], ,).set_default_format() - Sets format for all types, for all streams. It also handles wide character formatting: formatType(L[, L], L,) sequence - Lets a sequence, given with start/end iterators, be output as the given type == Syntax -- sequenceType(start iterator, end iterator) Examples -- #include boost/io/format/sequence.hpp std::vectorint v; // Fill vector std::cout sequence_(v.begin(),v.begin()+10); Output: [1,2,3,4,5,6,7,8,9,10] typedef std::istream_iteratorint in; std::cout sequence_(in(std::cin),in()); Input: 1 2 3 4 5 6 7 8 9 10 Output: [1,2,3,4,5,6,7,8,9,10] wrap - Lets a type be output using set format, even if it has its own output operator == Some types, such as std::complex, std::bitset, and boost::dynamic_bitset have already output stream operators defined, so to set their format, one may wrap the value before outputting. Syntax - wrap(value) Examples -- #include boost/io/format/std/complex.hpp std::complexdouble value(1.23, 2.34); std::cout value '\n' wrap(value); Output: (1.23,2.34) [1.23,2.34] Supported types = Arrays std pair complex (has output operator, use wrap) vector list deque set multiset map multimap bitset (has output operator, use wrap) boost dynamic_bitset (has output operator, use wrap) The supported types may also be extended by the user. Header organisation boost/io/format --- |--- std |--- boost libs/format/io --- |--- tests Compatibility == The library uses standard C++, but isn't very portable currently. It has been tested on Intel C++ 7.0 and g++ 3.2. I plan to work on the portability, and should soon get it to work on MSVC, etc., as well. The names, syntax and semantics is open to suggestions for change. I hope Daryle Walker doesn't mind that this library is sharing the io directory and namespace, at the Sandbox. If so, I could change it from io/format to io_format. Thanks for the patience to those who have waited for this update. Regards, Terje
Re: [boost] Re: MSVC++ 6.0 compiler errors with 1.30.0(mostlylexical_cast.hpp)
From: Rozental, Gennadiy [EMAIL PROTECTED] Even if none of the above looks sound for you I still argue that lexical_cast *should not force* inclusion of typeinfo. It's not inconvinience - it's showstopper. It's much more important than providing specific type info. In majority of the cases one knows it anyway. Kevlin Gennadiy. So. Are we gonna stuck with typeinfo in lexical_cast? Could we have at least some discussion about this? I'd certainly be open to make the type_info part optional. A question is how to do it. Using policies may complicate the interface, and from earlier discussions, and also from the earlier Future directions part of the docs, it turned out that adding new parameters weren't deemed acceptable (due to it no longer looking like a cast in that case). Another way may be a macro. However, as has been mentioned in this thread, it appears that the config macros aren't geared for macros with optional exclusion of RTTI. Then one might have a lexical_cast specific macro for it, like BOOST_LEXICAL_CAST_USE_RTTI, like you suggested. Kevlin or others, any thoughts? Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: io operations for stl containers?
From: Rozental, Gennadiy [EMAIL PROTECTED] #include boost/io/format/std/vector.hpp #include boost/io/format/std/map.hpp #include boost/io/format/array.hpp I am afraid boost/io/format will be confusing in a sight of presence of Boost.Format. I understand. Well, it's in a different namespace. I would prefer (since it all about container output formatting) boost/io/container Well, it actually may handle any composite type, such as std::complex, std::pair, etc., as well. It also handles any sequence (using io::sequenceType(begin,end) ), not just containers. I used to call it composite_format, but that was rather long... Using io::formatType(...), I think is quite succinct. Also it could be stl instead of std, though it's the matter of taste. The directories follow the namespaces, so it has std and boost. STL is only a subset of the standard library, so also for that reason, I think std would be more appropriate. std::cout formatvalue_type([, ]\n, = ) formatmap(,,) values; ... Syntax -- formatType(start sequence, end sequence, delimiter, [start element, end element])[.set_default_format()] formatType(set/unset format) I personally would really prefer verbose format specification. So I should not remember what each of the parameters means by it's position. Something along this lines: std::cout start_elelmentvalue_type( [ ) // if you need value type_here. I am not sure Yes, you do, or it won't know which type to set it for. end_elementvalue_type( ]\n ) element_delimetervalue_type( = ) ... values; Or std::cout formatvalue_type().start_elelment( [ ).end_element( ]\n ).delimeter( = ) ... values; Or mix of this styles. Or - the very best - all of them. This should be quite easy to add. The latter style is also used in Reece Dunn's list manipulator, which also deals with output for sequences. I don't have that much practice with it, but I've found myself that I don't have a problem remembering which parameter is what, in the 3+2 optional parameter list. Lack of verbosity may be considered one of the advantages over writing explicit output code. Thanks for the feedback. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)
From: David Abrahams [EMAIL PROTECTED] Rozental, Gennadiy [EMAIL PROTECTED] writes: Even if none of the above looks sound for you I still argue that lexical_cast *should not force* inclusion of typeinfo. It's not inconvinience - it's showstopper. It's much more important than providing specific type info. In majority of the cases one knows it anyway. Kevlin Gennadiy. So. Are we gonna stuck with typeinfo in lexical_cast? Could we have at least some discussion about this? My contribution to the discussion is that I don't think supporting C++ language subsets is worth complicating the interface in the way you propose. Maybe lexical_castT*(whatever) should return 0 on failure and that should be enough for those who can't handle the exceptions we want to throw... though I don't know how (or if) that interacts with things like char const*. Technically, this should be possible, since it now throws an exception if you try to convert to any pointer, as it checks for that. This is to remove the possibility of trying to convert to char *, which could otherwise succeed (due to the design of basic_istream), but would give undefined behaviour. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: MSVC++ 6.0 compiler errors with 1.30.0(mostlylexical_cast.hpp)
From: Rozental, Gennadiy [EMAIL PROTECTED] Another way may be a macro. However, as has been mentioned in this thread, it appears that the config macros aren't geared for macros with optional exclusion of RTTI. No. this has nothing to do with config Well, as Dave A said in another mail, there is already a config macro to disable exceptions. Whether or not libraries check for it is optional, though. From the docs: BOOST_NO_EXCEPTIONS - The compiler does not support exception handling (this setting is typically required by many C++ compilers for embedded platforms). Note that there is no requirement for boost libraries to honor this configuration setting - indeed doing so may be impossible in some cases. Those libraries that do honor this will typically abort if a critical error occurs - you have been warned! Embedded C++ doesn't have RTTI, either. Therefore, a BOOST_NO_RTTI might be reasonable, as well. I understand that your suggestion is not for macros describing lack of compiler support, but rather user settings. Yet, couldn't these be used for either, by explicitly setting them before any Boost includes? Having a lexical_cast-specific macro will just cover that component, while the same issue could occur with another library, unless a Boost-wide configuration macro is used. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)
From: David Abrahams [EMAIL PROTECTED] Terje Slettebø [EMAIL PROTECTED] writes: From: David Abrahams [EMAIL PROTECTED] Terje Slettebø [EMAIL PROTECTED] writes: C:\Program Files\Boost\boost_1_30_0\boost/lexical_cast.hpp(74) : warning C4512: 'no_lexical_conversionclass std::basic_stringchar,struct std::char_traitschar,class std::allocatorchar ,long' : assignment operator could not be generated This is due to that it stores a const std::string object, describing the exception Are you saying that you have defined an exception with a std::string member? That's VERY bad! Throwing that exception can lead directly to termination! You mean if the exception itself throws during construction or copying? Yes. I've tried the program below on Intel C++ 7.0 and MSVC 6, and I haven't got it to call terminate(). It may be that it doesn't handle exceptions correctly, though. Because you are not running in a low-memory condition. What difference would that make? In the example program, it throws an exception from the exception constructor, effectively simulating an out-of-memory exception. As it stands, it prints Exception - Constructor, as it throws an exception in the constructor of the Exception exception. If the throw-statement in the constructor is commented out, it prints Exception - Exception, apparently not invoking the copy constructor when throwing the exception (which it's allowed to). Irrelevant. A program that invokes undefined behavior may appear to work fine also. You said that it may terminate the program. I assumed from that that you meant it would call terminate(). Did you instead mean undefined behaviour? If so, how? And how would that be related to terminating the program? As you say, anything can happen with undefined behaviour, including the expected behaviour. What's wrong with char const*? You mean storing the string as a character array? No, I mean not storing the string at all (char const* is not an array), but storing an array is another option. Yes, I know that, of course. However, since if you just store a pointer, the string has to be allocated some other way. How would you allocate it? If you use new, won't that bring the same potential problem as std::string? This is why I thought you might have meant storing an array (as STLPort does it), rather than storing a pointer. Storing an array eliminates the possibility of throwing an exception at construction. Sure, that's possible, and I see that STLPort do it, and it's probably safer, as you say. It does mean you have to specify the maximum string length in advance, though. As no_lexical_conversion what() prints out the source and target types, it may truncate long type names. There's no guarantee you have readable names anyway. Finally, you should never format exception messages at the throw point. An exception whose what() needs to print type names should store the typeids and put the formatting logic in what(). A problem is that what() can't throw, either. So you'd have to wrap it in a try-catch. Then there's the issue of what to return from what() if the formatting throws. As Kevlin says in another posting, the terminate on second exception, which I thought you alluded to in your first reply, and maybe you did, may not apply at the point of construction, since it only applies after the evaluation of the throw-expression. In other words, if the construction fails, you only loose the first exception, and it instead throws the new one. As for throwing in the copy constructor, that might be a problem, since the call by value semantics of throwing an exception may mean that it makes a copy of the exception, after the throw-expression is evaluated. The reason the extended error type was added, was that there has been requests on this list for storing the types used in the conversion, in the exception, to make it easier to know which conversion failed. It has also proved useful in the regression testing. bad_lexical_cast was not modified, to not break the interface, so this type inherits from it. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)
From: Gennaro Prota [EMAIL PROTECTED] On Sat, 22 Mar 2003 09:52:07 -0500, David Abrahams [EMAIL PROTECTED] wrote: Kevlin Henney [EMAIL PROTECTED] writes: However, the decision as to whether this should be in the 'what' string is perhaps one that can be revisited. It would be feasible to avoid any allocation issues at all by leaving the human readable string as general as it was before and adding type_info members that described the source and target types. Yes, that was my suggestion. I'm happy that std::type_info has a private copy constructor. Hadn't it been for that, my suggestion to use just a couple of typedefs would have been routinely rejected :-) Storing a couple of type members is not enough, by itself. How would a catch-clause taking e.g. a reference to bad_lexical_cast access them? To access the typedefs, you need to know the exact type thrown, which means you need to know the types to begin with... I don't understand how this relates to private copy constructor, though, could you explain? Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)
From: David Abrahams [EMAIL PROTECTED] Terje Slettebø [EMAIL PROTECTED] writes: Terje Slettebø [EMAIL PROTECTED] writes: I've tried the program below on Intel C++ 7.0 and MSVC 6, and I haven't got it to call terminate(). It may be that it doesn't handle exceptions correctly, though. Because you are not running in a low-memory condition. What difference would that make? In the example program, it throws an exception from the exception constructor, effectively simulating an out-of-memory exception. Replace operator new so that it throws unconditionally *after* the exception object is constructed. If you try this on an implementation where the exception object gets copied during unwinding, it will terminate(). It's the copy ctor that matters in this case. The test program also had a throwing copy constructor. However, on Intel C++ 7.0, the copy was elided, so the copy didn't get tested. As it stands, it prints Exception - Constructor, as it throws an exception in the constructor of the Exception exception. If the throw-statement in the constructor is commented out, it prints Exception - Exception, apparently not invoking the copy constructor when throwing the exception (which it's allowed to). Irrelevant. A program that invokes undefined behavior may appear to work fine also. I did not state the latter part as a general claim, which is why I said that eliding the copy is something it's allowed to, but not required to. Thus, there's no argument to consider irrelevant. What's wrong with char const*? You mean storing the string as a character array? No, I mean not storing the string at all (char const* is not an array), but storing an array is another option. Yes, I know that, of course. However, since if you just store a pointer, the string has to be allocated some other way. How would you allocate it? Just use a string literal; the compiler has to allocate that as part of the program image. Sure, that's what the original lexical_cast did. However, if you are to include in the string info about the types, storing it as a string literal is not enough. As Kevlin says in another posting, the terminate on second exception, He never used that phrase. What do you mean? True. I was referring to In an insufficient-memory condition the former will result in a bad_alloc being thrown and in the latter a call to terminate. In other words, if you throw an exception in the copy constructor, when an exception has already been thrown, i.e. during stack unwinding, as you also say in the updated Error and Exception Handling document. which I thought you alluded to in your first reply, and maybe you did, may not apply at the point of construction, since it only applies after the evaluation of the throw-expression. In other words, if the construction fails, you only loose the first exception, and it instead throws the new one. I am aware of how C++ EH works, really! I know you are. This was mostly to try to get a common understanding, since I was a little confused about what you meant, and therefore wrote the above, explaining what I had meant. The reason the extended error type was added, was that there has been requests on this list for storing the types used in the conversion, in the exception, to make it easier to know which conversion failed. That's a good request, but you didn't do that, did you? Let me rephrase it: IIRC, the request was for storing information about the types used, not how this was to be done. Thus, whether or not this does what was requested depends on how to interpret the request. The suggestion to store (pointer/reference to) type_info objects doesn't store the types, either; it stores information about them, this time in a way easier for the program to use. So, I can just as well say as you say: The suggestion you said you meant (storing references to type_info objects) doesn't do that, either, does it? Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)
From: David Abrahams [EMAIL PROTECTED] Terje Slettebø [EMAIL PROTECTED] writes: From: Gennaro Prota [EMAIL PROTECTED] I'm happy that std::type_info has a private copy constructor. Hadn't it been for that, my suggestion to use just a couple of typedefs would have been routinely rejected :-) Storing a couple of type members is not enough, by itself. How would a catch-clause taking e.g. a reference to bad_lexical_cast access them? To access the typedefs, you need to know the exact type thrown, which means you need to know the types to begin with... There's absolutely no reason I can see to make the exact exception type depend on the types concerned. Just use a straightforward class, something along the lines of: struct bad_lexical_cast : std::exception { bad_lexical_cast( std::type_info const src, std::type_info const dst) : m_src(src), m_dst(dst) {} char const* what() throw() { return bad_lexical_cast; } std::type_info const src() const { return m_src; } std::type_info const dst() const { return m_dst; } private: std::type_info const src; std::type_info const dst; }; Right. I see that Kevlin also suggest this approach in a later posting. The original version of the extended exception used static initialisation, as mentioned, which is why it was templated. I think this is a good approach. Regarding the other MSVC 6 warning given in the original report, Gennaro Prota has suggested using an explicit !=, rather than relying on the implicit conversion from pointer to bool. This also avoids using a cast, instead. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)
From: David Abrahams [EMAIL PROTECTED] Terje Slettebø [EMAIL PROTECTED] writes: As it stands, it prints Exception - Constructor, as it throws an exception in the constructor of the Exception exception. If the throw-statement in the constructor is commented out, it prints Exception - Exception, apparently not invoking the copy constructor when throwing the exception (which it's allowed to). Irrelevant. A program that invokes undefined behavior may appear to work fine also. I did not state the latter part as a general claim, which is why I said that eliding the copy is something it's allowed to, but not required to. Thus, there's no argument to consider irrelevant. What I meant (though sorry I was probably too blunt about it) was that it's irrelevant whether you actually observed termination or not, unless you're intending for lexical_cast to work just on that compiler. That's correct, and I meant nothing else, either. The reason the extended error type was added, was that there has been requests on this list for storing the types used in the conversion, in the exception, to make it easier to know which conversion failed. That's a good request, but you didn't do that, did you? Let me rephrase it: IIRC, the request was for storing information about the types used, not how this was to be done. Thus, whether or not this does what was requested depends on how to interpret the request. The suggestion to store (pointer/reference to) type_info objects doesn't store the types, either; it stores information about them, this time in a way easier for the program to use. So, I can just as well say as you say: The suggestion you said you meant (storing references to type_info objects) doesn't do that, either, does it? Ugh. As far as it's possible to store a type at all in C++, yes my suggestion does store the types. No, it doesn't; it stores a reference to an object describing them. My version stored a string describing them. I just applied the same hair-splitting reasoning that made you categorically state that my implementation didn't do that (what was quoted as requested). My implementation do it just as well as your suggestion, both stores information describing the types. One is geared towards user-readable information, one is geared towards program-readable information. Agree? I wouldn't have made this such a big issue had you not claimed the implementation didn't do what was requested, when both that and your suggestion implements the request. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)
From: David Abrahams [EMAIL PROTECTED] Terje Slettebø [EMAIL PROTECTED] writes: What I meant (though sorry I was probably too blunt about it) was that it's irrelevant whether you actually observed termination or not, unless you're intending for lexical_cast to work just on that compiler. That's correct, and I meant nothing else, either. If you understood all along that the copy ctor of your exception class could cause termination when the exception was thrown, I don't understand why I went through this long twisty discussion just to have you tell me so. What happened was: 1. You told me it could cause termination. 2. I made a test case, and observed that it didn't cause termination on construction, and that due to the implementation, no copy was made, so it didn't test the copying (which may cause termination). 3. You said it was irrelevant that no termination was observed. 4. I said that I hadn't claimed the test proved there would be no termination, since on that platform, the copying wasn't tested. As you can see, I agreed with you from the beginning. It just seems that you thought I claimed that since it didn't terminate, it wouldn't do that on any platform. I didn't mean that, and it seems this misunderstanding was the cause of this long discussion. I wouldn't have made this such a big issue had you not claimed the implementation didn't do what was requested, when both that and your suggestion implements the request. I think there's a stronger argument for type_info being a representative of the type, because among other things an implementation is allowed to have type_info::name() return the empty string for all types. I don't disagree with that. I merely made the point that my implementation also fulfilled the request, which it seems you now agree to, as well. I also think returning the type as type_info is better. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)
From: John Swartzentruber [EMAIL PROTECTED] I downloaded 1.30.0 and tried to build my project. I got a few errors that seem to be in boost, primarily in lexical_cast. Also, weak_ptr.hpp uses bad_weak_ptr without including boost/detail/shared_count.hpp anywhere. I can fix that by including it in my code. These are the warnings in lexical_cast.hpp. Because I treat warnings as errors, these pretty much keep me from using this version of boost. In the reported output there are two warnings, both level 4 warnings, which are more or less remarks. That's why they are disabled in the lexical_cast unit tests. They are: C:\Program Files\Boost\boost_1_30_0\boost/lexical_cast.hpp(74) : warning C4512: 'no_lexical_conversionclass std::basic_stringchar,struct std::char_traitschar,class std::allocatorchar ,long' : assignment operator could not be generated This is due to that it stores a const std::string object, describing the exception. no_lexical_cast is the concrete exception type returned, and it inherits from bad_lexical_cast. The reason it stores a string object, rather than using a static string member (since the information is the same for all objects of it), is that MSVC 6 couldn't handle that static initialisation. Ironic, huh? :) A simple way to fix this is to make the string object non-const, although there's really no reason for it to be assigned to, as all objects are the same. C:\Program Files\Boost\boost_1_30_0\boost/lexical_cast.hpp(147) : warning C4800: 'void *' : forcing value to bool 'true' or 'false' (performance warning) C:\Program Files\Boost\boost_1_30_0\boost/lexical_cast.hpp(146) : while compiling class-template member function 'bool __thiscall This uses the implicit conversion from pointer to bool, and one could probably avoid the warning with an explicit cast. An alternative to the above is: #pragma warning(disable: 4512 4800) :) Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)
From: David Abrahams [EMAIL PROTECTED] Terje Slettebø [EMAIL PROTECTED] writes: C:\Program Files\Boost\boost_1_30_0\boost/lexical_cast.hpp(74) : warning C4512: 'no_lexical_conversionclass std::basic_stringchar,struct std::char_traitschar,class std::allocatorchar ,long' : assignment operator could not be generated This is due to that it stores a const std::string object, describing the exception Are you saying that you have defined an exception with a std::string member? That's VERY bad! Throwing that exception can lead directly to termination! You mean if the exception itself throws during construction or copying? I've tried the program below on Intel C++ 7.0 and MSVC 6, and I haven't got it to call terminate(). It may be that it doesn't handle exceptions correctly, though. #include iostream #include string #include stdexcept class Exception : public std::runtime_error { public: Exception() : std::runtime_error(Exception) { throw std::runtime_error(Construction); } Exception(const Exception ) : std::runtime_error(Exception (copied)) { throw std::runtime_error(Copy); } }; int main() { try { throw Exception(); } catch(const std::exception e) { std::cout Exception - e.what() '\n'; } catch(...) { std::cout Unknown exception\n; } } As it stands, it prints Exception - Constructor, as it throws an exception in the constructor of the Exception exception. If the throw-statement in the constructor is commented out, it prints Exception - Exception, apparently not invoking the copy constructor when throwing the exception (which it's allowed to). What's wrong with char const*? You mean storing the string as a character array? Sure, that's possible, and I see that STLPort do it, and it's probably safer, as you say. It does mean you have to specify the maximum string length in advance, though. As no_lexical_conversion what() prints out the source and target types, it may truncate long type names. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Win32/VC++ 6.0 lexical_cast problems
From: Beman Dawes [EMAIL PROTECTED] A fresh version of the Win32 regression tests has just been posted. See http://boost.sourceforge.net/regression-logs/cs-win32-RC_1_30_0-diff.html There are seven new fails in date_time tests; presumably all caused by lexical_cast.hpp problems. See typical error message below. I see that all of the new failing tests are on MSVC 6, and it seems the errors is due to allowing wide character support on MSVC 6. In the Date/Time tests there are calls such as lexical_castunsigned short(std::string), which lexical_cast on MSVC 6 interprets as trying to convert from std::string to wchar_t. This also fails in the lexical_cast unit test for MSVC 6. Ok, it seems we may have to exclude wide character support for lexical_cast on MSVC 6, to avoid breaking Date/Time. I suggest something like: #if defined(BOOST_NO_STRINGSTREAM) || \ defined(BOOST_NO_STD_WSTRING) || \ defined(BOOST_NO_STD_LOCALE) || \ defined(BOOST_NO_CWCHAR) || \ defined(BOOST_MSVC) (BOOST_MSVC = 1200) #define DISABLE_WIDE_CHAR_SUPPORT #endif (Testing for BOOST_NO_INTRINSIC_WCHAR_T, instead, would also disable wide character support on Intel C++ (on Windows), which does work with lexical_cast) I've tested this with Date/Time's testclock.cpp (one of the failing tests) on MSVC 6 and Intel C++ 7, and it now works. On the plus side, it appears to now work on g++ 2.95. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: RC_1_30_0 still broken -- More lexical_cast
From: Kevlin Henney [EMAIL PROTECTED] In article [EMAIL PROTECTED], Terje Slettebø [EMAIL PROTECTED] writes However, the three failing tests for each of MSVC 6 and g++ 2.95 (different ones for the two) are in the middle of some wide character tests. My original intent was to disable wide character support for any platform that was effectively less than 99% conforming in its support for wide characters, including non-intrinsic wchar_t. So g++ 2.95 and MSVC 6 should not, strictly speaking, offer any support for wide character conversions out of the box. Using John's suggestion, it now correctly disables wide character support for g++ 2.95, so the three failing tests that Genny reported (and which I posted) are unrelated to wide characters. To deal with them, one may set expected failures, as Gennadiy suggested. For MSVC 6, in my last posting, I posted a patch to disable wide characters for MSVC 6, as well. That takes care of the three other test failures on that compiler, since they were related to wide characters. So in summary, one may do: - Remove all BOOST_WORKAROUND's (for MSVC 6 and g++, they are not needed anymore for the former, and for the latter, expected failures is used) - Set expected failures to 3 for g++ 2.95 - Disable wide character support for MSVC 6, using the patch I gave: #if defined(BOOST_NO_STRINGSTREAM) || \ defined(BOOST_NO_STD_WSTRING) || \ defined(BOOST_NO_STD_LOCALE) || \ defined(BOOST_NO_CWCHAR) || \ defined(BOOST_MSVC) (BOOST_MSVC = 1200) #define DISABLE_WIDE_CHAR_SUPPORT #endif - Run regression tests, and if ok, ship Boost. :) Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Win32/VC++ 6.0 lexical_cast problems
From: Beman Dawes [EMAIL PROTECTED] At 03:13 AM 3/19/2003, Terje Slettebø wrote: Ok, it seems we may have to exclude wide character support for lexical_cast on MSVC 6, to avoid breaking Date/Time. I suggest something like: #if defined(BOOST_NO_STRINGSTREAM) || \ defined(BOOST_NO_STD_WSTRING) || \ defined(BOOST_NO_STD_LOCALE) || \ defined(BOOST_NO_CWCHAR) || \ defined(BOOST_MSVC) (BOOST_MSVC = 1200) #define DISABLE_WIDE_CHAR_SUPPORT #endif OK, the full Win32 tests are posted. The date-time tests are now passing. lexical_cast_test itself is failing for VC++ 6.0. See below. I see from the CVS that the above has only been put in the header, not the test, as well. It needs to be in both. If it's just in the header, it'll try the wide character tests - on a header that has wide character conversions disabled - a recipe for disaster. ;) I've tried the above for both the header and test on MSVC 6.5, and it passes with no errors here, 82/137 tests (the rest are omitted by the above test). I've done the above changes on the lexical_cast test, and committed it to both the trunk and 1.30. The last item on my checklist posted earlier was to remove the BOOST_WORKAROUND's (which used to be for MSVC 6 and g++ 2.95), as they are not needed, and I did that, as well, before running the test. Also, since the regression tests doesn't test for g++ 2.95, on Windows, I guess there's no need to set expected failures for that compiler, after all. It works without errors on g++ 3.2. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: RC_1_30_0 still broken -- More lexical_cast
From: Beman Dawes [EMAIL PROTECTED] My patience has been exhausted. The folks that care about configuring lexical_cast for GCC 2.95.3 with the SGI library need come forward immediately and tell us how to deal with this, or 1.30.0 will ship as is. I've applied John Maddock's suggestion to my local copy of the version in CVS, and ran some tests. Preliminary results are good, and are listed at the end, here. I've tested it on Intel C++ 7.0, MSVC 6, and g++ 3.2 (MinGW). Could somebody test the attached files on g++ 2.95.x? Genny? There are also some other changes, and I list them below. The current version in the CVS is very restrictive with wide character support, meaning you can't use it with wide characters on platforms that would otherwise be able to handle it. This includes Intel C++ 7.0 (on Windows) and MSVC 6. The restriction was done to remedy the failing regression tests. However, with John's suggestion, you get a pass _and_ wide character support for those platforms that can handle it, regardless of whether they have intrinsic wchar_t. The changes are --- - Changed #include boost/type_traits.hpp to #include boost/type_traits/is_pointer.hpp, as it's the only trait used. This removes a lot of includes, and therefore dependencies with the type traits. Kevlin has agreed to this suggestion. - Removed duplicate tests. Since tests for const char * and char * for source were merged to just using string literal for source, some tests ended up as duplicates. These duplicates have been removed, bringing the number of tests down from 171 to 137. This is also agreed to by Kevlin. - With wide character support in lexical_cast enabled for MSVC 6, three tests (of 137) fail. These are omitted for that compiler version, using BOOST_WORKAROUND and BOOST_TESTED_AT. They failing tests are related to that wchar_t is a typedef for unsigned short on MSVC 6. They are: BOOST_CHECK_THROW(lexical_castwchar_t(123), boost::bad_lexical_cast); BOOST_CHECK_THROW(lexical_castwchar_t(LTest), boost::bad_lexical_cast); BOOST_CHECK_THROW(lexical_castwchar_t(std::wstring(LTest)), boost::bad_lexical_cast); Test results for the attached files Intel C++ 7.0 (strict mode, intrinsic wchar_t enabled) - 137/137 passes MSVC 6 (no intrinsic wchar_t) - 134/137 passes (3/137 omitted, the ones above, or they would fail) g++ 3.2 (MinGW) (Not proper wide character support) - 82/137 (the rest omitted by the wide character disabling) As mentioned, with the current version in CVS, Intel C++ 7.0 and MSVC 6 only gets pass on about half of total tests, since wide character support is disabled in lexical_cast for them, even though, as shown above, they handle it very well. However, not at least, it's a question of whether this version fares better on g++ 2.95.x. Regards, Terje lexical_cast_test.cpp Description: Binary data lexical_cast.hpp Description: Binary data ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: RC_1_30_0 still broken -- More lexical_cast
From: David Abrahams [EMAIL PROTECTED] Terje Slettebø [EMAIL PROTECTED] writes: - With wide character support in lexical_cast enabled for MSVC 6, three tests (of 137) fail. These are omitted for that compiler version, using BOOST_WORKAROUND and BOOST_TESTED_AT. You shouldn't be using BOOST_TESTED_AT for that compiler, since there are known newer versions BOOST_WORKAROUND(BOOST_MSVC, = 1200) is the right test. Right. Reading the docs in workaround.hpp, again, I see that now. I'll change it. (unless of course it fails for those too). No, it passes all tests on MSVC 7. Also, I've just now got a mail from Gennaro Prota. He has tested the posted version on g++ 2.95.3-10 (Cygwin). The test correctly disable wide character support, and passed except for three cases: lexical_cast_test.cpp(105): error in test_conversion_to_intr: exception boost::bad_lexical_cast is expected lexical_cast_test.cpp(111): error in test_conversion_to_intr: exception boost::bad_lexical_cast is expected lexical_cast_test.cpp(147): error in test_conversion_to_boolle: exception boost::bad_lexical_cast is expected Notice the weird misspellings in the error messages. :) Also these three tests, like MSVC 6, concerns tests where it doesn't throw when it's supposed to: BOOST_CHECK_THROW(lexical_castint( 123), boost::bad_lexical_cast); BOOST_CHECK_THROW(lexical_castint(std::string( 123)), boost::bad_lexical_cast); BOOST_CHECK_THROW(lexical_castbool(123), boost::bad_lexical_cast); If these are omitted for g++ 2.95.x, all tests pass for that compiler. However, as it compiles without errors on both MSVC 6 and g++ 2.95.x, maybe one shouldn't have any BOOST_WORKAROUND's in the test code? That will make it show up as failing on MSVC 6 and g++ 2.95.x, even though it passes almost all the enabled tests on both. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: RC_1_30_0 still broken -- More lexical_cast
From: Rozental, Gennadiy [EMAIL PROTECTED] lexical_cast_test.cpp(105): error in test_conversion_to_intr: exception boost::bad_lexical_cast is expected lexical_cast_test.cpp(111): error in test_conversion_to_intr: exception boost::bad_lexical_cast is expected lexical_cast_test.cpp(147): error in test_conversion_to_boolle: exception boost::bad_lexical_cast is expected Notice the weird misspellings in the error messages. :) What do you mean? boolle and intr? :) Could this be a problem in the unit test framework? Also these three tests, like MSVC 6, concerns tests where it doesn't throw when it's supposed to: BOOST_CHECK_THROW(lexical_castint( 123), boost::bad_lexical_cast); BOOST_CHECK_THROW(lexical_castint(std::string( 123)), boost::bad_lexical_cast); BOOST_CHECK_THROW(lexical_castbool(123), boost::bad_lexical_cast); If these are omitted for g++ 2.95.x, all tests pass for that compiler. However, as it compiles without errors on both MSVC 6 and g++ 2.95.x, maybe one shouldn't have any BOOST_WORKAROUND's in the test code? That will make it show up as failing on MSVC 6 and g++ 2.95.x, even though it passes almost all the enabled tests on both. You could use expected failures feature of Boost.Test Aha. That could be an odd test, though: Ensuring that a bug is there. :) One thing is to test for something that is supposed to fail, or throw an exception, on a conforming compiler. However, using the same mechanism to make tests pass, which are really failing, seems like a strange use of that feature. It isn't clear to me that this improves the situation over BOOST_WORKAROUND, and may instead obfuscate it, as someone reading the code might not know whether a fail-test is to test conformance, or to allow a bug. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: RC_1_30_0 still broken -- More lexical_cast
From: David Abrahams [EMAIL PROTECTED] Terje Slettebø [EMAIL PROTECTED] writes: Also these three tests, like MSVC 6, concerns tests where it doesn't throw when it's supposed to: BOOST_CHECK_THROW(lexical_castint( 123), boost::bad_lexical_cast); BOOST_CHECK_THROW(lexical_castint(std::string( 123)), boost::bad_lexical_cast); BOOST_CHECK_THROW(lexical_castbool(123), boost::bad_lexical_cast); If these are omitted for g++ 2.95.x, all tests pass for that compiler. However, as it compiles without errors on both MSVC 6 and g++ 2.95.x, maybe one shouldn't have any BOOST_WORKAROUND's in the test code? That will make it show up as failing on MSVC 6 and g++ 2.95.x, even though it passes almost all the enabled tests on both. Often the cure is to break the test into two parts, so that you can demonstrate passing the majority of tests even on broken compilers. Yeah. That's what is done with the 10 tests making up the suite - 6 for char and 4 for wide character. However, the three failing tests for each of MSVC 6 and g++ 2.95 (different ones for the two) are in the middle of some wide character tests. As Beman also points out, what is most important is that lexical_cast doesn't cause other components to fail, even if they don't use an unsupported feature. Therefore, to not mask any run-time errors on MSVC 6 and g++ 2.95, one may remove the BOOST_WORKAROUND's, since the failing tests don't appear to have much in common. Anyway, now that you've has committed it, we'll see how it goes in the regression test. At least BOOST_TESTED_AT should be taken out before the release, as you said. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: RC_1_30_0 still broken -- More lexical_cast
From: Terje Slettebø [EMAIL PROTECTED] From: Rozental, Gennadiy [EMAIL PROTECTED] If these are omitted for g++ 2.95.x, all tests pass for that compiler. However, as it compiles without errors on both MSVC 6 and g++ 2.95.x, maybe one shouldn't have any BOOST_WORKAROUND's in the test code? That will make it show up as failing on MSVC 6 and g++ 2.95.x, even though it passes almost all the enabled tests on both. You could use expected failures feature of Boost.Test Aha. That could be an odd test, though Sorry, I misunderstood. I thought it was testing for failure, when I realised that expected failures is something else, in the framework. Yes, using it could be a possibility. It seems just right for the task. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] RC_1_30_0 still broken -- More lexical_cast
From: Vladimir Prus [EMAIL PROTECTED] Terje Slettebø wrote: /home/boost/boost-regress/boost/boost/lexical_cast.hpp:173: syntax error before `;' Looking at the CVS, it appears the reason for this is that config/compiler/gcc.hpp no longer defines BOOST_NO_STRINGSTREAM, even though it should, at least for 2.95.x and below, as is shown with the above errors.. The change was done about a year ago, though, so it appears lexical_cast hasn't been working on g++ 2.95.x for a long time. I don't have much to say, but lexical_cast was broken just now. My code which was compiling a week ago and wasn't changed since now produces the same warning, after updating to RC_1_30_0. Ok. I've forwarded this to Kevlin. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: RC_1_30_0 still broken -- More lexical_cast
From: Gennaro Prota [EMAIL PROTECTED] On Mon, 17 Mar 2003 14:47:20 +0300, Vladimir Prus [EMAIL PROTECTED] wrote: Gennaro Prota wrote: Ok. I've forwarded this to Kevlin. Maybe there's more than one problem here. I see that Vladimir talks about warnings while Jeff about errors. Also maybe it helps to see the exact condition to define BOOST_NO_STRINGSTREAM in config/stdlib/sgi.hpp, with the comment therein? Just trying to lend a hand... I'm sorry, warning in my post is typo. It should have been error, and the error message is precisely the same as previously reported. I just wanted to note that lexical_cast was not broken with gcc 2.95.4 until recently. Ok. That compiler has always used the new sstream header. I think the problem is that while the old lexical_cast just used std::stringstream the new version uses the more general std::basic_stringstream. Aha. I think this may be the key. Thanks a lot. :) I was really wondering what the heck was different. :) Well, I think this reinforces the suggestion to define BOOST_NO_STRINGSTREAM for 2.95.x. Comments? Either that, or to have some way to detect where std::basic_stringstream is not supported, and turn off wide character support for that, in lexical_cast. Currently, it disables wide character support if one of the following macros are set: BOOST_NO_STRINGSTREAM BOOST_NO_STD_WSTRING BOOST_NO_INTRINSIC_WCHAR_T even though it may work partially or fully with wide characters, despite one of these set. For example, Intel C++ 7.0 on Windows has intrinsic wchar_t, and passes all the lexical_cast tests, but as the intrinsic characters have to be turned on with a switch (for compatibility with MSVC 6/7), and there appears to be no macro to detect the switch, the config sets BOOST_NO_INTRINSIC_WCHAR_T. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: io operations for stl containers?
From: Jason House [EMAIL PROTECTED] Terje Slettebø wrote: typedef std::vectorchar vector_char; vector_char values; // Fill with 'A', 'B', 'C' std::cout io::formatvector_char([, ], , , \', \') values; Output: ['A', 'B', 'C'] However, is this overkill? It seems that way, especially considering that if it was a vector of anything other than a fundamental type with std::cout already defined for it, you could add a second io::formatchar(\',\',) and it would work. Right. However, I've already implemented it, anyway, as an experimental feature. :) Besides, the two extra strings default to empty strings. Feedback is most welcome. Would possibly a function object for outputting the contained item be better? [I first thought you meant a function object for outputting the _container_, not the elements, so I wrote the following section, before realising that you had meant for the elements. I address it afterwards] I've been thinking of the same, with regard to outputting the _container_ (not the element, itself). In an earlier posting, I mentioned the possibility of using function objects, as a way to generalising the handling of output. I also mentioned having the kind of function objects like BGL, i.e. visitors. That is, rather than only overloading the operator(), it may provide several member functions, e.g.: class stream_visitor { public: void start(); void end(); void delimiter(); }; std::cout formattype(stream_visitor(...)); One could then provide a function object which does what it currently does. There are issues with this, however. I've been thinking long and hard about how to provide this functionality. The issue is that the functors has to be stored somewhere, and being accessible. With the current version, all the format objects are the same type, so you know its type when it's stored and retrieved. However, if arbitrary (generic) functors are stored, you don't know its type, when you access it, when performing output. It's similar to trying to store different types in the same std::vector. There are solutions to this, and one is to use a common interface, and all functors inherit from that interface, and override the virtual functions. That would let you store them using a pointer to the interface. However, this means the overhead of a virtual function call per call to the member functions above. This may not be that much, but it's still also the issue that generic functors can't be used - they all have to inherit from the same interface. For this reason, I found that this could be a possible later addition, if we find that the added flexibility is worth it. Also, the current syntax could still be kept as a convenience, by having an overloaded constructor taking the strings, and creating the functor. So a change may be backwards compatible. Here's a possibly mutilated example (I've never actually used function objects before): std::ostream delimitted_char(std::ostream out, char x, std::string first, std::string last); std::cout io::formatvector_char([, ], , , bind(\', 4, bind(\', 3, delimitted_char))) Yes, it's possible, but I this seems to make it more complex than simply using io::formatvector_char([, ], ,, \', \'), with the two last strings defaulted to empty strings. There's yet another alternative way this may be done, using placeholder types, i.e.: std::cout io::formatstd::vector_ (...); // Sets the format for all vectors std::cout io::format_(...); // Sets the format for all types (defaults) This would avoid hardcoding any defaults, as the user could change it. The output routines could then check the formats in the following order, e.g. for std::vectorchar: If there's a format set for std::vectorchar, use it, else if there's a format set for std::vector_ (all vectors), use it, else use format for _. Comments? I like it :) I found it quite neat, as well. :) Interestingly, one important contribution of libraries are concepts and idioms. Since _ is used as placeholder other places, making it mean any type here is reasonably intuitive, as well. Using just _ scares me a bit... It would have to have a good default :) Well, it doesn't matter that much, as all the formats are user-settable. The library may provide a setting for _, but it can easily be set to something else by the user, in the same way. In fact, the current version in the Files (the first upload), has as defaults that all strings are empty. So the defaults have existed from the beginning, anyway. After all, you have to use _some_ format to print types for which no explicit format has been set. Being able to set this default explicitly, rather than hardcoding it in the library, should therefore be a good thing. In fact, I've made an implementation of the above, yesterday, and I'll just make some more tests, and upload it to the Files section and Sandbox soon. I'll post about it here when that's done. Regards, Terje
Re: [boost] Re: io operations for stl containers?
From: Jason House [EMAIL PROTECTED] Terje Slettebø wrote: std::vectorstd::pairchar,int test; std::cout test: // Using defaults (('A',1),('B',2),('C',3)) I would suspect that chars don't get output with '' around them... Is there even a way to specify/change that? Something similar for strings (along with an escape character) would be very handy for strings. I've found a way this may be done. If you specify start element and end element strings, in addition, it may be done. Currently, it takes start sequence, end sequence, and delimiter, so this would mean two (optional) more. E.g.: typedef std::vectorchar vector_char; vector_char values; // Fill with 'A', 'B', 'C' std::cout io::formatvector_char([, ], , , \', \') values; Output: ['A', 'B', 'C'] However, is this overkill? Even if the last two are optional, it means the output routines have to output (possibly empty) strings before and after each element, in addition to the delimiter. Feedback is most welcome. There was a suggestion for allowing generic formats, though, using the same format for all instantiations of a template. The question is how to do it. The current version stores the format for each specific type, as you say. Volodya suggested a couple of ways it could be done, partial specialisation, or storing the template name in a map. There's yet another alternative way this may be done, using placeholder types, i.e.: std::cout io::formatstd::vector_ (...); // Sets the format for all vectors std::cout io::format_(...); // Sets the format for all types (defaults) This would avoid hardcoding any defaults, as the user could change it. The output routines could then check the formats in the following order, e.g. for std::vectorchar: If there's a format set for std::vectorchar, use it, else if there's a format set for std::vector_ (all vectors), use it, else use format for _. Comments? Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Possible problem in integer_traits.hpp
Hi. When trying to use integer_traits on Intel C++ 7.0, I get the following error (main line and branch): boost/integer_traits.hpp(69): error: name followed by :: must be a class or namespace name public detail::integer_traits_basebool, false, true ^ This is the compiler's way of saying that integer_traits_base is not known at this point. The structure of the header is like this: --- Start --- namespace boost { templateclass T class integer_traits : public std::numeric_limitsT // ... namespace detail { templateclass T, T min_val, T max_val class integer_traits_base // ... } // namespace detail template class integer_traitsbool : public std::numeric_limitsbool, public detail::integer_traits_basebool, false, true // Error here { }; } // namespace boost --- end --- When moving the detail namespace and integer_traits_base above the definition of integer_traits, the error disappears. Could it be that when specialising templates, it only looks up the names in the context of the primary template, not the context of the specialisation? If this is the case, could this be fixed? Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: Possible problem in integer_traits.hpp
From: Terje Slettebø [EMAIL PROTECTED] When trying to use integer_traits on Intel C++ 7.0, I get the following error (main line and branch): boost/integer_traits.hpp(69): error: name followed by :: must be a class or namespace name public detail::integer_traits_basebool, false, true ^ This is the compiler's way of saying that integer_traits_base is not known at this point. Actually, it means that detail is not known, of course. However, the next error says that integer_traits_base isn't known, either. Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] RC_1_30_0 still broken -- More lexical_cast
From: Jeff Garland [EMAIL PROTECTED] On Sun, 16 Mar 2003 17:34:18 -0500, Beman Dawes wrote I'll go over the do-list again after dinner, but it looks like almost all problems have been cleared except for this one. I don't know if the Linux results are up to date, but it appears that we have still taken a step backward with lexical cast on gcc 2.95.3. This is causing a large number date_time tests which compiled and executed correctly with the 1.29 release to fail. Without actually looking at the source it would be my guess that this is related to the fact that the 2.95.3 standard library only supported old iostreams and that somehow the lexical_cast work around got lost in the changes. This is supported by the fact that the same tests work fine with STLPort. It would be nice if this workaround could be restored before the release even if results in the 2.95.3 version having the 'string' bug. I've attached the details for reference... Jeff In file included from /home/boost/boost-regress/boost/boost/date_time/date_parsing.hpp:10, from /home/boost/boost-regress/boost/boost/date_time/gregorian/parsers.hpp:9, from /home/boost/boost-regress/boost/boost/date_time/gregorian/gregorian.hpp:17, from ../libs/date_time/test/gregorian/testdate.cpp:7: /home/boost/boost-regress/boost/boost/lexical_cast.hpp:173: syntax error before `;' Looking at the CVS, it appears the reason for this is that config/compiler/gcc.hpp no longer defines BOOST_NO_STRINGSTREAM, even though it should, at least for 2.95.x and below, as is shown with the above errors.. The change was done about a year ago, though, so it appears lexical_cast hasn't been working on g++ 2.95.x for a long time. In other words, the problem isn't in lexical_cast but in the config files. Could this be fixed? Also, shouldn't this be done in the library config, not the compiler? Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] CVS main line is all messed up
From: Victor A. Wagner, Jr. [EMAIL PROTECTED] for the past 3 hours I've been getting: ...failed updating 300 targets... ...skipped 117 targets... ...updated 8 targets... when trying to make the latest CVS update: date /T update.log time /t update.log cvs -z3 update -A -P -d update.log bjam -sTOOLS=vc7 msvc vc71 bjam.log mgrep target bjam.log this also, of course, prevents me from chasing down why I got 12 missing functions when I tried to build simple_ls.cpp. I started to take a look at what's causing the errors, but... I think I'll let the folks who checked in something they shouldn't find them. One of the errors I see insists that filesystem isn't part of namespace boost. Sorry, that may well have been me. I checked in an updated description in is_base_and_derived.hpp (OK'ed by John Maddock), and it happened to contain: B1 const volatile*/B2 const volatile* which of course the compiler interpreted as ending the comment. Therefore it gave an error on the rest. Any file including this header, or type_traits.hpp (which includes it), would therefore fail. I didn't run the tests on this one before committing, because I thought changing a comment couldn't possibly break any tests. It's fixed now. This goes for RC_1_30_0, as well. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] RC_1_30_0: lexical_cast.hpp broken under Mac OS X/gcc3.2.2
From: Beman Dawes [EMAIL PROTECTED] At 07:40 PM 3/12/2003, Ralf W. Grosse-Kunstleve wrote: The recent patch to lexical_cast.hpp causes problems under Mac OS X/gcc 3.2.2. The error message appears at the top of: http://cci.lbl.gov/boost/results/1047512220/dailylog_coral_test .../boost/boost/lexical_cast.hpp:92: `wstring' undeclared in namespace `std' This worked before: http://cci.lbl.gov/boost/results/1047490620/dailylog_coral_test (There are some other unrelated problems on this platform.) The same code also caused problems for Win32 GCC, Intel, and VC++ 6.0. I've added a quick fix for lexical_cast.hpp line 92, which cleared a lot of the problems, but not all of them. See http://boost.sourceforge.net/regression-logs/cs-win32-RC_1_30_0-diff.html AFAIK, all the new fails are because of lexical_cast.hpp use. I've already privately emailed Kevlin and Terje, but given time zone differences they may not see the messages right away. This sort of last minute snafu reinforces Ralf's earlier message; it really isn't good software development practice to sit on changes for months, and then try to get them working after a branch for release. Not to mention getting a brand new version to work right away. The new version of lexical_cast is Kevlin's own, which he recently made, not my proposition. I think his version is better, though, as it's much shorter and removes duplication. At the moment, it doesn't work well on MSVC 6, and apparently has problems on other compilers, as well. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] RC_1_30_0: lexical_cast.hpp broken under Mac OS X/gcc3.2.2
From: Terje Slettebø [EMAIL PROTECTED] The new version of lexical_cast is Kevlin's own, which he recently made, not my proposition. I think his version is better, though, as it's much shorter and removes duplication. Just to point out that it's the kind of duplication which is not easily removed; the new version works differently. The proposition used several overloaded function templates for the various special cases, whereas the new version uses a trait technique. Another advantage of the new version is that it doesn't require special workarounds for compilers lacking partial ordering of function templates, which the proposition needed. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] MPL's round lambda
A few months ago, Aleksey posted a cool way of doing lambda using function notation. I hadn't followed the thread at the time, but I read up on it recently. Like many others, I found it hard to understand how it worked, so I asked Aleksey if he could make a minimal example of it, which he did. For the benefit of anybody else interested in knowing how it works, I post the example here. I found it much easier to understand how it works, with such a minimal example. --- Start --- #include boost/mpl/quote.hpp #include boost/mpl/apply.hpp #include boost/mpl/bind.hpp #include boost/type_traits/is_same.hpp #include boost/static_assert.hpp using namespace boost::mpl; templatetypename T struct expr { typedef T type; }; templatetypename F, typename T1, typename T2 struct exprF (T1, T2) : bind2F, typename exprT1::type, typename exprT2::type {}; struct is_same : quote2boost::is_same {}; // Here: typedef applyexpris_same(_, int), int::type type; BOOST_STATIC_ASSERT(type::value); --- End --- Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: io operations for stl containers?
From: Vladimir Prus [EMAIL PROTECTED] Terje Slettebø wrote: Right. There was a suggestion for allowing generic formats, though, using the same format for all instantiations of a template. The question is how to do it. The current version stores the format for each specific type, as you say. Volodya suggested a couple of ways it could be done, partial specialisation, or storing the template name in a map. However, it could be hard to use the latter, as it could be hard to find the right type to look up, when outputting, given that you have specific types, not templates. Uhm... I meant that the right type should be explicitly written down: templateclass T ostream operator(ostream, const vectorT v) { const composite_format cf = composite_format::get(vector); } not nice, but should work. Ah, I see. That would work. If partial specialisation was used instead, you'd still need to specify the full type (even if only the generic format is set), and then, how to differentiate between specific and generic format? For example: std::cout io::set_formatstd::vectorstd::pairchar, int (...); // Uses partial specialisation of class template set_format for std::vector, setting generic format Oh... so here's the gotcha! I definitely don't like this syntax for setting format for *all* vectors. Me neither. It looks like it sets it for a specific type. Maybe, we can go even simpler way: introduce separate classes for all container kinds. BGL already has vecS, setS, and so on. The syntax for setting format will be cout io::set_formatvecS(...) ; Yeah, that could be a way. From what I have thought about it, allowing a generic type creates room for unexpected behavior in output when there are composite types containing composite types, and somewhere along the lines a *generic type* default is overridden. There might be a specific reason for a bunch of lists inside of a composite type to have a specific set of delimiters... but it probably isn't desired for the lists inside those lists to be forced into using the same delimiters. Right. Well, as mentioned, the current version uses format for specific types, so in that case, you could format each part of the nested container as you wanted, as shown with the 2D-array, which of course is an array of arrays. I think that nested containers should be handled in a more explicit way. Why can't we allow to explicitly set braces/delimiters for container at certain nesting level: cout io::set_formatvecS,1(...) would change delimiters only for top-level container. The question is that the same code can be called both from top-level and when outputting some container. It would be possible to just reset nesting level, and restore it after outputting. Yeah, like with I/O state savers. I'll do some more experimentation with this, and others are free to do the same with the code, of course. I haven't yet updated it much, from the version at Yahoo Files, since it hasn't really been certain what the design should be. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: io operations for stl containers?
From: Jason House [EMAIL PROTECTED] Terje Slettebø wrote: From: Jason House [EMAIL PROTECTED] Is there even a way to specify/change that? It isn't currently, as the fundamental types aren't handled as composite types, and therefore aren't formatted using any set format. Also, it seems it may not be possible in an obvious way. snip It appears to prefer the operator(char) stream member function, to this free function, as it isn't called when doing std::cout 'A';. :( It would be a good question to figure out why that won't work, and how to fix it... What happens, in general, if somebody want to override a stream operator to do something else? Well, outputting UDTs work fine, as you can then overload the operator. However, as it's already overloaded, as a member function of the stream class, for the built-in types, it doesn't help to overload it for them. String output probably uses character output by default... it would be very bad to have a system that made the string string (no quotes) output as 's''t''r''i''n''g' Yeah. :) basic_istream/basic_ostream have overloaded stream operators for CharType *, so they handle strings, in other words, the iostream versions of gets()/puts(). Debugger friendly manipulation would be good. I still haven't thought about how exactly outputting of an arbitrary composite variable will work in the debugger by default... I agree that having a wrapper makes it easy for the output formatting of general types, but actually being able to execute std::cout my_suspect_variable in the debugger without premeditation still poses a significant problem. Why can't bugs be predicted before you notice them? You're right, good point. Would it be possible to get some information on what kind of functions, if any, may be called in e.g. your debugger? From this, we may find what we can do. Well, I personally haven't gotten into the habit of calling functions for any debugger. Me neither. I know that gdb allows that... and last that I tried it under the cygwin port, it wasn't very stable (but I kind of expect that in a cygwin port). I do also remember hitting trouble trying to call templated types. I believe that it could make calls to templated functions, but you needed to know the real name for the function... The base function name plus extra characters in order to distinguish it... I might have gotten the real name off the call stack or something like that... Does that help to define my debugger? I would hope to make it work for as many debuggers as possible (provided that they at least support making function calls) Well, I guess that in either case, this may be handled through layering, i.e. possibly providing convenience functions which calls the overloaded stream operators, if the latter is difficult to call from a debugger. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Meta programming 'debug' mode.
From: David Abrahams [EMAIL PROTECTED] Dirk Gerrits [EMAIL PROTECTED] writes: Dirk Gerrits wrote: I'd say something like: #ifdef STATIC_NDEBUG #define BOOST_STATIC_ASSERT2(e) BOOST_STATIC_ASSERT(e) #else #define BOOST_STATIC_ASSERT2(e) (void(e)) #endif Analogous to cassert. Argh, the if and else branches should be reversed of course. You've gotta love negative logic. ;) I like the basic idea, but are you sure it will work in all the contexts where BOOST_STATIC_ASSERT works? I think BOOST_STATIC_ASSERT functions like a declaration, syntactically. Then how about simply: #ifndef STATIC_NDEBUG #define BOOST_STATIC_ASSERT2(e) BOOST_STATIC_ASSERT(e) #else #define BOOST_STATIC_ASSERT2(e) // Possibly void(0) here, like assert #endif By the way, what's the point with void(0), compared to nothing? Both void(0); and ; are valid statements. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Meta programming 'debug' mode.
From: David Abrahams [EMAIL PROTECTED] Terje Slettebø [EMAIL PROTECTED] writes: From: David Abrahams [EMAIL PROTECTED] I like the basic idea, but are you sure it will work in all the contexts where BOOST_STATIC_ASSERT works? I think BOOST_STATIC_ASSERT functions like a declaration, syntactically. Then how about simply: #ifndef STATIC_NDEBUG #define BOOST_STATIC_ASSERT2(e) BOOST_STATIC_ASSERT(e) #else #define BOOST_STATIC_ASSERT2(e) // Possibly void(0) here, like assert #endif By the way, what's the point with void(0), compared to nothing? Both void(0); and ; are valid statements. is ; legal where a declaration is expected? class X { ; // legal? }; Apparently not. void(0) doesn't work, either, so we need something else to let it pass where declarations are allowed, as you say. It should be quite easy. Of course, if BOOST_STATIC_ASSERT didn't require a ; when used, one could get away with defining it to nothing, as above, when STATIC_NDEBUG is not set. Defining it to BOOST_STATIC_ASSERT(true), as Jaap suggests in a recent posting is also an option, if much of the processing is done in the parameter passed, rather than in the macro itself (which is typically a typedef or enum), which is likely. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Proposal: static_string library
From: Beman Dawes [EMAIL PROTECTED] At 05:58 PM 3/5/2003, Robert Klarer wrote: The purpose of the static_string library is to offer an alternative to string literals and the standard type const std::string. A static_string uses no dynamically allocated memory, and is more efficient at execution time than either string literals or basic_strings. Yes, agreed. That would be useful. IIRC, the C++ committee's performance working groups has talked about such a string in the past. There are questions that come to mind: * Can you come up with a small, workable language extension that eases those problems? Josuttis/Vandevoorde mentions being able to pass string literals as template parameters as a possible future extension. That would be a clean way to handle it. Possibly could there also be a general solution regarding passing compound values. At the moment, values of class type can't be passed as template parameters. * Can you come up with an alternate design that gives up a tiny bit of efficiency (one pointer indirection perhaps) but then allows reasonable construction and internationalization? If run-time computation is ok, and that one only wants to avoid dynamical allocation, then one might do something like I used in another posting in this thread: templateclass CharType, int N class fixed_size_string; templateclass CharType, int N1, int N2 fixed_size_stringCharType, N1+N2 operator+(const fixed_size_stringCharType, N1 s1, const fixed_size_stringCharType, N2 s2); etc. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Proposal: static_string library
From: Robert Klarer [EMAIL PROTECTED] Terje Slettebø wrote: If run-time computation is ok, and that one only wants to avoid dynamical allocation, then one might do something like I used in another posting in this thread: templateclass CharType, int N class fixed_size_string; templateclass CharType, int N1, int N2 fixed_size_stringCharType, N1+N2 operator+(const fixed_size_stringCharType, N1 s1, const fixed_size_stringCharType, N2 s2); An implementation of basic_string that uses the small string optimization already implements something very close to this. We don't need to specify an entirely new kind of string to benefit from this technique. True, for small strings. However, that particular technique doesn't work for larger strings. I just mentioned the above, since it appeared that much of the interest for static_string came from the lack of dynamical allocation, so I wanted to point out that you don't need compile-time computation for that. Naturally, a compile-time string would be much less expensive to copy around, though, since it's all encoded in the type, and there would be no run-time cost for many operations. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: resource manager naming
From: Joel de Guzman [EMAIL PROTECTED] Terje Slettebø wrote: From: Joel de Guzman [EMAIL PROTECTED] Dave Gomboc wrote: 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. 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. 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. managedlock managedwidget,shared // Smart pointer resourcelock resourcewidget,shared // Smart pointer When the template is in use (unless it uses a default template argument), the template argument will be part of the signature, and therefore show what is managed. Therefore, I think managed makes sense, too. IIUC, your argument can be used for e.g. std::pair, too. std::pair of what? Answer: That depends on the template arguments. No, a pair is always a pair regardless of what the composed types are: pairT1, T2 // a pair comprised of T1 and T2 You don't need to know the template parameters to know that it is a *pair*. That's the big difference. The template parameter is an abstract concept. Detached from the parameters, it is still a pair. The same does not hold for managedT. What is managed? It is not even a noun without the qualifiers. Good point, it's not a noun. resource_manager, manager or resource are nouns, so they may be better. managedwidget // does this *manage* the actual rendering into the window? Gotcha! No it doesn't! To adjust it so it becomes a noun: managerwidget Manager of widget. It's kind of implied that what is managed is the resource itself, even though resource doesn't say anywhere. This is similar to that you think it's implied that resourcewidget means it manages the resource, even though manage doesn't say anywhere. By the way, I used widget in the meaning of anything, as it's used some places (like foo and bar). resource_manager starts to look attractive, again. ;) Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: resource manager naming
From: Joel de Guzman [EMAIL PROTECTED] managerwidget Manager of widget. It's kind of implied that what is managed is the resource itself, even though resource doesn't say anywhere. This is similar to that you think it's implied that resourcewidget means it manages the resource, even though manage doesn't say anywhere. Look at it this way. Which noun best describes the following: 1) You acquire it 2) You release it 3) You transfer its ownership A) manager B) resource C) managed Resource. resource_manager starts to look attractive, again. ;) Perhaps. But there's a *better* and *shorter* alternative that very well fits the description. We can say: linear_list_of_items_managerint, YUCK! Instead, we say listint. The management *is* implicit! Right. Also, in general, I would say that any name suffixed by _manager are best used for classes that manage *many* things simultaneously, NOT JUST ONE. Take a window_manager for example. It is something that manages the operations of many windows. In the Macintosh, for example, the resource manager manages all* the resources in an application. Right again. Ok, I agree that resource may be a useful name for it, with implied management, like e.g. std::list, as you say. Anyway, as Dave A points out in another posting, and which was also the topic of an earlier of mine, the usefulness of the concept in the first place hasn't been demonstrated. The reason I jumped in on the naming discussion, is that I thought managed, or rather manager could be a possibility, as well. I thought the same that Dave said, that resourcewidget doesn't really tell me much, as it seems it's saying the same thing twice; widged is a resource. Also, as Gennadiy points out, list is a list, while resource is not a resource; it's a manager of a resource. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: resource manager naming
From: Joel de Guzman [EMAIL PROTECTED] Dave Gomboc wrote: 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. 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. 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. managedlock managedwidget,shared // Smart pointer resourcelock resourcewidget,shared // Smart pointer When the template is in use (unless it uses a default template argument), the template argument will be part of the signature, and therefore show what is managed. Therefore, I think managed makes sense, too. IIUC, your argument can be used for e.g. std::pair, too. std::pair of what? Answer: That depends on the template arguments. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: smart_ptr vs smart_resource
From: Phil Nash [EMAIL PROTECTED] [Rob Stewart] There can still be a smart_ptr class, even if there's a smart_resource class. Both may be separate manifestations, possibly sharing some implementation details, of a SmartResource concept. Equally plausible, smart_ptr could be implemented in terms of smart_resource somehow (derivation, aggregation, whatever). In the Policy Based case smart_ptr would just be smart_resource (or resource_manager) with certain policies (or policy sets). Template typedefs would help a lot here. I also think this makes sense. However, I'm wondering how much commonality there is in such a broader concept. This is kind of making a library implementation of the RAII idiom, and we have that already, in the form of constructors/destructors. Looking at my own code, to find such use, I've found a few places, such as the following: // Direct3D class vertex_buffer_lock { public: vertex_buffer_lock(vertex_buffer_base vb,vertex *vertices,const uint num_vertices,const uint flags =0) : vertex_buffer(vb) { vertex_buffer.lock(vertices,num_vertices,flags); } ~vertex_buffer_lock() { vertex_buffer.unlock(); } private: vertex_buffer_base vertex_buffer; }; Would a resource_manager provide anything additional, here? I'd still need to write a policy which would be really the same as the above. Also, how would a resource_manager handle all the different constructors? Perhaps using overloaded, templated constructors. That wouldn't cater for default arguments, like the above, though. Also, if you use T for the constructor arguments, you risk getting reference to reference problems. In short, I think it could be good to find a few use-cases, such as the above, and try to implement it using a generic resource_manager. That would show if the concept adds anything, or not. In other words, let the rubber meet the road. :) Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: smart_ptr vs smart_resource
From: Phil Nash [EMAIL PROTECTED] [Terje Slettebø] I also think this makes sense. However, I'm wondering how much commonality there is in such a broader concept. This is kind of making a library implementation of the RAII idiom, and we have that already, in the form of constructors/destructors. Yes.. it's ctors and dtors that have really brought the RAII idiom into the language - and of course is very important in the resource_manager concept. Now, to your example: Looking at my own code, to find such use, I've found a few places, such as the following: // Direct3D class vertex_buffer_lock { public: vertex_buffer_lock(vertex_buffer_base vb,vertex *vertices,const uint num_vertices,const uint flags =0) : vertex_buffer(vb) { vertex_buffer.lock(vertices,num_vertices,flags); } ~vertex_buffer_lock() { vertex_buffer.unlock(); } private: vertex_buffer_base vertex_buffer; }; Would a resource_manager provide anything additional, here? I'd still need to write a policy which would be really the same as the above. Also, how would a resource_manager handle all the different constructors? Well, as you so rightly point out, full RAII wrappers for such resources would require you to write most, if not all, of the code yourself - although I wonder if a resource_manager framework would still make getting them right easier... (I'd need to give that more thought). One advantage would be that the release mechanism would be independant of any other aspects of the wrapper - and so could be ensured to be more robust in the face of exceptions without you having to worry about it directly. I'm not sure what you mean, here. In the above example, the destructor takes care of the release. Also, as it only manages _one_ resource (the lock), it is exception safe (vertex_buffer (which inherits from vertex_buffer_base) is just a wrapper class for D3D's VertexBuffer interface). Speaking of that, I also have a COM smart pointer class there. That could definitely make use of a smart pointer/resource manager, as it could then make use of the pointer semantics, etc. Even as a policy, you'd still have to make sure that your acquire/release functions are exception safe, just like the constructor/destructor above. So I don't see how a resource_manager class would add anything in this respect. On a related note the various copying policies would be taken care of for you. If you want to make your resource copyable, or shareable or COWable or whatever - it just takes a change of policy to give you the feature (if appropriate). Which reminds me, the class above actually was defined as: class vertex_buffer_lock : private boost::noncopyable Yes, if you could make the copying/ownership policy independent of what is owned, for example by making it call acquire/release functions on another policy, which implements the code in the constructor/destructor above. Also, if you use T for the constructor arguments, you risk getting reference to reference problems. I believe this can be fixed with type_traits. Come to think of it, it may not be a problem, after all. Consider this simple test program: class test { public: test(int ) {} }; templateclass T class resource_manager { public: resource_manager() : resource() {} templateclass T1 resource_manager(T1 t1) : resource(t1) {} private: T resource; }; int main() { int i=1; resource_managertest testA(i); int ir=i; resource_managertest testB(ir); } This compiles and runs without any problems. In short, I think it could be good to find a few use-cases, such as the above, and try to implement it using a generic resource_manager. That would show if the concept adds anything, or not. In other words, let the rubber meet the road. :) Yes.. some examples have already been given, including managing file handles (although in practice we already have an RAII file object in the form of fstream), mutex locks (which saw the resurrection of this thread recently), and all sorts of OS handles and other resources that are usually presented as a C interface. Yes, I know there's a lot of use cases. My emphasis was on _implementing_ them. :) That way, one get to see if they may be handled uniformly by such a framework. Several times now I have had to write my own wrappers for the MS Inet HTTP interface, purely to provide the RAII management of them. Each time I have thought, I really should write that general resource manager code. And really I should - even though it probably wouldn't be the implementation that was accepted into boost (if ever). It would definitely be interesting in looking into this. I'm not saying it won't be useful. What I'm saying is show me. :) Thanks for your comments Terje, You too. :) Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: io operations for stl containers?
From: Jason House [EMAIL PROTECTED] std::vectorstd::pairchar,int test; std::cout test: // Using defaults (('A',1),('B',2),('C',3)) I would suspect that chars don't get output with '' around them... Right. I was just thinking C++ code, here. :) Is there even a way to specify/change that? It isn't currently, as the fundamental types aren't handled as composite types, and therefore aren't formatted using any set format. Also, it seems it may not be possible in an obvious way. For example, the following addition to the header doesn't work: templateclass CharType,class CharTraits std::basic_ostreamCharType,CharTraits operator (std::basic_ostreamCharType,CharTraits stream,char value) { typedef basic_composite_formatCharType,char format_type; const format_type format=format_type::format(stream); stream format.start; stream.operator(value); stream format.end; return stream; } It appears to prefer the operator(char) stream member function, to this free function, as it isn't called when doing std::cout 'A';. In this case, it's not possible to set the format for each type separately. Maybe it could be good to keep that feature of the current composite operators, as well, something like: typedef std::pairchar,int map; typedef std::vectorMap map_list; map_list test; std::cout io::set_delimitermap(\n) test; Output: (('A',1) ('B',2) (C,3)) so basically, you would like to combine tuple-like output specification (ie for all tuples) and type specific such as composite_format? I was thinking of that, yes. As well as a default, possibly user-settable, for any type not having set an explicit format. This would let you control the formatting in layers, so to speak: - You could use/set the default format for all types. - You could use/set the format for all instantiations of a given template, e.g. std::vector. - You could use/set the format for specific types. If possible, it would apply the most specific format set (i.e. it would prefer 3 to 2, to 1). Another thing is if this layering is practically possible. :) We get into this below here. templateclass CharType, class CharTrait, class T1, class T2 inline std::basic_ostreamCharType, CharTrait operator(std::basic_ostreamCharType, CharTrait o, const consT1, T2 t) As you say, this may be a problem to call from a debugger, unless it supports calling function templates. If one need to call it from a debugger, one could always wrap the code in a function. :( Debugger friendly manipulation would be good. I still haven't thought about how exactly outputting of an arbitrary composite variable will work in the debugger by default... I agree that having a wrapper makes it easy for the output formatting of general types, but actually being able to execute std::cout my_suspect_variable in the debugger without premeditation still poses a significant problem. Why can't bugs be predicted before you notice them? You're right, good point. Would it be possible to get some information on what kind of functions, if any, may be called in e.g. your debugger? From this, we may find what we can do. There was a suggestion for allowing generic formats, though, using the same format for all instantiations of a template. The question is how to do it. The current version stores the format for each specific type, as you say. Volodya suggested a couple of ways it could be done, partial specialisation, or storing the template name in a map. However, it could be hard to use the latter, as it could be hard to find the right type to look up, when outputting, given that you have specific types, not templates. Overloading of class templates might have helped, here. E.g.: std::cout io::set_formatstd::vectorstd::pairchar,int (...); // Set specific format (io::format is a class template) std::cout io::set_formatstd::vector(...); // Set generic format for std::vector (io::format overloaded with a version taking template template parameter, and specialised for std::vector) Well, std::vector would cause trouble because the std::vector requires extra arguments... I don't think you could get that to compile. True, it doesn't, because it's not currently legal C++. :) That's what I meant with Overloading of class templates might have helped, here. It's not possible to overload class templates. However, this is mentioned as a possible extension, in the Future Directions chapter of Josuttis/Vandevoorde. Together with partial specialisation of function templates, etc. Using a string might work... but using it as a template argument would probably cause trouble. Yes, you can't use string literals as template parameters. I don't know if there is a way to use partial template specialization. There is, as I showed in the following example. However, it means you have to provide the parameters to the template, as well (e.g. std::vector), even if you just mean to
Re: [boost] Re: io operations for stl containers?
From: Vladimir Prus [EMAIL PROTECTED] Sorry for having taken so long to respond to these messages. I felt a need for a break, to consider how it might be done. In a way, something good came from it, as well: I've recently looked at Boost.Tuple, and I see that they have I/O operators defined (in tuple_io.hpp). To quote from the docs: --- Start quote --- Streaming The global operator has been overloaded for std::ostream such that tuples are output by recursively calling operator for each element. Analogously, the global operator has been overloaded to extract tuples from std::istream by recursively calling operator for each element. The default delimiter between the elements is space, and the tuple is enclosed in parenthesis. For Example: tuplefloat, int, std::string a(1.0f, 2, std::string(Howdy folks!); cout a; outputs the tuple as: (1.0 2 Howdy folks!) The library defines three manipulators for changing the default behavior: - set_open(char) defines the character that is output before the first element. - set_close(char) defines the character that is output after the last element. - set_delimiter(char) defines the delimiter character between elements. Note, that these manipulators are defined in the tuples subnamespace. For example: cout tuples::set_open('[') tuples::set_close(']') tuples::set_delimiter(',') a; outputs the same tuple a as: [1.0,2,Howdy folks!] The same manipulators work with operator and istream as well. Suppose the cin stream contains the following data: (1 2 3) [4:5] The code: tupleint, int, int i; tupleint, int j; cin i; cin tuples::set_open('[') tuples::set_close(']') tules::set_delimiter(':'); cin j; reads the data into the tuples i and j. Note that extracting tuples with std::string or C-style string elements does not generally work, since the streamed tuple representation may not be unambiguously parseable. --- End quote --- Maybe these routines could be generalised, and used for any composite/compound type, including tuples? If it's good enough for the standard library (given that Boost.Tuple have been accepted in the Library TR), it may be good enough for the other types, as well. :) Terje Slettebø wrote: From: Jason House [EMAIL PROTECTED] Terje Slettebø wrote: Regarding this project. I've got doubts about the viability of it. Well, I'm glad you've given it a greater level of thought. I really like the idea of the composite_format, and probably should try to do the same :) Thanks for your feedback. I like the idea, as well. We have I/O for single objects, but no specific way for composites. The question is if we should have that. :) Maybe the reason we don't have it, yet, is that it may be hard to come up with a system that is general enough, yet easy to use. Most likely I don't need to say it again, but having fixed i/o operators with fixed output format is better that have nothing. As you've noticed, my original motivation was debugging output, and I still find this important enough. You're right. That was probably the motivation for Boost.Tuple's stream operators, as well: A minimal, easy to use interface, with sensible defaults. One thing is to create something useful. Another thing is to create something useful as a _library_ component. As has been noted regarding application and library development, application development and library development is typically quite different. With an application, you typically have quite specific requirements. With a library component, however, it's about anticipating future use. Or making something general enough to be useful as a library component. But you don't write library, put a seal on it, and stop. There's nothing wrong with making it more flexible when users demand it. As it stands, only few persons are interested in the simplest facilities. Is it worth spending time on completely generic/flexible solution if no-one has expressed desire for it? Right, again. What do you think of the Boost.Tuple approach? In your original posting, you said: I was thinking about boost/io/vector.hpp boost/io/set.hpp and so on. There are basically two approaches: 1. Operators use fixed format: bracked list with commas between values for vector, for example. 2. Manipulators are provided to set brackets and separators. I had implemented the second approach some time ago, but it turned out that was overkill. So, 1) looks better now. Boost.Tuple uses the second approach, and it seems it can be useful to provide the possibility to change the separators. It's still a quite simple solution. Very true, but some libraries are useful simply because they're simply code that people would write themselves over and over... only done in a better way. +1. I've tried to make the same point above. You both succeeded. :) written default for this makes it all worth it for me! The for loop has no chance of being evaluated properly in a debugger
Re: [boost] Re: io operations for stl containers?
From: Jason House [EMAIL PROTECTED] Terje Slettebø wrote: From: Vladimir Prus [EMAIL PROTECTED] Sorry for having taken so long to respond to these messages. I felt a need for a break, to consider how it might be done. I was wondering about this line of discussion earlier today... wondering if it died on the vine or not. I'm glad to see that it hasn't Right. After I had sent it, I found that break wasn't quite right. I meant that I had been considering it, including what had been said in the thread. Specifically, like I said in an earlier posting, I was wondering if there was enough commonality to warrant a library implementation. Then I happened to look more into Boost.Tuple, and realised that even a simple solution could be useful, as you and others have pointed out, as well. In a way, something good came from it, as well: I've recently looked at Boost.Tuple, and I see that they have I/O operators defined (in tuple_io.hpp). Well, it definitely seems like the tuples were thinking along similar lines with a start, middle, and stop delimiters. The documentation brings up a point about parseability of data streams. It doesn't quite make sense to me that there should be restriction to a single character in order to to make things uniquely parseable. If it's a fixed sequence of characters, I don't see how that makes it any significantly less parseable... Maybe I'm missing something? The docs says: Note that extracting tuples with std::string or C-style string elements does not generally work, since the streamed tuple representation may not be unambiguously parseable. It's not about the delimiters. which it seems you mean, but about the tuple elements. Consider: tuplestd::string,int test; stream test; // Stream contains a string, with comma, 123 Here, it can't know that the first comma is part of the string, and not meant to separate elements. Not to mention that it would stop after a, due to the space character. I agree that it should be possible to have multi-character delimiters, without creating parsing problems. It could be an idea to keep this, as it may make for more flexible output. Even single-character delimiters is quite flexible, as you can even get each element on its own line, by using '\n' as the element separator. To look again at one example of how the tuple way might work: std::vectorstd::pairchar,int test; std::cout test: // Using defaults (('A',1),('B',2),('C',3)) In this case, it's not possible to set the format for each type separately. Maybe it could be good to keep that feature of the current composite operators, as well, something like: typedef std::pairchar,int map; typedef std::vectorMap map_list; map_list test; std::cout io::set_delimitermap(\n) test; Output: (('A',1) ('B',2) (C,3)) Or, generating program-code like listing: std::cout io::set_formatmap_list({\n,}\n,,\n) io::set_formatmap({,},, } test; { {'A', 1}, {'B', 2}, {'C', 3} } Maybe also: std::cout io::set_formatmap_list((\n,)\n,\n) io::set_indent(2) test; ( ('A',1) ('B',2) ('C',3) ) You might also have a non-template overload of the manipulators, which sets the delimiters for all types, as done in tuples. This may also have a positive effect on a serialisation library: The standard types will have default stream operators. It does enable defaults and allows a way to customize each spacer individually, which is a good addition. I think the ability to set all 3 also is a must-have :) Yeah, I think that's useful, too. :) The tuple functions, as provided should be extremely easy to call from a debugger since there is no templating going on. Actually, there is. They are defined in tuple_io.hpp as: templateclass CharType, class CharTrait, class T1, class T2 inline std::basic_ostreamCharType, CharTrait operator(std::basic_ostreamCharType, CharTrait o, const consT1, T2 t) As you say, this may be a problem to call from a debugger, unless it supports calling function templates. If one need to call it from a debugger, one could always wrap the code in a function. I think that if when composite_format matures, there should be a way to add non-templated calls to change defaults. maybe: namespace composite_format{ namespace tuple{ ... set_open(char x){ return composite_format_opentuple(x); } } } The manipulators might also be handled the same way as above, wrapping them in the function. Actually that example doesn't quite work because tuple is not well defined. The previous discussion of composite_fromat (or at least the code presented) did not allow for a generic class of types, and only provided functionality for a very specific type. Right. There was a suggestion for allowing generic formats, though, using the same format for all instantiations of a template. The question is how to do it. The current version stores the format for each specific type, as you say. Volodya suggested a couple of ways
Re: [boost] Re: io operations for stl containers?
From: Jason House [EMAIL PROTECTED] Jason House wrote: Terje Slettebø wrote: Another possibility might be to have a sentry object, doing automatic state saving and restoring in the constructor and destructor. In fact, there are already such classes in Boost: Daryle Walker's I/O state savers, which fits this situation like a glove. I think that I like your solution better :) putting it constructor/deconstructor does seem better. I can't even argue that it's more typing for multi-line expressions... Well, I know at least have more fuel to think about... First of all, does your constructor take the stream as an argument? It would have to in order to do state saving in the constructor... If so, that at least makes prevents the following case (that probably needs special handling) { io_format var1(...); std::cout var1 stuff; std::cerr var1 more_stuff; } My understanding is that the constructor would not perform state saving, but that it is the call to that has to perform the locking. Right. In the example I had, performed the saving. In that case, it would have to check a save-flag in the destructor. One could also pass the stream to it in the constructor, as you say. So what happens when multiple streams are used? That's no problem. The format is set for a specific stream (each stream has its own iword/pword for the type to be output). So for the free-standing saver, it would need to take the stream as a constructor argument. what happens when you have 2 or more io_formats in the same function used on the same stream? example { io_formatT var1(...), var2(...); std:: cout var1 stuff1; std::cout var2 stuff2; std::cout var1 stuff3; std::cout var2 stuff4; std::cout io_formatT(...) stuff5; } /* deconstruct all 3 io_formatT's ... not necessarilly in the right order! */ This should work just fine. When the manipulator is used, it sets the format given by it. When a new manipulator is used, it changes the format to the new one. Also, the language ensures that the objects are destroyed in the reverse order of creation, so they will all be deleted after the last statement above. Here, var1, var2, and the unnamed class from the last line in the function are all being deconstructed at the same time. Some caution needs to occur here. Well, as this version of them just sets the format, and doesn't do anything in the destructor, their order of destruction doesn't matter for the output. Is that what the state-saver class you referred to does already? That one does the restoring in the destructor. If we used the combined setter/saver/restorer I mentioned in the posting I just sent, them only the first of the above formats (var1), needed to save the format, to ensure that the format wasn't changed by the output statements. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: io operations for stl containers?
From: Paul A. Bristow [EMAIL PROTECTED] This looks really neat - and potentially very useful. Thanks. :) Sadly, array is one of the most interesting cases - so I'm sure I won't be the only one 'watching this space'. I've looked more into it, and it seems this is a problem not just for MSVC, but a problem with the current way of doing it, overloading operator for T()[N], sinch string literals has the type const char[N], as well... With overloaded operator for T()[N], and using std::cout Test , g++ gives an ambiguity error, while on Intel C++, it selects the composite overload, resulting in funny output: It tries to output the null-terminator, as well, not knowing that for character strings, this is a string terminator. Besides, it can't really know if the user meant to send a character string, or a non-null-terminated character array. It seems the differences is down to subtle implementation differences. Here are the results, when an overloaded operator with T[N] is defined (S - string-literal operator, C - composite operator (T()[N]), A - ambiguous): const int array[3]; std::cout array; MSVC 7 - C Intel C++ 7 - C g++ 3.2 - C const char array[3]; std::cout array; MSVC 7- A (S or C) Intel C++ 7 - C g++ 3.2 - C std::cout Test; MSVC 7 - A (S or C) Intel 7 - C g++ 3.2 - A (S or C) In order to allow string literals to be used, without ambiguity or the wrong operator being selected, it seems that one needs to overload operator on something else than T()[N]. T[N] isn't an option, either, as this is the same as overloading on T *, which means it isn't able to deduce N. This quandary may be solved by wrapping arrays in an object, which then is passed to the overloaded operator. For example: std::cout wrap_array(array); Comments/suggestions? PS composite_format is a bit long, but I can't suggest better. I know, but I don't know any better, either. I see that Volodya suggests composite_io in another posting. That's another possibility. Anyway, I guess what's most important is to get the functionality in place. A default system may make it easier, as well. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: io operations for stl containers?
From: Terje Slettebø [EMAIL PROTECTED] const int array[3]; std::cout array; MSVC 7 - C Intel C++ 7 - C g++ 3.2 - C const char array[3]; std::cout array; MSVC 7- A (S or C) Intel C++ 7 - C g++ 3.2 - C std::cout Test; MSVC 7 - A (S or C) Intel 7 - C g++ 3.2 - A (S or C) In order to allow string literals to be used, without ambiguity or the wrong operator being selected, it seems that one needs to overload operator on something else than T()[N]. T[N] isn't an option, either, as this is the same as overloading on T *, which means it isn't able to deduce N. This quandary may be solved by wrapping arrays in an object, which then is passed to the overloaded operator. For example: std::cout wrap_array(array); I found that boost::ref works for this, as well, so you may use: char array[3[[3][3]; std::cout array; // Overloading for this gives wrong handling of string literals, on all compilers. std::cout cref(array); // Ok For example: void array3D_test() { char boards[3][3][3]= { { {'X','O','X'}, {'O','X','O'}, {'X','O','X'} }, { {'X','X','X'}, {'X','O','X'}, {'X','X','X'} }, { {'O','X','O'}, {'X','X','X'}, {'O','X','O'} } }; std::cout composite_formatboost::reference_wrapperchar ()[3] (\n|,|\n,|) composite_formatboost::reference_wrapperchar ()[3][3] (---,---,---) composite_formatboost::reference_wrapperchar ()[3][3][3] (--- Boards ---\n\n,\n\n--- Boards ---,\n\n) boost::cref(boards) '\n'; } Output: --- Boards --- --- |X|O|X| --- |O|X|O| --- |X|O|X| --- --- |X|X|X| --- |X|O|X| --- |X|X|X| --- --- |O|X|O| --- |X|X|X| --- |O|X|O| --- --- Boards --- I'll work on a version that works with this. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: io operations for stl containers?
From: Jason House [EMAIL PROTECTED] Terje Slettebø wrote: It should handle maps and pairs reasonably well. I think that I have the same complaints about this as io_manip The saving of information to the stream means that you can affect all future output... For instance, if you have a type mapcustom_object, liststring and custom_object's stream output uses io_formatliststring , then you are going to run into trouble if it wants a different formatting. Right. That's a consequence of this. As you say too, I don't know any obvious alternatives, though. I thought of one thing that might work reasonably well. How about making ++io_format T save the current format in a stack. and having io_format T-- restore the previously queuued format I've thought of the exact same thing. :) Not how the syntax for it would be, but when I was thinking of this, it suddenly occurred to me: State savers! This essentially creates a scope in the state space. As you say, you may then read the currently set format, and restore it afterwards. The restoration is important, and there are issues such as exception safety. so, then something like std::cout ++io_formatchar ()[3](\n|,|\n,|)-- ++io_formatchar ()[3][3](---,---,---)-- board '\n'; would save and restore the formating for char()[3][3] and char()[3] and never stomp on anything else. In this case, it seems it saves and restores the format, before the format gets a chance to be used. In other words, the scope only covers the state saving, not the output. Another possibility might be to have a sentry object, doing automatic state saving and restoring in the constructor and destructor. In fact, there are already such classes in Boost: Daryle Walker's I/O state savers, which fits this situation like a glove. In your original posting, you had this example: For instance, if you have a type mapcustom_object, liststring and custom_object's stream output uses io_formatliststring , then you are going to run into trouble if it wants a different formatting. Such a custom object may then have something like the following in its stream output: boost::io::ios_pword_saver(stream,index); // Set stream state, and do output. That's all. :) This also ensures that the state is restored properly, even in the presence of exceptions, something the ++/-- way won't do. Of course, this requires the pword-index, so one might make the interface more user friendly, and fit the rest, for example by making the state saver a manipulator, itself. As I understand, the lifetime of a temporary object extends until the end of the full expression it's used in, so the following should be well-defined: std::vectorint v; std::cout composite_savevectorint () composite_format(...) v '\n'; This saves the format at the start, and restores it at the end. An alternative is a named temporary, such as: composite_savevectorint sentry(stream); // Set format and do output The net effect is that you can optionally add the extra few characters and prevent stomping on other code that is displaying your class. Exactly. :) I feel fortunate to have so many competent people around me. This certainly gives library building a boost. :) Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] io operations for stl containers?
From: Vladimir Prus [EMAIL PROTECTED] Terje Slettebø wrote: From: Vladimir Prus [EMAIL PROTECTED] after having to output std::vector to stream again and again using custom solution, I started to wonder why we don't have a solution in boost. Does it makes sense to include operators for vectors, sets, etc? and so on. There are basically two approaches: 1. Operators use fixed format: bracked list with commas between values for vector, for example. 2. Manipulators are provided to set brackets and separators. I had implemented the second approach some time ago, but it turned out that was overkill. So, 1) looks better now. If this is done as a library, then I think it's best not to have hard-coded brackets and separators. One might use an xalloc() value for each type to output. For example something like: You see, that's what I have implemented back in 2001. You could change braces/separator for each stl container, and it used xalloc()/pword(). There's one problem though: I don't remember the syntax of brace changing, just because I used it a couple of times long ago and then stopped. Probably, the scope should be more clearly defined: Edward Diener wrote: Al Stevens who writes the C++ column for Doctor Dobbs Journal put out a persistent template library for C++ containers some time back. It is probably on the DDJ web site, although I haven't looked there recently. You might want to check that out and see what he did. I will readily admit I have not had the need to persist container data in my daily programming but I can understand others having that need. Rozental, Gennadiy wrote: I do not see a way how you could implement solution with better flexibility/conciseness ratio than copy+ostream_iterator one. I'm not much interested in persistence (after all, I hope that Robert's library will take care of that). Likewise, I never needed arbitrary delimiters, etc. But while developing an algorithm for finding k shortest paths in a graph, I need to output each path, and have no easy standard way. One might call this output operators are mostly debugging help, but why not have standard debugging help? std::cout boost::io_formatMap(,, [, ]) boost::io_formatMapList(,,\n) list '\n'; This might print: [1, a] [2, b] [3, c] This example should one case where manipulators are desirable: vector vectorint v; cout v ; Here, each nested vector better go on a separate line. I suggest: cout multiline v; where multiline manipulator causes each element of the next output container to go on separate line. The above io_format's are intended to be manipulators. You could get this manipulator with: io_formatvectorint (\n,,) multiline; You could also make it so that this manipulator set the format for any container, but in cases where you have arbitrary deep nesting of containers (like in Peter Dimov's posting), it may be better to set the format on a per-type basis. Incidentally, I've just made a version that does exactly this. :) I've attached it, including a test, with this posting. It's used like this: int main() { typedef std::pairint,char Map; typedef std::vectorMap MapList; MapList list; list.push_back(std::make_pair(1,'A')); list.push_back(std::make_pair(2,'B')); list.push_back(std::make_pair(3,'C')); std::cout io_formatMap([,],,) io_formatMapList(,,\n) list '\n'; } Output: [1,A] [2,B] [3,C] It's a little rough, as it doesn't do proper stream error handling, or ownership management for the pword object, but it works. Feedback is welcome. Regards, Terje Test.cpp Description: Binary data ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: io operations for stl containers?
From: Paul A. Bristow [EMAIL PROTECTED] This looks most useful - potentionally :-( Alas the two files, test and composite_stream_operators.hpp http://groups.yahoo.com/group/boost/files/composite_stream_operators/). won't compile on MSVC 7.0. test_composite_format.cpp test_composite_format.cpp(43) : error C2679: binary '' : no operator found which takes a right-hand operand of type 'composite_formatT' (or there is no acceptable conversion) with [ T=char ()[3] ] and similarly for T=Map Is the cause/workaround obvious? Looking at the error messages, and from what I've heard, it may be that it has problems with template friends (which is what the operator is). If that's the case, the workaround should be very easy - making it a free-function template. I did that, now, and it works. :) At least the vector_pair_test(). The array2D_test() uses a little fancy code, such as passing the type reference to array as a template parameter, and it seems MSVC 7.0 has some problems with this. Anyway, that was just to demonstrate usage with built-in types, as well, such as arrays. I'll look into it. There wasn't really any need for it to be a friend function, as it didn't access any private parts. It was just defined inside the class for convenience. I've also tested it on Intel C++ 7.0 in strict mode and g++ 3.2, so the code should be conformant, at least. Thanks for the report. I hadn't yet got around to do more portability testing, but intend to do that, including writing more tests for it. I've updated the version at Yahoo Groups with the above changes. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: io operations for stl containers?
From: Jason House [EMAIL PROTECTED] Terje Slettebø wrote: and given this: int main() { char board[3][3]= { {'O','X','O'}, {'X','X','O'}, {'O','O','X'} }; std::cout io_formatchar ()[3](\n|,|\n,|) io_formatchar ()[3][3](---,---,---) board '\n'; } we get: --- |O|X|O| --- |X|X|O| --- |O|O|X| --- Hey, that's pretty cool. I'm glad to see the ability to format items inside of a container as well. I'm glad you like. :) Yes, it applies operator recursively, using overloading, and any format settings for the given type, so for the outer array, it matches the second format above, and for the inner it matches the first one. It should handle maps and pairs reasonably well. I think that I have the same complaints about this as io_manip The saving of information to the stream means that you can affect all future output... For instance, if you have a type mapcustom_object, liststring and custom_object's stream output uses io_formatliststring , then you are going to run into trouble if it wants a different formatting. Right. That's a consequence of this. As you say too, I don't know any obvious alternatives, though. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: io operations for stl containers?
From: Vladimir Prus [EMAIL PROTECTED] Terje Slettebø wrote: From: Vladimir Prus [EMAIL PROTECTED] after having to output std::vector to stream again and again using custom solution, I started to wonder why we don't have a solution in boost. Does it makes sense to include operators for vectors, sets, etc? I was thinking about boost/io/vector.hpp boost/io/set.hpp You can do this quite well using the standard library and stream iterator adapters. This may do both of your approaches above. For example: I certainly know that. I guessed you might. However, the solution seemed like a good match to your question, given that you didn't give any code example of its use. You mentioned outputting a vector to a stream, using custom separators, and that's what this does. std::cout Print vector\n; std::copy(list.begin(),list.end(),Out(std::cout,\n)); And I don't like it in the least. Compared with std::cout new path is v \n; I understand what you mean now. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] io operations for stl containers?
From: Vladimir Prus [EMAIL PROTECTED] after having to output std::vector to stream again and again using custom solution, I started to wonder why we don't have a solution in boost. Does it makes sense to include operators for vectors, sets, etc? I was thinking about boost/io/vector.hpp boost/io/set.hpp and so on. There are basically two approaches: 1. Operators use fixed format: bracked list with commas between values for vector, for example. 2. Manipulators are provided to set brackets and separators. I had implemented the second approach some time ago, but it turned out that was overkill. So, 1) looks better now. If this is done as a library, then I think it's best not to have hard-coded brackets and separators. One might use an xalloc() value for each type to output. For example something like: typedef std::pairint,char Map; typedef std::vectorMap MapList; MapList list; // Fill container std::cout boost::io_formatMap(,, [, ]) boost::io_formatMapList(,,\n) list '\n'; This might print: [1, a] [2, b] [3, c] Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] io operations for stl containers?
From: Glenn G. Chappell [EMAIL PROTECTED] Vladimir Prus wrote: after having to output std::vector to stream again and again using custom solution, I started to wonder why we don't have a solution in boost. Does it makes sense to include operators for vectors, sets, etc? ... std::cout new path is v \n; The philosophy behind the STL would suggest accessing containers through their iterators. Something like std::cout new path is Foo(v.begin(), v.end()) \n; would not be too bad (and it would be even better if it were called something besides Foo). This would be very general, while remaining quite readble, I think. Delimiters could be set using optional parameters, among other methods. std::cout new path is Foo(v.begin(), v.end(), [, ,, ]) \n; You then still have the issue of what to do with the element types. For example: std::vectorstd::pairchar,int v; std::cout Foo(v.begin(),v.end(),[,,,]) '\n'; How to print each element, and what if you want different delimiters for the elements? Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: compile-time functions interface
From: David Abrahams [EMAIL PROTECTED] I'm combining a couple of postings here. Gennaro Prota [EMAIL PROTECTED] writes: This is a simple question; suppose you have a template like this: template unsigned long x struct static_log2 { BOOST_STATIC_CONSTANT( int, value = ...); }; and that the implementation you use is absolutely general as far as the argument type is concerned; in other words: if C++0x will make unsigned long long available you want to replace unsigned long with that wider type. Specifically, this is the case for the excellent static_log2 implementation suggested by Vesa Karvonen a while ago on this list. A first, obvious, way to do this is to typedef the argument type: namespace boost { typedef unsigned long static_log2_argument_type; template static_log2_argument_type x struct static_log2 { ... } } *This* is precisely why you metafunctions should operate on types, not numbers. Types are the only fully polymorphic metadata because they can wrap anything else (well, as soon as we get template typedefs they will be able to wrap anything else, but they're close enough now). That's why MPL has integral_cT, value. *This* is precisely why you metafunctions should operate on types, not numbers. Types are the only fully polymorphic metadata because they can wrap anything else (well, as soon as we get template typedefs they will be able to wrap anything else, but they're close enough now). That's why MPL has integral_cT, value. Yes, of course. I thought it could be hard to find a way to provide the types for such a metafunction like static_log2, when it turns out that a solution to it is to not do it like that in the first place, as you say. I've even used this polymorphic ability of MPL to write examples of generic metafunctions like factorial. I just didn't think of of that, as this metafunction worked in a different way. The answer is to change the way of doing it, rather than finding a way to do it with the current version of the metafunction. As Terje Slettebø noticed in private mail, this is a general problem for any 'compile-time function'. Just to clarify here, what I meant was that this wasn't something specific for this particular metafunction, of course, so it could be good to find a general solution, such as the above one. From the next posting: Gennaro Prota [EMAIL PROTECTED] writes: From: David Abrahams [EMAIL PROTECTED] For static_log2 you would specialize it as: template unsigned long x struct argument_type static_log2x { typedef unsigned long type; }; That, however, still requires you to specify a number (whatever it is) when requiring the argument type: argument_type static_log216 :: type I don't even think it works. Throwing this at Comeau online: template unsigned long N struct static_log2 {}; template class T struct argument_type; template unsigned int x // *** struct argument_type static_log2x { typedef unsigned long type; }; Yeilds: ComeauTest.c, line 6: error: constant x is not used in template argument list of class template argument_typestatic_log2x template unsigned int x ^ But this works again if I change *** to unsigned long. None of my other compilers agree, but I am inclined to believe EDG. Why should it be any different from substituting class x at ***? I'm not sure what you mean, here. The error above comes from argument type mismatch, as the type of x is unsigned int, while static_log2 expects an unsigned long, so there needs to be a conversion. Therefore, the partial specialisation doesn't work. As you note, if you change it to match, with unsigned long, it works. I think EDG is right on this one, that there has to be an exact match, except top-level cv-qualification. whereas I think the intuitive syntax would be: argument_type static_log2 :: type To get the intuitive syntax, you can't use a default value in the specialization of argument_type, simply because that's illegal. But you could, if you really strive for it at all costs, use a default (=0) for static_log2 itself. How ugly (and ad-hoc) that would be is evident to everyone, so I was just, to say, thinking out loud in the hope that it could suggest other ideas. IMO, unless EDG is wrong you're going to have to use types if you want to generalize it. You can use the syntax Genny used: argument_type static_log216 :: type. However, unless you use an arbitrary default argument for static_log2, just for this purpose, you need to specify an arbitrary constant, instead, as shown here, just to get the type. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: compile-time functions interface
From: David Abrahams [EMAIL PROTECTED] Terje Slettebø [EMAIL PROTECTED] writes: As you note, if you change it to match, with unsigned long, it works. I think EDG is right on this one, that there has to be an exact match, except top-level cv-qualification. cv-qualification?? Whoa, the compiler seems to accept them, but they're also ignored. This compiles: template const volatile int x struct foo; template template int x class class bar {}; barfoo x; Yes, that's what I meant: The types have to match, except for any top-level cv-qualification difference, as it's ignored, as you say. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_base_and_derived question
From: Gennaro Prota [EMAIL PROTECTED] --- John Maddock [EMAIL PROTECTED] wrote: One question though - a lot of people seem to have worked on this: which people deserve the copyright/credit listing? Rani only, IMO. I think so, too. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_base_and_derived question
From: Gennaro Prota [EMAIL PROTECTED] On Thu, 30 Jan 2003 15:13:19 +0100, Terje Slettebø [EMAIL PROTECTED] wrote: [...] Roughly speaking B is a base of D if and only if the base-specifier-list of D contains a class name for B or for a class of which B is a base. Of course you can see if that's the case by knowing the definition of D and examining an inheritance graph. And since that's what a compiler does all the time, is_base_and_derived is another thing that could be (ahehm) easily implemented as a built-in operator. True. But it's also detectable using C++98, as shown by Rani's proposal. One must be *extremely careful* when making such an assertion. In the following part of the posting, I said that if it turns out it doesn't work correctly, then... We may understand how it works and have a few test cases, but that's not a big guarantee. C++ is a _very_ complex language, and all sorts of conversions can appear wherever you expect them the less. The fact that we don't see any leak in Rani's code doesn't mean that it there isn't. Probably, a week ago we were all enough convinced that it wasn't possible to detect a private base without causing an access error. No. You can't prove a negative, an impossibility. You can't prove that something can't be done. You can, however, prove that something can be done. You use an analogy later here, and I can come with one, as well: No matter how many black crows you find, you can't prove that there can never be a white crow. Only one white crow is enough to prove that there can be a white crow. And if we were convinced about that and were wrong, then we could be wrong now by thinking that the code works. Like I said, I've never said that this has been _proven_. You seem to be jumping the gun a little, here. Like I said in the posting, I'm not arguing whether or not there should be built-in language support for this. I've just pointed out some consequences of either approach. Let me make a little digression: the great Adrien Marie Legendre once proved that there doesn't exist any couple of rational numbers x and y such that: x**3 + y**3 = 6 It then happened that Henry Ernest Dudeney published a solution with only two digits in the numerator and the denominator of both fractions: 17/21 and 37/21 My point exactly: Adrien Marie Legendre tried to prove a negative. Now, you will agree with me that Legendre was all but a dumb. And he even had a proof. As was shown with your example, this was not a logically valid proof. If you want another example: when Whiles published his first demonstration of the last theorem of Fermat he was sure the proof was right, but an error was found by the reviewers. Then he made some changes and no error has been found so far. Now, the point of this rigmarole is not that we must proof any assertion concerning C++ (we are programmers not mathematician) but that we must be careful and modest; everybody makes error and the fact that experts are less likely to make errors is just an illusion: They may be less likely to make obvious mistakes. This goes for any field. This is analogous to the advantages of a four-wheel drive car: It lets you get stuck in inaccessible places. :) You may drive where normal cars can't go, but if you get stuck, you may need a helicopter to get out. :) You make this point in the following, as well. the complexity limit of what you get right is just shifted a little further on: you are more exercised but there's a limit (higher than the limit of a beginner) after you are, to say, in foggy land too. In the case of Whiles, the demonstration is so complex that not even an expert can state, with a reasonable certainty, that it is correct. As to C++, a number of experts certainly thought, with reasonable certainty, that the specification was correct but then we have a list of hundreds of defects. And some of those defects are on *fundamental* aspects of the language. Also some of them, e.g. issue 200, are simply incredible for their simplicity. The fact that after 2 years it hasn't been solved yet means that it is *too* complex, even for the committee experts. There's no offense intended in my words. I think everybody should be fair enough to admit that. Sometimes the committee likes to venture out to sea, probably because they are fun of the language just like me and you (more on this later) Genny, have I ever said that Rani's proposal has been _proven_ to work? I have not. I _explicitly_ said that it could be hard to do that, but it might be possible. What I said is that it works, i.e. we haven't found a case where it doesn't work. I have _not_ stated that this has been _proven_ to work. I know about mathematical and logical formalisms, as well, and I know there may be a long way from empirical evidence, to actual proof. This doesn't mean that, as you say yourself here, that if something turns out to work, even if it may not have
Re: [boost] Re: is_base_and_derived question
From: David Abrahams [EMAIL PROTECTED] John Maddock [EMAIL PROTECTED] writes: Maybe you had the following variation on Terje's code in mind. The following worked with GCC3.1/2, VC6/7/7.1 and Comeau 4.3.0.1: Hey, now that one really does work well, I'm still testing here (doesn't work with Borland, but I have a fallback position for that), but if there are no objections then you should expect to see the boost code updated soon. One question though - a lot of people seem to have worked on this: which people deserve the copyright/credit listing? S... Somewhere back in this thread Peter Dimov raised a serious question about whether this implements the semantics we want. Was there ever agreement on that? As I mentioned in an earlier posting, Rani's proposal does what the current docs on is_base_and_derived says. It doesn't mandate public, unambiguous base class. If one wants that semantic, then perhaps another trait could be useful for it. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_base_and_derived question
From: Terje Slettebø [EMAIL PROTECTED] From: David Abrahams [EMAIL PROTECTED] S... Somewhere back in this thread Peter Dimov raised a serious question about whether this implements the semantics we want. Was there ever agreement on that? As I mentioned in an earlier posting, Rani's proposal does what the current docs on is_base_and_derived says. It doesn't mandate public, unambiguous base class. If one wants that semantic, then perhaps another trait could be useful for it. Or, change the description in the docs to reflect the semantics of the current version. Either one or the other needs to be done, I think, because as it stands, the description doesn't match the current implementation. So either we change the map, or change the terrain. :) Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_base_and_derived question
From: David Abrahams [EMAIL PROTECTED] Terje Slettebø [EMAIL PROTECTED] writes: No. You can't prove a negative, an impossibility. I think that's wrong, and here's my one white crow to prove it ;-) I can prove that there can never exist a positive integral multiple of 2 which is both greater than 2 and prime. It's the same as saying that *every* positive integral multiple of 2 which is greater than 2 is a non-prime (now it's not a negative statement anymore, but it is logically equivalent). The positive integral multiples of 2 which are not greater than 2 are: 2. Since every other positive integral multiple of 2 is divisible by both 2 and itself, it must be non-prime. Ok, so you can do it in a field where you decide on all the rules, such as maths. I was more thinking in terms of if you don't have all the facts. For example, many thought it was impossible to fly, and perhaps constructed proofs for it, using their available knowledge. However, it turned out to be possible, anyway, in a way they may not have known about. However, since the topic was whether it was possible to prove that you could not detect inheritance without an access violation, I guess that might be provable, as well, since you may decide on the logic used in the implementation. So it seems you're right. But anyway, isn't this straying a little bit far from being on-topic? It is. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_base_and_derived question
From: Daniel Frey [EMAIL PROTECTED] David Abrahams wrote: Who cares? The new toy is so cool! :-) Seriously, Peter is a wise man. Personally I would go with his suggestion about having two (or more) separate metafunctions, at least for the sake of generality I'd rather settle on one for the sake of simplicity and see if it's enough for people. Once you provide two interfaces, you're sort of stuck supporting them both. I agree. And we should keep in mind that people can use trivial combination anyway, so we needn't offer them all with separate names/interfaces, e.g. is_base_and_derived B, D ::value || is_void B ::value is easy enough for users, so if they want to use void as a base for all classes, they can do it that way. All we need to do is to provide very good documentation. This may solve the issue of how or whether to support the semantics of the current implementation. That may be something like: is_base_and_derivedB, D::value is_convertibleD, B::value Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Deadline for the Standard Library TechnicalReport
[Note to moderators: This is just to reply, including giving possible alternative places to discuss this] From: Jason House [EMAIL PROTECTED] The first part of this is probably a stupid question Not at all. :) Terje Slettebø wrote: What makes the template typedef proposal different from the template alias proposal, is that the former may be specialised, and the latter may be deduced. What do you mean by deduced? The paper says: 2. A typedef template is itself an alias; it cannot be specialized. This choice would allow: . deduction on typedef template function parameters (see 2.4) The paper doesn't propose that model. However, that has been suggested as an alternative, mentioned in this thread, in the form of template alias (i.e. not using typedef at all). I saw it in the proposal too... Here's a copy of text from the proposal: *** templateclass T, class P class smart_ptr; templateclass T typedef smart_ptrT, SharedPolicy shared_ptr; templateclass T void f(smart_ptrT, SharedPolicy); templateclass T void f(shared_ptrT); In this proposal, the last two lines declare different templates. *** That is the kind of stuff that concerns me. There is a deviation in the usage of smart_ptrT, SharedPolicy and shared_ptrT even though they are typedef'd to be the same. I think what is meant is that the templates are not aliases (i.e. the templateclass T void(...) templates). Otherwise, the last two lines would declare identical templates. However, as I understand it, the template function parameters express the same type, i.e. typeof(smart_ptrT, SharedPtr) == typeof(shared_ptrT), for a given T. Also, where should such discussion be going? Someone mentioned that this is not the place, but I'm not familiar with the various other mailing lists. Hm, there's the C++ standards committee mailing lists (reflectors) which have been mentioned, but as I understand, these are not open to the public. Another alternative is the newsgroups, such as comp.std.c++, which is discussion about the standard, itself, which this is about. They may also be accessed from the web (http://groups.google.com/groups?hl=enlr=ie=UTF-8group=comp.std.c%2B%2B). Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_base_and_derived question
From: Terje Slettebø [EMAIL PROTECTED] Given that supertype/subtype has such a general meaning, how should an is_super_and_subtype be defined? I guess the proposal mean to define it in terms of inheritance, only, and in that case, it would work like is_base_and_derived, with the addition that a type is its own supertype/subtype (but not its own base/derived type). If we consider substitutability outside the class hierarchy, only (not considering private/protected inheritance), then for is_super_and_subtype to obey LSP, it should only give true in the case where an object or pointer/reference of a type S is implicitly convertible to type T. This means public, unambiguous base class, only. This is the way is_base_and_derived works today, except that it doesn't give true for B = D. However, for is_base_and_derived to really tell if something is base and derived classes, it should ignore issues of access and ambiguity, which is related to convertibility/substitutability, only, but not to whether or not they are related by inheritance. In other words, it should give the semantic that Rani's proposal has. Whether or not the above semantic is desirable is another question. However, if it is, to summarise, we could define these like this: - Rename the current is_base_and_derived to is_super_and_subtype, and allow it to give true for S = T. - Use Rani's proposal for the new is_base_and_derived. Add specialisation to give false for B = D. There's also a question of existing code relying on the current semantics, of is_base_and_derived giving false in the case of private/protected or ambiguous base class. However, it may be argued that such code does not rely on the stated documentation, so it's broken, anyway. Changing the implementation of is_base_and_derived to use Rani's proposal still gives its stated semantics, which is (from the docs): is_base_and_derivedT,U::value - Evaluates to true if type T is a base class to type U. It does not say public, unambiguous base. That could be the wording for is_super_and_subtype, instead. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_base_and_derived question
From: Gennaro Prota [EMAIL PROTECTED] On Thu, 30 Jan 2003 11:13:23 +0100, Terje Slettebø [EMAIL PROTECTED] wrote: From: Gennaro Prota [EMAIL PROTECTED] On Tue, 28 Jan 2003 10:47:52 -0800, Andrei Alexandrescu [EMAIL PROTECTED] wrote: Peter Dimov [EMAIL PROTECTED] wrote in message While we're at it, is the final verdict that is_base_and_derivedvoid, X should be false? What about is_base_and_derivedvoid, void? Well, clearly void is no base. Even if we also define is_super_and_subtype, void is hardly a supertype of everything. Could you please clarify this? You mean: T is a subtype of U = ...?... T is a supertype of U = ...?... Supertype/subtype is a more general notion than inheritance and base/derived. The Liskov Substitution Principle states[...] Be careful though. If you bring in a behavioral principle like LSP than the issue becomes complicated. The point is that if you define supertype = base class and subtype = derived class, then what's the point in having an is_super_and_subtype? In this case, they would be identical. The square/rectangle example is classic: if your square class throws e.g. when detecting that invariants are broken then it's trivial to construct an object of type square o1 and a program P defined in terms of rectangles which changes behavior if you replace an instance of rectangle with o1. Whether defining such a square class is good practice or not is another matter. The point is that is_base_of is just a mechanical relation that is difficult to define in terms of behavior. Yes, as you say, the language doesn't enforce LSP for public inheritance, it merely _assumes_ it, as I mentioned in the previous posting. Roughly speaking B is a base of D if and only if the base-specifier-list of D contains a class name for B or for a class of which B is a base. Of course you can see if that's the case by knowing the definition of D and examining an inheritance graph. And since that's what a compiler does all the time, is_base_and_derived is another thing that could be (ahehm) easily implemented as a built-in operator. True. But it's also detectable using C++98, as shown by Rani's proposal. Not that I'm set for it, but please think about this: can you give off-hand a proof that Rani's implementation is equivalent to the mechanical definition I gave above? A proof? Egads. :) I had a hard enough time figuring out how it works, in the first place. :) It relies on some dusty corners of the language, such as the order in which overload resolution is done. As has been shown with tests, hardly any of the current compilers gets it right, only the EDG ones have been reported as working with it. I think it may be doable, though. If you are going to write the documentation for is_base_and_derived what do you write? The definition above? Or something else? If you write the definition above (as it is now, because the docs say more-or-less if and only if B is a base of D) shouldn't you prove that it is implementable in C++? How much time will the committee spend to get agreement on the definition and seeing that it is implementable? How much time does it take to implement the built-in operator once you stick to the mechanical definition? Maybe the answer to the last question is much much smaller than the previous ones. I haven't argued for or against having is_base_and_derived as a built-in operator, or not. However, the fact is that having it as an operator requires a language change, and that's likely several years away. There are a few observations: - is_base_and_derived (Rani's proposal) is usable here and now, so regardless of any language/library change, it may be used now. - If it turns out that is_base_and_derived doesn't completely detect base and derived class, according to the definition in the standard, and a way is not found to do so within the current definition of the language, one may e.g.: - Change the part of the standard that the is_base_and_derived relies on for its workings, so that it _does_ work correctly, if possible. Or, - Add is_base_and_derived as an operator in C++0x There is a very important point: Adding is_base_and_derived as an operator/keyword in C++ requires adding a keyword, and that's a _major_ change. It may break a lot of programs, if those programs uses an identifier with this name, especially if it's not used in the way an operator would be used. On the other hand, if you're able to implement it using the language features, then it may e.g. be a standard library component, and that won't break any existing programs. What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T. Notice that it doesn't say anything about class or inheritance, anywhere
Re: [boost] Re: is_base_and_derived question
From: Gennaro Prota [EMAIL PROTECTED] On Thu, 30 Jan 2003 12:33:04 +0100, Terje Slettebø [EMAIL PROTECTED] wrote: From: Andrei Alexandrescu [EMAIL PROTECTED] Even if we also define is_super_and_subtype, void is hardly a supertype of everything. Well, it could be. It's like an abstract base class, even for built-in types - everything can be implicitly converted to void What do you mean? In standard terminology, for an expression e to be *implicitly* convertible to T you must be able to write: T t = e; You're right that it isn't implicitly convertible to void in this sense. What I was thinking of was that if you return a value from a function, it may be ignored by the caller. However, you're right that this doesn't have anything to do with implicit conversion - there can't even be a void object, so it clearly isn't obeying LSP. void *, with regard to other pointers, is something else, though. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: is_base_and_derived question
From: John Maddock [EMAIL PROTECTED] This is tested on Comeau 4.3, Intel C++ 6/7 and g++ 3.2. Except it *doesn't work* ! The problem is that your static assertion don't test anything, changing to: //typedef char TestA[is_base_and_derivedB, D::result]; // Multiple bases (error on g++) typedef char TestB[is_base_and_derivedB1,D::result ? 1 : -1]; //typedef char TestC[is_base_and_derivedB2,D::result]; // Private base (error on g++) typedef char TestD[!is_base_and_derivedint,D::result ? 1 : -1]; typedef char TestE[!is_base_and_derivedB, B::result ? 1 : -1]; typedef char TestF[is_base_and_derivedB,DV::result ? 1 : -1]; // Virtual base and both Borland and gcc 3.21 give errors on cases 2 and 6 Well, this means that there are other problems in these compilers. The following _should_ give an error: typedef char Test[0]; and indeed it does on the EDG compilers. Well, then it turns out that even this version doesn't work correctly on g++ and Borland, and it doesn't give an error, either, for the above cases. Using BOOST_STATIC_ASSERT, this would have been detected. There's no need to shout. :) The test code should work on a conforming compiler. By the way, those static asserts were inherited from Rani's example code, with a couple of additions. I guess this is a good reason to use a portable static assert, like the Boost one. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_convertible: rationale and wording
From: Gennaro Prota [EMAIL PROTECTED] On Thu, 30 Jan 2003 12:20:32 -, John Maddock [EMAIL PROTECTED] wrote: Can you show, with an example, why the code used for named template arguments can't reasonably use an expression? It doesn't have access to one, only a type: the usage is take some template parameter, see if it is convertible to some policy type, and if it is, then extract the policy information. The technique I know relies on detecting whether the template argument is *derived* from some policy, and that's doable with expressions. You don't need expressions (if by that you mean an object of the type to test, or pointer/reference to it) to check for convertibility, as it may be done with sizeof, so no object of any kind need to be created. However, you may need an object, or pointer/reference to it, to use function templates. Also, that won't make it a compile-time expression, so why use function templates for this? Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Deadline for the Standard Library TechnicalReport
From: Jason House [EMAIL PROTECTED] 2. Section 2.5 (Different Declarations) rubs me the wrong way. Thr proposal does say that some people dislike this, and I guess I'm one of them. If template A,B class X; template A typedef foo XA,B; then I'm opposed to typeof(XA,B) != typeof(fooA) As I understand the proposal, template typedefs will yield the same type, not a new type. The template typedef, _in itself_ (i..e. its definition) is not an alias to an existing template, but an instantiation (i.e. use of it) yields an alias of an existing type. Therefore, template typedefs don't introduce new types. typeof(XA,B) == typeof(fooA) After all if typedef bar int; then typeof(bar) == typeof(int) /* causes occasional dismay */ I'd like to see templates hold the same logical niche for both templated and untemplated types. They do. :) What makes the template typedef proposal different from the template alias proposal, is that the former may be specialised, and the latter may be deduced. It would be interesting to have a means of defining a new type via a typedef-like declaration that did not share type equality, I just wouldn't want it to be a normal looking typedef statement. There has been suggestions for this, e.g. something like this: typedef new int new_int; typeof(int) != typeof(new_int) This wouldn't introduce new keywords, either. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: is_base_and_derived question
From: John Maddock [EMAIL PROTECTED] Before changing the documentation please consider the following improved implemetation that overcomes ambiguity and access control issues of the current is_base_and_derived implemetation (I lately posted it to c.l.c++.m) That's really interesting, but I can't get to work with the compilers I have access to (Borland/gcc), I've attached a modified version that at least compiles with these compilers, but it doesn't produce the correct results: The following version works on g++ for the same cases that the current is_base_and_derived works (i.e. excluding multiple bases, and private/protected inheritance), and gives an error in the cases it doesn't work, while it works completely on the compilers that supports this (such as Comeau C++ and Intel C++ 6/7). In other words, it degrades gracefully, and breaks noisily, if the compiler doesn't support the extra cases. This is tested on Comeau 4.3, Intel C++ 6/7 and g++ 3.2. You could get the same effect with #ifdef between Rani's original version, and the current Boost version, but the following version makes the #ifdef unnecessary. templatetypename B, typename D struct helper { templatetypename T static char check(D const volatile , T); static char ( check(B const volatile , int))[2]; struct C { operator B const volatile () const; operator D const volatile (); }; static C getC(); }; templatetypename B, typename D struct is_base_and_derived { static const bool result = sizeof(helperB,D::check(helperB,D::getC(), 0)) == 1; }; // If strict interpretation, i.e. not its own base class templatetypename T struct is_base_and_derivedT, T { static const bool result = false; }; struct B {}; struct B1 : B {}; struct B2 : B {}; struct D : B1, private B2 {}; struct BV1 : virtual B {}; struct BV2 : virtual B {}; struct DV : BV1, BV2 {}; // g++ doesn't like multiple definitions of the same typedef, therefore they have different names typedef char TestA[is_base_and_derivedB, D::result]; // Multiple bases (error on g++) typedef char TestB[is_base_and_derivedB1,D::result]; typedef char TestC[is_base_and_derivedB2,D::result]; // Private base (error on g++) typedef char TestD[!is_base_and_derivedint,D::result]; typedef char TestE[!is_base_and_derivedB, B::result]; typedef char TestF[is_base_and_derivedB,DV::result]; // Virtual base int main() { } Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: MPL usage for code generation
From: Aleksey Gurtovoy [EMAIL PROTECTED] David Abrahams wrote: It appears to be just bad luck that higher order functional programming with function templates is impossible in C++. My current understanding (which, admittedly, is not backed up by a real-world experience) is that if you care about higher-orderness of your generic algorithms, a preferred implementation construct for those algorithms is not a function template, but a static _function object_ (a technique used in FC++): struct my_function_ { template typename U void operator()(std::string const text, U) { // ... } } my_function; // here! For ordinary uses, the above will act just like a plain function template (minus ADL/explicit template arguments specification): However, it does tend to create some boilerplate code, if all you want is to call a function template for all the types. It's similar to std::for_each, if you want to execute arbitrary code, unless you use BLL. Nevertheless, I've asked at comp.std.c++ why function template template parameters aren't allowed (the posting hasn't appeared, yet). and it will also allow one to do something like this: std::string text(text); mpl::for_each my_types (boost::bindvoid(my_function, text, _1)); I got error: no instance of function template boost::mpl::for_each matches the argument list, when trying this on Intel C++. Do you have a version of this that works? Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: MPL usage for code generation
From: David Abrahams [EMAIL PROTECTED] Terje Slettebø [EMAIL PROTECTED] writes: Perhaps it might be possible to do some compile-time/run-time lambda (similar to Boost.Lambda for runtime, and MPL's lambda), so you could do something like: mpl::for_eachmy_list(my_function_(s)); It would then transform the function call my_function_(s) into an instantiated function object of the kind suitable for mpl::for_each. I'm afraid that particular syntax won't work for this particular case, though. If my_function is a function template, my_function_ is a function, and my_function_(s) calls that function. Yes, even with function template template parameters, the syntax would have to be changed. I realised that you can't just pass the address of a function, since in this case, it's a function template. Besides, it wouldn't help to use the placeholder in that place (unless you specialised the user-supplied function, but that would be no point). The above was just to sketch the idea of it. Since there are no (function template) template parameters, only (class template) template parameters, there doesn't appear to be any way to make this one particularly easy except by using the preprocessor to define some kind of function object. Yes, I realised that later, as well. Is there any good reason for not allowing function templates as template template parameters? I think it's amazing that we got the template facility that exists, in the standard, so maybe it simply wasn't time to consider this, to avoid delaying standardisation. If this was possible, you might have done something like this, instead (using TTP): mpl::for_eachmy_list, std::string , my_function(s); It appears to be just bad luck that higher order functional programming with function templates is impossible in C++. Well, it might be changed in a future revision of the standard, if it turns out to be practical. I can imagine something like this: templateclass Sequence, class T, templateclass void Function(T) struct for_each; Possibly using overloaded class templates, as well (another possible extension). Anyway, this goes beyond the topic of Boost. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: MPL usage for code generation
From: Terje Slettebø [EMAIL PROTECTED] I can imagine something like this: templateclass Sequence, class T, templateclass void Function(T) struct for_each; Possibly using overloaded class templates, as well (another possible extension). Come to think of it, the latter wouldn't be needed here, as for_each is a function template, and they can be overloaded. :) That would allow different arity for the the function template template parameter. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: MPL usage for code generation
From: David Abrahams [EMAIL PROTECTED] Andrei Alexandrescu [EMAIL PROTECTED] writes: Or (barring my lack of mastering some syntactic details): inline void do_my_function(string, void_) {} template class Lst inline void do_my_function(string s, Lst lst) { my_functionfrontLst::type(s); do_my_function(s, pop_frontLst::type()); } ... do_my_function(s, my_list()); No struct, no for_each, no operator(). Et que le meilleur gagne :o). Yeah, I haven't always been very comfortable with the value-per-character of mpl::for_each -- it seems to have similar properties to std::for_each in that way. Perhaps it might be possible to do some compile-time/run-time lambda (similar to Boost.Lambda for runtime, and MPL's lambda), so you could do something like: mpl::for_eachmy_list(my_function_(s)); It would then transform the function call my_function_(s) into an instantiated function object of the kind suitable for mpl::for_each. That would collapse the 7 or 12-line solution to one line. :) Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: compile-time binary constants
From: Gennaro Prota [EMAIL PROTECTED] On Sat, 18 Jan 2003 20:16:36 -0700, Greg Colvin [EMAIL PROTECTED] wrote: At a meeting years ago I proposed to make string literals more useful as constant expressions, but we decided against that. As I recall part of the problem is that linkers are free to map the same literal string to different addresses in different compilation units. I'm not sure what you are referring to by using string-literals as constant expressions. If you are alluding to making the array referred to by a string-literal usable as a template argument, like in template const char c[] struct X {}; X hello x; then I'd like to make a comment. Currently C++ doesn't allow this. Briefly, the problem is that a string-literal (which is not an object per se, but an expression which *refers* to an object implicitly created by the compiler) refers to an unnamed object and such an object is not usable as a template argument. However it would be perfectly possible to give it a compiler-generated name. Now, as you say, it's not specified whether array objects corresponding to identical string literals are collapsed together or not and thus you don't know whether e.g. x and y below have the same type or not X hello x; // (*) X hello y; You could avoid this problem by encoding the text string in the value used to represent the string literal. That would ensure that all template instantiations, using the same string literal, regardless of translation unit, have the same type. However, you would still have the issue, as Greg says, here, that the literals could have different addresses in different TUs, so that if you took their address, you'd get different values, despite being the same literal. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Policy-based smart pointers revisisted
From: Peter Dimov [EMAIL PROTECTED] From: Terje Slettebø [EMAIL PROTECTED] I understand the concern. For one thing, we don't have template typedefs, yet, although me may get a similar effect (if not the same type) with e.g.: templateclass T struct shared_ptr : smart_ptrT, policies... {}; What are the primary strengths of a policy based smart pointer? 1. It allows users to create their own custom smart pointers. 2. It allows users to globally switch to another smart pointer type by changing a typedef: 3. It allows users to write generic functions that can take any smart pointer. (1) and (3) aren't affected by convenience wrappers, and (2) is made more difficult if the shared_ptr pictured above is used in the project. I think there's also another concern, which may or may not apply here: Avoiding code duplication. If it's possible to sensibly divide the aspects of a smart pointer into policies, then instead of writing a new smart pointer to deal with the change (e.g. from reference counted, to COM-type reference counted), you just change that particular aspect or policy. I understand your point about scope. If a component tries to be all-encompassing, you might loose cohesion in the process. After all, you could have a component, Program, and various policies determining what the program did. :) Program wouldn't likely be a very cohesive unit, though. I'm also all for simplicity, cohesion, decoupling, do the simplest thing that could possibly work (XP/pragmatic programmers), etc., and I'm sure Andrei is, as well. After all, when Loki's typelists have been discussed, he's stated that they are heavily KISSed. Others have argued that the flexibility of MPL makes it worth it. So it's a little ironic situation. :) I guess it comes down to which of a policy-based system, or a set of independent smart pointers, as a total, has the best cost/benefit ratio. It may also depend on how much variation is likely. This is a typical library issue, anyway. I understand that the Boost smart pointers are quite versatile, so they may cover much of the functionality needed, anyway. For completeness, there is also 4. Depending on the PBSP design, it might allow users to mix and match smart pointers of different types. One could also allow this with separate pointers, and as I understand, that's already the case with the Boost ones (e.g. shared_ptr and weak_ptr cooperating). Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Policy-based smart pointers revisisted
From: Greg Colvin [EMAIL PROTECTED] At 07:33 AM 1/18/2003, Peter Dimov wrote: It is not simply declaration complexity that Dave's talking about - it can be avoided by making smart_ptrT be shared_ptrT by using default parameters. It is semantic complexity. shared_ptr is fairly deep by itself (and getting the specification and the tests to a state that can be considered adequate wasn't easy.) One aspect of the semantic complexity that bothers me is that the various flavors of smart pointer may not be interchangeable. shared_ptr is partly parameterized on implementation, but the interface and semantics remain the same. For a policy-based smart pointer to be usable I think you need a clear set of concepts that clients can use as requirements, and a clear delineation of which combinations of policies support which concepts. Good idea. This is what I hinted to with providing convenience typedefs/classes, which guaranteed correct, and documented, semantics. CE distinguishes between the Configuration DSL and the ICCL (Implementation Component Configuration Language). The former is geared towards the user, and embodies application domain knowledge, while the latter is geared towards the implementation, with knowledge about that. Then you have a generator to bridge the two. Policy-based design is typically mostly ICCL, with it being a kind of special case of GenVoca, as Mat Marcus has mentioned. There's typically little or no functionality such as that provided by a Configuration DSL. If one had more functionality like that, it could make it easier to use, and you shouldn't have to be an expert on the implementation of the smart pointer, to be able to choose correct policies, and avoid any invalid combinations or pitfalls. This reminds me that I'll read up on the discussion regarding policies, in the Boost archive. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Policy-based smart pointers revisisted (was: Re: Preliminarysubmission: command line config file library)
From: David Abrahams [EMAIL PROTECTED] Please don't take this to mean I'm against a policy-based smart pointer; quite the opposite. I've said all along it would be great to have one in boost. I've even wished I had an appropriate occasionally. I just don't want to trivialize what I perceive to be valid concerns, either. Understanding the costs of complexity should be as important to the designer of policy-based classes as to everyone else, if not more so. I understand the concern. For one thing, we don't have template typedefs, yet, although me may get a similar effect (if not the same type) with e.g.: templateclass T struct shared_ptr : smart_ptrT, policies... {}; etc. However, I also understand the concern regarding understanding the policies available, their responsibilities and interaction. Therefore, convenience templates like the above could make it easier to use them, while still allowing new convenience templates/template typedefs to be made, or new policy implementations added. Having such convenience templates is a bit like having a small configuration DSL on top of the policy-based smart pointer, to use the terminology in CE. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Fun, only handled by vc6/7!
From: David Abrahams [EMAIL PROTECTED] Terje Slettebø [EMAIL PROTECTED] writes: Why would we want that? What is this useful for? It would be useful for writing a templated implicit conversion operator with restricted applicability via SFINAE. Right. I've read up properly on the thread, now. I see how this could be useful. Sorry for not having done that earlier. SFINAE is a feature of the language which (coincidentally) allows a technique for removing functions from the overload set based on some compile-time computation. This technique relies on having a return type or parameter type to play with. Unfortunately, implicit conversion operators have neither. Read all about SFINAE in Jossutis Vandevoorde. g I've done it. Also, when the term first time was brought up here, it was pointed out that this technique has been used for quite a while, also before the book got published. However, now we have a name for it. :) Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Fun, only handled by vc6/7!
From: Paul Mensonides [EMAIL PROTECTED] From: David Abrahams [EMAIL PROTECTED] Here's an interesting turn-of-the-tables: I was experimenting with using SFINAE to disable conversion operators, and I discovered that almost every compiler except vc6/7 rejects this code: template class T struct voidify { typedef void type; }; template class T struct Y {}; struct X { template class T operator YT (typename voidifyT::type) const { return YT(); } }; Is this even legal? I.e. for a user-defined conversion operator to have any arguments at all? Look twice; the argument is void. I know, but I don't think you can derive a 'void' parameter list that way. snip In other words, the void parameter list is fundamentally different than type void. It appears this is right. 8.3.5/2 says: [...] If the parameter-declaration-clause is empty, the function takes no arguments. The parameter list (void) is equivalent to the empty parameter list. Except for this special case, void shall not be a parameter type (though types derived from void, such as void*, can). So it seems only void can be used, not any type expression that evaluates to void. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Fun, only handled by vc6/7!
From: Terje Slettebø [EMAIL PROTECTED] From: Gennaro Prota [EMAIL PROTECTED] In some old newsgroup post, searched through Google a while ago, I also read that the committee rejected a proposal to allow the generalized form f(T) with T=void, but I've never read the proposal itself (I didn't find it at that time). Maybe Dave can do something to raise the dead though ;-) Why would we want that? What is this useful for? FWIW, the f(void) notation was introduced in C++ for compatibility with C (DE, p. 41): C with Classes introduced the notation f(void) for a function f that takes no arguments as a contrast to f() that in C declares a function that can take any number of arguments of any type without any type check. My users soon convinced me, however, that the f(void) notation wasn't elegant, and that having functions declared f() accept arguments wasn't intuitive. Consequently, the result of the experiment was to have f() mean a function f that takes no arguments, as any novice would expect. It took support from both Doug McIlroy and Dennis Ritchie foe me to build up the courage to make this break from C. Only after they used the word abomination about f(void) did I dare give f() the obvious meaning. However, to this day, C's type rules are much more lax than C++'s, and ANSI C adopted the abominable f(void) from C with Classes. Further, he says: Unfortunately, ANSI C adopted f(void) so I had to introduce f(void) into C++ for ANSI C compatibility. (http://technetcast.ddj.com/tnc_program.html?program_id=9). After having broken C programs to introduce f() as a way of unambiguously specifying no parameters, in C++, why would we want to go back to the C way of doing things, with f(void)? Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost