Boost logo

Boost :

From: Fernando Cacciola (fcacciola_at_[hidden])
Date: 2001-10-17 16:15:11


----- Original Message -----
From: Sebastien Marc <sebmarc_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Wednesday, October 17, 2001 4:24 PM
Subject: RE: [boost] Boosting boost

> [SNIP]
>
> To me, the resulting string s should contain "5" but
> instead the exception is thown.
>
> Seb.
>

There are different issues involved here.
One issue is whether any_cast<> should perform conversions or not, and how
should it behave in case of failure.
Another issue is a problem with the conversion you are expecting to occur.
This issue is not a particularity on the behavior of any_cast<> but a
general confusion with char pointers and char arrays . Let me explain:

Going from "int 5" to a "char const*" that points to the beginning of a
char[2] containing "5\0" is not a 'conversion' (neither a 'cast'), and it
would be incorrect if a 'conversion' function did that.
The conversion from a value of type "int" to a "char const*" is allowed, but
the result is not what you expected.
If any_cast would behave the way you expected, the interface would be
totally ackward.

Consider this:

int v = 5 ;
char const* ptr = static_cast<char const*>(v);

This is perfectly legal, but you shouldn't expect 'ptr' to point to a char
array containing "5\0", but to the address 5.

To understand why, think about this: what does actually take to do the
conversion as you expected it?
'ptr' is just a pointer, so an actual array must be allocated, and the user
(the code using 'ptr') would have to deallocate this array. Unfortunately,
knowing exactly how to, and more importantly, when and whether deallocate
'ptr' is not trivial, so this behavior is typically inappropriate .

The same will happen with any conversion function attempting to convert from
anything into its 'literal representation' returning a 'char counts*',
because the string must be placed in a char array, but a char pointer is not
a char array.

For example, the following doesn't work either:

char const* ptr = boost::lexical_cast<char const*>(v);

Now, the root of the confusion is in the abused C analogy between a 'char
const[]' and a 'char const*'. They might be used indistinctly in many
places, but they are totally different objects.

In other words, what you really want is to convert from an integer into a
array of chars, which is a perfectly reasonable conversion, but you are
specifying 'char const*' as the target type, but a 'char const*' is not a
char array, just a pointer to the first element of such an array.

You example is a bit tricky because the 'char const*' acts as a temporary,
obscuring the details explained above.
Consider:

char const* convert( int n )
{
   char* array = new char [ std::numeric_limits<int>::digits10 + 1 ] ;
   sfprintf(array,"%d",n);
   return array ;
}

int v = 5 ;
string s = convert(v);

This code is nearly identical to what you expected to be the behavior of
any_cast<>.
However, it has a subtle flaw: it leaks the char array.
Just exactly the same would happen if any_cast<char const*> (or
lexical_cast<char const*>, for that matter), would return
a char array filled with the lexical representation of its data.

Now, having understood why a conversion function intended to return a char
array cannot return a char pointer (they are different objects), its easy to
see what the true solution would be: Convert not to 'char const*' but to
'string' (or any other char array wrapper). That is, you might have expected
this to work:

  any a1 = 5;
  string s;
  s = any_cast<string>(a1);

However, as pointed out by William Kempf, 'any' is intentionally designed to
disallow this sort of conversion. But, as shown by Steve, you can use
lexical_cast<> to achieve that:

  any a1 = 5;
  string s;
  s = lexical_cast<string>(any_cast<int>(a1));

I hope this made things more clear.

Fernando Cacciola
Sierra s.r.l.
fcacciola_at_[hidden]
www.gosierra.com


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