Re: [boost] Re: Re: Re: GUI/GDI template library

2003-08-03 Thread Terje Slettebø
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

2003-06-24 Thread Terje Slettebø
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

2003-06-22 Thread Terje Slettebø
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

2003-06-22 Thread Terje Slettebø
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

2003-06-21 Thread Terje Slettebø
(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)

2003-06-06 Thread Terje Slettebø
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

2003-06-05 Thread Terje Slettebø
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?

2003-04-30 Thread Terje Slettebø
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

2003-04-27 Thread Terje Slettebø
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?

2003-04-27 Thread Terje Slettebø
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?

2003-04-27 Thread Terje Slettebø
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

2003-04-24 Thread Terje Slettebø
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

2003-04-24 Thread Terje Slettebø
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

2003-04-23 Thread Terje Slettebø
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

2003-04-17 Thread Terje Slettebø
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

2003-03-31 Thread Terje Slettebø
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?

2003-03-27 Thread Terje Slettebø
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?

2003-03-26 Thread Terje Slettebø
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)

2003-03-26 Thread Terje Slettebø
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?

2003-03-26 Thread Terje Slettebø
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)

2003-03-26 Thread Terje Slettebø
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)

2003-03-26 Thread Terje Slettebø
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)

2003-03-22 Thread Terje Slettebø
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)

2003-03-22 Thread Terje Slettebø
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)

2003-03-22 Thread Terje Slettebø
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)

2003-03-22 Thread Terje Slettebø
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)

2003-03-22 Thread Terje Slettebø
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)

2003-03-22 Thread Terje Slettebø
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)

2003-03-21 Thread Terje Slettebø
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)

2003-03-21 Thread Terje Slettebø
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

2003-03-19 Thread Terje Slettebø
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

2003-03-19 Thread Terje Slettebø
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

2003-03-19 Thread Terje Slettebø
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

2003-03-18 Thread Terje Slettebø
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

2003-03-18 Thread Terje Slettebø
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

2003-03-18 Thread Terje Slettebø
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

2003-03-18 Thread Terje Slettebø
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

2003-03-18 Thread Terje Slettebø
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

2003-03-17 Thread Terje Slettebø
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

2003-03-17 Thread Terje Slettebø
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?

2003-03-17 Thread Terje Slettebø
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?

2003-03-16 Thread Terje Slettebø
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

2003-03-16 Thread Terje Slettebø
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

2003-03-16 Thread Terje Slettebø
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

2003-03-16 Thread Terje Slettebø
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

2003-03-14 Thread Terje Slettebø
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

2003-03-12 Thread Terje Slettebø
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

2003-03-12 Thread Terje Slettebø
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

2003-03-10 Thread Terje Slettebø
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?

2003-03-09 Thread Terje Slettebø
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?

2003-03-09 Thread Terje Slettebø
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.

2003-03-09 Thread Terje Slettebø
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.

2003-03-09 Thread Terje Slettebø
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

2003-03-06 Thread Terje Slettebø
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

2003-03-06 Thread Terje Slettebø
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

2003-02-28 Thread Terje Slettebø
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

2003-02-28 Thread Terje Slettebø
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

2003-02-27 Thread Terje Slettebø
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

2003-02-26 Thread Terje Slettebø
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

2003-02-26 Thread Terje Slettebø
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?

2003-02-25 Thread Terje Slettebø
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?

2003-02-24 Thread Terje Slettebø
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?

2003-02-24 Thread Terje Slettebø
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?

2003-02-07 Thread Terje Slettebø
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?

2003-02-05 Thread Terje Slettebø
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?

2003-02-05 Thread Terje Slettebø
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?

2003-02-05 Thread Terje Slettebø
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?

2003-02-04 Thread Terje Slettebø
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?

2003-02-04 Thread Terje Slettebø
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?

2003-02-04 Thread Terje Slettebø
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?

2003-02-03 Thread Terje Slettebø
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?

2003-02-03 Thread Terje Slettebø
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?

2003-02-03 Thread Terje Slettebø
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

2003-02-02 Thread Terje Slettebø
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

2003-02-02 Thread Terje Slettebø
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

2003-01-31 Thread Terje Slettebø
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

2003-01-31 Thread Terje Slettebø
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

2003-01-31 Thread Terje Slettebø
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

2003-01-31 Thread Terje Slettebø
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

2003-01-31 Thread Terje Slettebø
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

2003-01-31 Thread Terje Slettebø
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

2003-01-31 Thread Terje Slettebø
[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

2003-01-30 Thread Terje Slettebø
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

2003-01-30 Thread Terje Slettebø
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

2003-01-30 Thread Terje Slettebø
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

2003-01-30 Thread Terje Slettebø
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

2003-01-30 Thread Terje Slettebø
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

2003-01-30 Thread Terje Slettebø
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

2003-01-29 Thread Terje Slettebø
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

2003-01-24 Thread Terje Slettebø
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

2003-01-23 Thread Terje Slettebø
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

2003-01-23 Thread Terje Slettebø
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

2003-01-22 Thread Terje Slettebø
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

2003-01-19 Thread Terje Slettebø
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

2003-01-18 Thread Terje Slettebø
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

2003-01-18 Thread Terje Slettebø
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)

2003-01-17 Thread Terje Slettebø
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!

2003-01-13 Thread Terje Slettebø
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!

2003-01-12 Thread Terje Slettebø
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!

2003-01-12 Thread Terje Slettebø
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



  1   2   >