Boost logo

Boost :

From: Kevlin Henney (kevlin_at_[hidden])
Date: 2001-07-14 05:50:12


In message <003001c10c2c$7faf3e10$2101bf0a_at_[hidden]>, Corwin Joy
<cjoy_at_[hidden]> writes
>Proposal 1: A second "any" class which I will call anyx (for "any"
>eXtractable).

I think a different name would be appropriate, as many will mistake this
for the uninformative but common "x" as "extended" naming convention.

>This is the same as the any class but with stream operators
>i.e.
>
> class anyx
> {
> public:
> friend std::ostream & operator <<(std::ostream &o, const anyx &x)
> friend std::istream & operator >>(std::istream &i, const anyx &x);

That these are friend operators is an implementation assumption. Also, I
think you meant to omit the const on the any reference for stream
extraction.

>...skip the obvious implementation with virtual functions etc...

Actually, I don't think this is something that you can skip. What is the
"obvious" implementation? Output is trivial, but what do you intend for
input? Are you proposing a full-blown factory mechanism that can somehow
identify the type on the stream or are you assuming that input for an
any will be based on its current type? 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. 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

>There are two reasons why this would be nice:
>1. You often want to send a variant type to a stream or output.
>2. If you really want a cast operator from any you can now get it via:
>
>any a("3.1415");
>double d = lexical_cast<double>(a);

If this kind of code is common, eg moving between text and numbers, then
any is the wrong solution: string and lexical_cast provide a more
appropriate approach.

>Also, this lexical cast is pretty inefficient if you want to cast across
>pure numeric types. It would be nice to have the equivalent of numeric_cast
>working with any. Surprisingly, I think this can also be done.

You're right, I'm surprised ;-) Surprised at both the alleged
inefficiency -- inefficient wrt what exactly? -- and surprised that it
could be done in an effective manner without changing the basic intent
of any: values are held but not interpreted.

>So, lets
>say the numeric types you are using with any can be safely upcast to doubles

If they can be safely upcast to a double, then the type you want to use
is a double not an any.

>(if you have numeric types that can't be upcast to a double such as
>arbitrarily long integers we can specialize the templated "holder" class to
>upcast to some other type -- this implies that holder has to go outside the
>"any" class since sub-class templates can't be specialized).

Do you mean nested class not subclass? But how would this help? The
holder would now know about a type of greater precision. However,
because any would be written against the interface of placeholder, which
would presumably only know about double, it could not take advantage of
this greater precision. This whole problem would be made trivial with
virtual member templates, but as they are not supported then the problem
throws up more issues than practical solutions.

>Then, numeric
>class might look like this inside any:
>class any {
> template<typename Target> Target numeric_cast(Target *dmy) {

Why would this be a non-static member of any? And what is the role of
the pointer argument? What is intended syntax for usage that you are
after?

> // Step 1: Get numeric_limits for any "content", and the sign value
>for content. Throw if these are not compatible with the target type.

Given that numeric_limits is templated, how do you plan to get the
correct values from the content? Return them as double? And what were
you planning to do for non-numerics?

> // Step 2: upcast content to "root" type, e.g. double
> // Step 3: downcast "root" type to Target
>}
>
>// There are some tricks in the above if you have multiple possible root
>types - I can discuss if there is interest

IMHO, I think this needs more than tricks to be a satisfactory, simple
and safe facility.

>Suggestion 2:
>The current "any" is quite inefficient in that both the clone and the
>constructor allocate with just a simple new. If you are using a lot of
>"any" instances this is going to thrash the allocater & be quite
>inefficient. I think it would be very nice to take advantage of the boost
>pooled memory allocator here.

Have you demonstrated this thrashing? I haven't explored this in detail,
but for many uses of any you seem to get good recycling.

Sorry if I sound a little cynical about these proposals, but they do not
really seem to add anything -- and may indeed detract -- from the
current any class.

Kevlin
____________________________________________________________

  Kevlin Henney phone: +44 117 942 2990
  Curbralan Limited mobile: +44 7801 073 508
  mailto:kevlin_at_[hidden] fax: +44 870 052 2289
  http://www.curbralan.com
____________________________________________________________


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk