Boost logo

Boost :

From: Corwin Joy (cjoy_at_[hidden])
Date: 2001-07-16 13:54:22

----- Original Message -----
From: "Kevlin Henney" <kevlin_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Monday, July 16, 2001 2:29 AM
Subject: [boost] Re: "any" suggestions

> No matter, even if one were to remove default construction and cripple
> the class in that way, it does not address the issues with your
> proposal. If I am to stream something into an any, I have to guarantee
> that what is (typically) external to the program and is now being
> streamed into the any is of the right type. How did you plan to arrange
> this? If you know the type in advance, you don't need an any type at
> all.

Not true. As illustrated in my last post there are times when you want to
set a type at construction time. This is a kind of type-prototype design.
Any writes / updates to the held value after that then need to be cast to
the last value.
> If your plan is to allow arbitrary streaming of arbitrary types, you
> will find you run into more issues than you had perhaps appreciated
> initially, and the fault is with the assumptions and not with the any
> class.
I am not proposing arbitrary streaming of arbitrary types.

> >> And the following would
> >> rather defeat the object of supporting I/O in the first place:
> >>
> >> boost::any value = 0.0;
> >> std::cin >> value; // will attempt to extract a double
> >>
> >
> >This does not at all defeat the purpose of supporting I/O. There any
> >times when you want to use "any" as a kind of prototype design where
> >you say that the type must is set by the initial construction and any
> >further "writes" to that type must be cast into that type.
> If you could demonstrate this with real code I would be interested, but
> to date in my work when I have encountered such designs there have
> generally been simpler and more appropriate solutions, and such uses of
> any have often been misguided.

I can demonstrate this with real code, and no I don't think such a use of
any is misguided.
Here is an extract from the my last post:

>> Peter Dimov wrote:
> > you say that the type must is set by the initial construction and any
> > further "writes" to that type must be cast into that type.
> Could you please provide an example of such a design? This is quite
> interesting.

Sure. We have a variant class in the Database Template Library that I
co-authored ( What
happens is that at construction time, the program analyzes the table being
bound to and determines the types of the columns such as date, string,
integer, wide-string etc. Once these types have been determined a variant
is constructed to hold each database column. After initial construction,
any writes into this variant class are not allowed to change the variant's
type (otherwise the database binding would become invalid). So, writes into
the variant are cast into whatever type is currently held by the object. If
the cast cannot be performed, a runtime exception is thrown.
I think other examples of this "type" prototype are out there. Examples
might be initial parsing of a file to determine the types of fields held and
then holding this types fixed after construction or other applications where
the metadata is analyzed seperately from the value and needs to remain fixed
after construction.

> >It is true this is an inefficient solution if the op is common. My point
> >that "any" is rather useless without providing some kind of operation to
> >safely cast out values to types other than just the currently held type.
> I think you have misunderstood the basis of the design of any (which is
> documented): if you RTKS you will see that variant types are classified
> into three categories. The role that any plays is in the second
> category: a non-interpreting, discriminated union. You are trying to
> convert it into the first, which is of course a quite different design
> that satisfies slightly different needs.

I read the documentation before I started this thread and I don't agree that
the categories are mutually exclusive. I think one can add support for
casts to an "any" type structure without giving up safety.

> Converting-variant types have their uses, but they also introduce a
> number of subtleties that many programmers trip over -- both their users
> and their authors.

I'm sure that implicitly converting variant-types have big problems. If you
force casts to be explicit I'm not sure you're that much different than the
situation with regular casts.

> Andrew Koenig wrote an article on these issues many
> years ago, in JOOP I believe, although I do not have the reference to
> hand.

I'd be interested to see the reference.
> In its current form you want something that any does not, should not and
> will not provide, and you are welcome to attempt your own design for an
> interpreted variant and submit it to Boost for consideration.

I may very well do that.

> However,
> just to say that any in its current form is "rather useless" does not
> affect the utility that others perceive in the class or do anything to
> convince me that you are making a good case for change.
> >The current approach of any_cast which says, "well, we only allow you to
> >back out the value in the form of the original type" is ridiculous.
> And why is it "ridiculous"? You should be a little more careful,
> considered and constructive with your comments -- it is entirely
> possible that the misunderstanding is not in the design of any.
Well, I find it riducoulous because if you knew the type held by "any" at
compile time why would you use any in the first place? It seems to me that
every time you start using any for practical work you will need to start
making assumptions / casts and switch cases. I challenge you to produce a
example of actually using values from the current "any" class in a
non-trivial way that doesn't require casts. So e.g.
print out a list of any values
sort a list of any values
add 1 to any values

> >> Have you demonstrated this thrashing? I haven't explored this in
> >> but for many uses of any you seem to get good recycling.
> >>
> >I haven't done numerical tests -- mostly because this point strikes me as
> >quite obvious.
> Be careful here: it is not at all obvious. Your intuition needs to be
> very finely honed to be right about performance issues based on
> conjecture rather than measurement. Even the most expert programmers get
> it wrong (I would recommend reading Bentley and Kernighan & Pike,
> amongst others).
> >Consider what happens if you have e.g. a vector of 1000
> >"any" objects. If you copy this vector you are going to get 1000 calls
> >clone() which calls new() 1000 times to allocate a whole bunch of
> >tiny objects (int, double, long, most likely other small & commonly used
> >types). This kind of thing is well known to be quite inefficient
> Have you considered not using strings in your program as well? I hear
> they use dynamic memory ;-)

strings are a different problem. They require variable sized allocations,
any potentially does not. By using a fixed size allocater for the holder
I'm pretty certain you can get significant performance gains.

> >Even if you don't agree with the pool
> >implementation in boost, I think it would be quite good to upgrade "any"
> >take an allocator
> This is a reasonable consideration and has been mentioned before on this
> list, but if I were to introduce it I would need to be convinced that it
> is both effective and genuinely desirable, given the tradeoffs it
> introduces -- it is not, by definition, an "upgrade".

And what exactly is the "downside" of providing a template parameter to take
an allocator. It seems relatively easy to add & I don't see how it would
degrade the existing functionality or performance of any.

>However, in the
> meantime I would recommend that you reread the docs for Boost pool to
> see why it is not appropriate in the case of any.
I read them, and I think it is appropriate & efficient to have the holder
use a pool.

> >so that end-users who don't want their heap trashed can
> >control the allocation behaviour.
> If you have any evidence that any trashes the heap please post it. Such
> a correctness issue is clearly more serious than performance concerns.
I'm quite leery of making lots of calls to new to alloc small blocks after
having gotten bitten by a hard to track memory bug with small reallocs in
VC5 vis

Boost list run by bdawes at, gregod at, cpdaniel at, john at