From: Kevlin Henney (kevlin_at_[hidden])
Date: 2001-07-16 02:29:16
Corwin Joy writes
>> This latter suggestion would
>> generally be more frustrating to users than it would be useful, eg
>> boost::any value;
>> std::cin >> value;
>> would fail because value has no current type.
>This is not a problem with the stream operator. Rather this is a problem
>with the "any" class. Frankly it's quite goofy the way this class default
>constructs with an artificial void/empty type. Better would be to not allow
>default construction of an "any" object than to have this artificial empty
>type. Anyway, if one stays with the flawed way that "any" currently default
>constructs I don't find it at all unreasonable for the stream operator to
>fail / throw in the case of streaming into an empty type.
WADR, I think that perhaps goofiness is in the eye of the beholder:
default construction is perfectly natural for both specific and variant
value types. I believe you may be in a minority -- perhaps even of one -
- to think otherwise.
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
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
>> 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 many
>times when you want to use "any" as a kind of prototype design where 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.
>It is true this is an inefficient solution if the op is common. My point is
>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.
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. Andrew Koenig wrote an article on these issues many
years ago, in JOOP I believe, although I do not have the reference to
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. 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 get
>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.
>> Have you demonstrated this thrashing? I haven't explored this in detail,
>> 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
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,
>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 to
>clone() which calls new() 1000 times to allocate a whole bunch of typically
>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 ;-)
>Even if you don't agree with the pool
>implementation in boost, I think it would be quite good to upgrade "any" to
>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". 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.
>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.
Kevlin Henney phone: +44 117 942 2990
Curbralan Limited mobile: +44 7801 073 508
mailto:kevlin_at_[hidden] fax: +44 870 052 2289
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk