[boost] [lexical_cast] A suggestion

36 views
Skip to first unread message

Vladimir Batov

unread,
Jan 13, 2009, 7:26:04 AM1/13/09
to Boost Developers' List
I use boost::lexical_cast quite a bit. Possibly due to specifics of my task I constantly stumble upon two things:

1. It throws if/when conversion fails;
2. It requires the 'Target' class to be default-constructible.

I'd like to suggest extending the existing

template<class Target, class Source>
Target
lexical_cast(Source const& arg)

interface with

template<class Target, class Source>
Target
lexical_cast(Source const& arg, Target const& failure_value)

The behavior of the latter would be to return the 'failure_value' if/when the conversion fails. That communicates the fact of the conversion failure differently (without an exception thrown), i.e. its usage would be as following:

int value = boost::lexical_cast(some-string, -1);
if (value == -1) conversion failed.

In fact, my usage pattern is such that I often do not even need to check the success of the conversion -- if the conversion fails, the supplied failure/default value is returned/used and proceeded with.

Secondly, the proposed lexical_cast requirements would be looser -- no need for the default-constructibility of the Target, only the copy-constructibility (as already required anyway). For that the current lexical_cast implementation

if(interpreter << arg) {
Target result;
if (interpreter >> result)
return result;
}
throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
return Target(); // normally never reached (throw_exception)

would change (for the proposed interface) to something like

if(interpreter << arg) {
Target result(failure_value);
if (interpreter >> result)
return result;
}
return failure_value;

I am not sure how much value such an interface extension might have for others but for my usage pattern the benefit would be quite visible as the majority of our classes are with no default constructors and handling conversion-failure exceptions is quite a hassle... not to mention that for whatever guided/misguided reasons exceptions are virtually banned for our mission-critical development.

Best,
V.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Neil Groves

unread,
Jan 13, 2009, 7:39:34 AM1/13/09
to bo...@lists.boost.org
I would like to add my support for this proposed change:

I have similar use-cases where I require a non-throwing implementation and
hence I have to, reluctantly avoid lexical_cast. This change appears to be
very compelling.


>
> Best,
> V.


Neil Groves

Deane Yang

unread,
Jan 13, 2009, 9:22:09 AM1/13/09
to bo...@lists.boost.org
Neil Groves wrote:
> I would like to add my support for this proposed change:


Me, too.

Neil Groves

unread,
Jan 13, 2009, 11:13:04 AM1/13/09
to bo...@lists.boost.org
On Tue, Jan 13, 2009 at 3:50 PM, Chris Weed <chri...@gmail.com> wrote:

> On Tue, Jan 13, 2009 at 7:26 AM, Vladimir Batov <ba...@people.net.au>
> wrote:
> >
> > I use boost::lexical_cast quite a bit. Possibly due to specifics of my
> task I constantly stumble upon two things:
> >
> > 1. It throws if/when conversion fails;
> > 2. It requires the 'Target' class to be default-constructible.
> >
> > I'd like to suggest extending the existing
> >
> > template<class Target, class Source>
> > Target
> > lexical_cast(Source const& arg)
> >
> > interface with
> >
> > template<class Target, class Source>
> > Target
> > lexical_cast(Source const& arg, Target const& failure_value)
> >
> > The behavior of the latter would be to return the 'failure_value' if/when
> the conversion fails. That communicates the fact of the conversion failure
> differently (without an exception thrown), i.e. its usage would be as
> following:
> >
> > int value = boost::lexical_cast(some-string, -1);
> > if (value == -1) conversion failed.
> >
> > In fact, my usage pattern is such that I often do not even need to check
> the success of the conversion -- if the conversion fails, the supplied
> failure/default value is returned/used and proceeded with.
> >
>

> This doesn't look like a good interface due to using a casted value as
> a "null"-code. This code would fail when "-1" is a value of
> some-string. This could lead to very big problems!
> I would suggest something more like
> boost::optional<int> value =
> boost::lexical_cast(some-string,boost::no_throw);
> if(!value) conversion failed.
>

I prefer the original suggestion of providing a failure value for most of my
uses because:
1. Often I do not want to check an error, I have a value in mind to use in
the case of error
2. It removes the requirment for a default constructor

I see that if we need to handle an error condition then the ability to
return an optional<Target> is a good plan. Perhaps two new overloads would
be optimal?

Neil Groves


> Chris

Alexander Nasonov

unread,
Jan 13, 2009, 11:21:44 AM1/13/09
to bo...@lists.boost.org
Vladimir Batov <batov <at> people.net.au> writes:

> int value = boost::lexical_cast(some-string, -1);
> if (value == -1) conversion failed.

I know that you know this but lexical_cast was designed to be
constistent with {static,const,reinterpret}_cast<Target>(source).

It doesn't have to be named lexical_cast. Most likely you're converting
from a string, you could name it from_string or something similar.
--
Alex

Alexander Nasonov

unread,
Jan 13, 2009, 11:29:17 AM1/13/09
to bo...@lists.boost.org
Neil Groves <neil <at> grovescomputing.com> writes:

> I see that if we need to handle an error condition then the ability to
> return an optional<Target> is a good plan. Perhaps two new overloads would
> be optimal?

This looks interesting but boost::optional<T> is already InputStreamable:
#include <boost/optional/optional_io.hpp>

Alex

Vladimir Batov

unread,
Jan 14, 2009, 12:41:25 AM1/14/09
to bo...@lists.boost.org
> ...

> This doesn't look like a good interface due to using a casted value as
> a "null"-code. This code would fail when "-1" is a value of
> some-string. This could lead to very big problems!
> I would suggest something more like
> boost::optional<int> value =
> boost::lexical_cast(some-string,boost::no_throw);
> if(!value) conversion failed.

Well, "very big problems" sounds like a stretch. I've been using a
lexical_cast equivalent in that fashion and in practice very often there are
values that are well out our sensible range. If, say, -1 is no good then
something like INT_MAX might well be. Quite often though I do not even need
to look for a ""null"-code" as I provide the *default* value instead. I.e. a
value inside the sensible range that I proceed with when the conversion
fails. If all that is no good, then I'd expect the existing interface to
come to the rescue.

In addition, the interface above does not seem to address #2, i.e. the
default-constructability requirement of the Target which for my a big
hassle.

Vladimir Batov

unread,
Jan 14, 2009, 1:18:30 AM1/14/09
to bo...@lists.boost.org
> I know that you know this but lexical_cast was designed to be
> consistent with {static,const,reinterpret}_cast<Target>(source).

Understood. I do not think though that it might be an issue. The similarity
is only cosmetic as the group is supported by the language, works with types
when lexical_cast is a library solution, works with values. So, in fact, the
user has to learn lexical_cast *not* to use it as the "real" type casts.
More so, I'd expect lexical_cast interface extended without interrupting
whatever impression/behavior the user has established in relation with the
current interface.

> It doesn't have to be named lexical_cast. Most likely you're converting
> from a string, you could name it from_string or something similar.

I indeed often (in 70%) use it for string-to-something conversion. However,
for the remaining 30% I need it beyond string-to/from conversion. As for
"from_string" I certainly had to do something along the lines for myself.
However, beyond my private sandbox I am always reluctant introducing a new
vocabulary when the existing can be sensibly reused and (IMHO) improved.

Best,
V.

Andrew Troschinetz

unread,
Jan 13, 2009, 11:56:37 PM1/13/09
to bo...@lists.boost.org
Alexander Nasonov <alnsn <at> yandex.ru> writes:

> This looks interesting but boost::optional<T> is already
> InputStreamable:
> #include <boost/optional/optional_io.hpp>

This sounded really cool to me so I attempted a cursory hack to get
this working. The only way I could figure out how to provide an
override for optional<T> that never throws was to change
detail::lexical_cast from a function to a struct to get partial
template specialization. Maybe there is a better way, I'm new at this.
It seems like there must be because I wound up with lots of almost-
duplicated code.

Here's the old familiar detail::lexical_cast, structified:

structified
optional

Vladimir Batov

unread,
Jan 30, 2009, 8:12:46 PM1/30/09
to bo...@lists.boost.org
With no volunteeres coming forward :-) , I am considering extending the
lexical_cast interface as described below. Is there any chance of that
change integrated? Is there a process to achieve that? I understand it would
go through an acceptance review as for new components but it has to go
through some kind of review, check. Is there anyone at present
supporting/maintaining the component? I understand these might be
boring/annoying questions for seasoned boosters. My humble apologies go to
them. Any pointers would be immensely appreciated.

Best,
V.

Alexander Nasonov

unread,
Feb 2, 2009, 5:59:58 AM2/2/09
to bo...@lists.boost.org
Vladimir Batov <batov <at> people.net.au> writes:

> With no volunteeres coming forward , I am considering extending the

> lexical_cast interface as described below. Is there any chance of that
> change integrated?

I'm againt this change. See my other messages in this thread for details.

> Is there anyone at present supporting/maintaining the component?

I'm a maintainer.

If you really want to push this change, you should involve the C++
committee, especially the authors of N1973 Kevlin Henney and Beman Dawes.

Thanks,
Alex

Vladimir Batov

unread,
Feb 3, 2009, 12:41:20 AM2/3/09
to bo...@lists.boost.org, kev...@curbralan.com, Home
Alex,

Thank you for getting back to me. Much appreciated.

> I'm against this change. See my other messages in this thread for details.

Well, I certainly read your messages in the thread and somehow they did not
come across as you were against. It's certainly clear now. Even though I was
not proposing to change anything. It was clearly an addition, i.e. it would
not have any disruptive impact. However, the practical usefulness of that
addition is substantial (well, for my and I suspect others usage pattern).

> I'm a maintainer.

Thanks for the info.

> If you really want to push this change, you should involve the C++
> committee, especially the authors of N1973 Kevlin Henney and Beman Dawes.

I am CCing the authors. Maybe they see it in a more favorable light. :-) Not
sure through if they get back to me/us on that.

Best,
V.

Kevlin Henney

unread,
Feb 3, 2009, 4:52:08 AM2/3/09
to Vladimir Batov, bo...@lists.boost.org
Hi,

> Well, I certainly read your messages in the thread and somehow they
> did not come across as you were against. It's certainly clear now.
> Even though I was not proposing to change anything. It was clearly an
> addition, i.e. it would not have any disruptive impact. However, the
> practical usefulness of that addition is substantial (well, for my and
> I suspect others usage pattern).

[...]


>> If you really want to push this change, you should involve the C++
>> committee, especially the authors of N1973 Kevlin Henney and Beman
>> Dawes.
>
> I am CCing the authors. Maybe they see it in a more favorable light.
> :-) Not sure through if they get back to me/us on that.

I haven't been following the discussion, so would it be possible for you
to provide some context/background?

Thanks,

Kevlin

--
____________________________________________________________

Kevlin Henney phone: +44 117 942 2990
mailto:kev...@curbralan.com mobile: +44 7801 073 508
http://curbralan.com fax: +44 870 052 2289
Curbralan: Consultancy + Training + Development + Review
____________________________________________________________

Michael Fawcett

unread,
Feb 3, 2009, 12:23:04 PM2/3/09
to bo...@lists.boost.org
On Tue, Feb 3, 2009 at 12:41 AM, Vladimir Batov <ba...@people.net.au> wrote:
>
> not have any disruptive impact. However, the practical usefulness of that
> addition is substantial (well, for my and I suspect others usage pattern).

Just to jump in here, I'm one of those "others". I ended up writing a
function that try'd the lexical_cast, then on exception, returned the
default value that was passed to the function. I used this often in
parsing files. It looked something like:

template <typename T, typename S>
T try_lexical_cast(const S &value, T default_value)
{ /* stuff */ }

It would be really nice if we didn't have to pay for the cost of an
exception every time that happens in cases where we are expecting lots
of failures but also have an appropriate default value on hand.

And, to be clear, I am *for* Vladimir's addition.

--Michael Fawcett

Vladimir Batov

unread,
Feb 3, 2009, 4:35:42 PM2/3/09
to bo...@lists.boost.org, kev...@curbralan.com, Home
Kevlin,

Thank you for your prompt reply. Much appreciated.

> I haven't been following the discussion, so would it be possible for you
> to provide some context/background?

To see all opinions expressed the discussion could be found at
http://groups.google.com/group/boost-developers-archive/browse_thread/thread/52fd3afc05f64a02#

The description of my suggestion/request is as follows:

boost::lexical_cast is very important to me and I use it quite a bit.
Possibly due to specifics of my task I constantly struggle with two things:

1. It throws an exception if/when conversion fails (which is not an
exceptional situation);
2. It requires the 'Target' class to be default-constructible (many of my
classes do not have).

I'd like to suggest extending (no disruption to the existing
interface/users) the existing

template<class Target, class Source>
Target
lexical_cast(Source const& arg)

interface with

template<class Target, class Source>
Target

lexical_cast(Source const& arg, Target const& default_value)

The behavior of the latter would be to return the 'default_value' if/when

the conversion fails. That communicates the fact of the conversion failure

differently (without an exception thrown) as IMHO a conversion failure is
not really that exceptional (rather common). The usage would be something
like:

int value = boost::lexical_cast(some-string, -1);
if (value == -1) conversion failed.

In fact, my usage pattern is such that I often do not even check the success

of the conversion -- if the conversion fails, the supplied failure/default
value is returned/used and proceeded with.

Equally importantly, the requirements of the proposed/extended lexical_cast
would be looser -- no need for the default-constructability of the Target,
only the copy-constructability.

That proposed/additional lexical_cast interface would be implemented
something like

if(interpreter << arg) {
Target result(failure_value);
if (interpreter >> result)
return result;
}
return failure_value;

as opposed to the current lexical_cast implementation:

if(interpreter << arg) {
Target result;
if (interpreter >> result)
return result;
}
throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
return Target(); // normally never reached (throw_exception)

I am not sure how much value such an interface extension might have
community-wide (although a few people on the list expressed their support)
but for our deployment the benefit would be quite substantial as the
majority of our classes are with no default constructors. That's been a
serious stumbling block for us adopting lexical_cast as-is (I had to write a
replacement). Having to provide the default constructor for such classes is
a huge hassle for the developer and wide-open for eventual abuse/confusion.

Having to handle bad_lexical_cast exceptions is in all honesty quite a
hassle (with my usage pattern) and probably not exactly justified as there
is nothing exceptional about failed conversion (more like I could not open a
file)... not to mention that for whatever guided/misguided reasons

exceptions are virtually banned for our mission-critical development.

Thank you for your consideration. Looking forward to hearing from you.

Best,
V.

Vladimir Batov

unread,
Feb 3, 2009, 4:35:48 PM2/3/09
to bo...@lists.boost.org

----- Original Message -----
From: "Vladimir Batov" <ba...@people.net.au>
Newsgroups: gmane.comp.lib.boost.devel
To: "Boost Developers' List" <bo...@lists.boost.org>
Sent: Tuesday, January 13, 2009 11:26 PM
Subject: [lexical_cast] A suggestion

Andrew Troschinetz

unread,
Feb 4, 2009, 11:31:50 AM2/4/09
to bo...@lists.boost.org
On Feb 3, 2009, at 3:35 PM, Vladimir Batov wrote:

> I'd like to suggest extending (no disruption to the existing
> interface/users) the existing
>
> template<class Target, class Source>
> Target
> lexical_cast(Source const& arg)
>
> interface with
>
> template<class Target, class Source>
> Target
> lexical_cast(Source const& arg, Target const& default_value)
>
> The behavior of the latter would be to return the 'default_value' if/
> when the conversion fails. That communicates the fact of the
> conversion failure differently (without an exception thrown) as IMHO
> a conversion failure is not really that exceptional (rather common).

Last time this topic came up I took some time to modify
lexical_cast.hpp (starting from boost 1.37.0 source) to fit this
interface. I also added a specialization for boost::optional<T> that
instead of throwing bad_lexical_cast, simply returned an empty
optional type (which required rewriting optional_io.hpp, as I believe
it has a bug: https://svn.boost.org/trac/boost/ticket/2659 ).

Here's some example usage: http://codepad.org/hn6MjKjm

modified lexical_cast.hpp: http://codepad.org/JAA4Me9Q
modified optional_io.hpp: http://codepad.org/8ablH1Nq

I too would love to see these extensions to lexical_cast, but in the
meantime I've been using these modified versions. Just thought I'd
share them in case anyone else was interested.

--
Andrew Troschinetz
Applied Research Laboratories

Alexander Nasonov

unread,
Feb 4, 2009, 11:53:07 AM2/4/09
to bo...@lists.boost.org
Andrew Troschinetz <ast <at> arlut.utexas.edu> writes:

> Here's some example usage: http://codepad.org/hn6MjKjm

It's not clear from the example that this inliner

lexical_cast< optional<int> >("x").get_value_or(-1);

is a replacement for

lexical_cast("x", -1);

It's not conceptually correct but we already have an exception for
handling spaces in strings. I should think about making one more
exception for optional<T>. Though, the inliner is not short,
not sure people will like it.

--
Alex

Andrew Troschinetz

unread,
Feb 4, 2009, 12:27:33 PM2/4/09
to bo...@lists.boost.org
On Feb 4, 2009, at 10:53 AM, Alexander Nasonov wrote:

> Andrew Troschinetz <ast <at> arlut.utexas.edu> writes:
>
>> Here's some example usage: http://codepad.org/hn6MjKjm
>
> It's not clear from the example that this inliner
>
> lexical_cast< optional<int> >("x").get_value_or(-1);
>
> is a replacement for
>
> lexical_cast("x", -1);


I actually hadn't thought of that inliner, but now that I see it I
prefer it because I think it's cleaner conceptually and from an
interface standpoint. It also means there's no need for a lexical_cast
specialization for optional types, which I wrote all the while with a
feeling of "there must be a better way to do this."

But that inliner still doesn't get around the problem of types that
aren't default constructible.

--
Andrew Troschinetz
Applied Research Laboratories

_______________________________________________

Vladimir Batov

unread,
Feb 5, 2009, 7:52:11 AM2/5/09
to bo...@lists.boost.org
> ... But that inliner still doesn't get around the problem of types that
> aren't default constructible.

IMHO the default-constractibility requirement is unfortunate and in my
particular case is not achievable. Understandably a library can only create
an object it knows nothing about by imposing certain conditions (like
demanding a certain constructor). Therefore, I'd consider any attempt to
avoid that "delicate" situation to be a good design philosophy as it extends
the applicability scope.

Best,
V.

Alexander Nasonov

unread,
Feb 6, 2009, 11:03:31 AM2/6/09
to bo...@lists.boost.org
Alexander Nasonov <alnsn <at> yandex.ru> writes:

> lexical_cast< optional<int> >("x").get_value_or(-1);

> [...]


> It's not conceptually correct but we already have an exception for
> handling spaces in strings. I should think about making one more
> exception for optional<T>. Though, the inliner is not short,
> not sure people will like it.

I can confirm that this is Kevlin's prefered option.

See for example this discussion:

http://lists.boost.org/Archives/boost/2005/05/86492.php

Andrey Semashev

unread,
Feb 6, 2009, 12:36:34 PM2/6/09
to bo...@lists.boost.org
Alexander Nasonov wrote:
> Andrew Troschinetz <ast <at> arlut.utexas.edu> writes:
>
>> Here's some example usage: http://codepad.org/hn6MjKjm
>
> It's not clear from the example that this inliner
>
> lexical_cast< optional<int> >("x").get_value_or(-1);
>
> is a replacement for
>
> lexical_cast("x", -1);
>
> It's not conceptually correct but we already have an exception for
> handling spaces in strings. I should think about making one more
> exception for optional<T>. Though, the inliner is not short,
> not sure people will like it.

First of all, I think this would be useful addition. Quite often I do
need to supply a default value that will be returned if the conversion
fails.

However, I'd rather opt for not involving optional into this. Not only
does it make the expression longer and less clean, it introduces a
dependency on another library and makes me wonder how can I lexical_cast
optionals. I like the lexical_cast< int >("x", -1); syntax much more.

If the syntax is considered unacceptable, I can suggest another alternative:

int x = lex_cast< int >("x").with_default(10);
int y = lex_cast< int >("y").or_default_constructed();

The trick is that lex_cast returns a proxy that can either be converted
to int (in which case it does the regular lexical_cast) or can be used
to provide additional tweaks, like the ones above.

Obviously, the function name should be different from lexical_cast, as
it can be incompatible in some cases.

Vladimir Batov

unread,
Feb 6, 2009, 5:01:26 PM2/6/09
to bo...@lists.boost.org
> ... I like the lexical_cast< int >("x", -1); syntax much more.

>
> If the syntax is considered unacceptable, I can suggest another
> alternative:
>
> int x = lex_cast< int >("x").with_default(10);
> int y = lex_cast< int >("y").or_default_constructed();

The situation with the additional default parameter to lexical_cast is just
crazy. People clearly need the behavior and have been asking for it since
2005 and they still get nothing but excuses and explanations instead. In
fact, according to Kevlin's
http://lists.boost.org/Archives/boost/2005/05/85519.php post it was the
original behavior. I greatly appreciate Kevlin's contribution but
unfortunately in the current form lexical_cast is hardly useful to me (and I
suspect many others) -- throwing an exception (and having to process it) on
something as mundane as string conversion failure is, well, a bit
heavy-handed -- it results in unbelievably messy and ugly code. The second
issue (actually *first* for me) is the default-constructability.

I can understand Kevlin's reaction like "we looked at the possibilities, we
rejected them". Well, maybe it is time to have a look again. We make wrong
decisions all the time. There is nothing wrong in revisiting/re-evaluating
old decisions as we get more experience.

I sympathize with the idealistic desire for lexical_cast to look like the
dynamic_cast et al. The problem is that no matter how you make lexical_cast
look it does not do what other language-supported casts do -- dynamic_cast
el al work with *types*, lexical_cast works with *values*. Making
lexical_cast look like what it is not (the "real" casts) has no practical
value and is just misleading.

Now seemingly out of desperation people are venturing into

lexical_cast<optional>


lex_cast< int >("x").with_default(10);

lex_cast< int >("y").or_default_constructed();

It's just crazy from the usability point of view. Are you sure users will
appreciate all that mounting complexity on top of lexical_cast? All that is
needed

lexical_cast(Source const&, Target const& =Target())

or most likely a completely independent overload

lexical_cast(Source const&, Target const&)

That overload can live side-by-side with the original lexical_cast without
disturbing it... unless "lexical_cast" character sequence has been
trade-marked. I'll be first to use it.

I need scissors with two rings for fingers. The scissors' designer might
strongly insist on a variation with just one ring for one finger due to its
minimalist and beautiful design looking like something else. It has no
*practical* use for me. We can strike a compromise or I'll have to go
someplace else. That's what I understand has been happening since 2005 --
people have been simply turned away and that is wrong -- we write code for
people and want people using our code (I do). C++ is full of compromises --
compromises due to C compatibility, usability, just convenience. People love
it.

Best,
V.

Scott McMurray

unread,
Feb 6, 2009, 7:27:24 PM2/6/09
to bo...@lists.boost.org
On Fri, Feb 6, 2009 at 17:01, Vladimir Batov <ba...@people.net.au> wrote:
>
> I sympathize with the idealistic desire for lexical_cast to look like the
> dynamic_cast et al. The problem is that no matter how you make lexical_cast
> look it does not do what other language-supported casts do -- dynamic_cast
> el al work with *types*, lexical_cast works with *values*. Making
> lexical_cast look like what it is not (the "real" casts) has no practical
> value and is just misleading.
>

I have no idea what you mean by dynamic_cast working with "types" not
"values". static_cast<float>(1000000000u) drastically changes the
representation and the type, just like
lexical_cast<float>("1000000000") does.

And optional<> is not that strange. The first example in its
documentation is "optional return values" (
http://www.boost.org/doc/libs/1_37_0/libs/optional/doc/html/boost_optional/examples.html#boost_optional.examples.optional_return_values
), which is exactly what

attempt_lexical_cast<T>(x) just calling lexical_cast<optional<T> >(x)
makes perfect sense to me, though it's so trivial that it seems like a
waste to provide the extra function. Having the different semantics
for the different type is just like dynamic_cast, just this one uses
optional instead of *.

One very clear use:

if (optional<int> oi = lexical_cast<optional<int> >(mystring)) {
int i = *oi;
... use i ...
} else {
... parse failed ...
}

And if you want defaults:

int i = -1;
if (optional<int> oi = lexical_cast<optional<int> >(mystring)) {
i = *oi;
}
... use i ...

Or, using the helper:

int i = lexical_cast<optional<int> >(mystring).get_value_or(-1);

Why is this so bad?

Vladimir Batov

unread,
Feb 6, 2009, 8:24:05 PM2/6/09
to bo...@lists.boost.org
> I have no idea what you mean by dynamic_cast working with "types" not
> "values".

I am sure to do:

Foo& foo = dynamic_cast<Foo&>(moo);
Foo& foo = const_cast<Foo&>(moo);

same instance, different type.

> static_cast<float>(1000000000u) drastically changes the
> representation and the type,

Yes, for static_cast I'll give you that. However, it is not static_cast
*own* quality as it simply piggy-backs on the built-in *language* support
for conversions between *related* types. That way, static_cast is nothing
more but syntactic sugar as "float foo = 10u" will just do.

> just like
> lexical_cast<float>("1000000000") does.

lexical_cast is different as it's not jusr sugar-coating and "float foo =
"10" " wil not take you anywhere. Therefore, if we have to find the closest
?_cast that lexical_cast looks like, then, I'd choose reinterpret_cast --
conversions between *unrelated* types. And I am personally not exactly
comfortable with that comparison as I do not see it serving any useful
purpose.

All in all, these language-supported casts behave *differently* -- the
purpose is the paramaunt. It is arguable if their visual similarity is
beneficial or a hindrance (the user still need to understand their
differences and usage subtleties). Now lexical_cast steps in and seemingly
sactifices usefulness/purpose for appearance. Not the right choice is you
ask me (you obviously are free to disagree).

> And optional<> is not that strange.

To start with "strangeness" is subjective. And that is last of my worries. I
thought I voiced my reasons against it -- it still requires the
default-constructability. I work with quite complex classes which happen not
to have the default constructor. Second, IMHO lexical_cast is seemingly
straightforward (easy to grasp for a casual user). Throwing optional<> into
the mix does not seem justified (that's surely subjective unlike the
default-constructability).

> Or, using the helper:
>
> int i = lexical_cast<optional<int> >(mystring).get_value_or(-1);
>
> Why is this so bad?

Well, if you want lexical_cast (and Boost) *not* used in the wide, then keep
mounting these wonderful complexities and interfaces. Surely the users will
be very supportive of your effort.

Best,
V.

Vladimir Batov

unread,
Feb 6, 2009, 11:02:28 PM2/6/09
to bo...@lists.boost.org
>> int i = lexical_cast<optional<int> >(mystring).get_value_or(-1);
>>
>> Why is this so bad?
>
> Well, if you want lexical_cast (and Boost) *not* used in the wide, then keep
> mounting these wonderful complexities and interfaces. Surely the users will
> be very supportive of your effort.

Well, that was somewhat terse and unfriendly. Apologies. I'll elaborate and give you metrics.

1. int i = lexical_cast<optional<int> >(mystring).get_value_or(-1);
2. int i = lexical_cast(mystring, -1);

#1 and #2 do exactly the same (although #2 does it better as it does not demand default-constructability). However, #1 has 3 new special-vocabulary elements (lexical_cast, optional, get_value_or) vs. just one entry for #2. I.e the entry level for a user to deploy #1 is at least 3 times higher than #2. You might say -- "no, big deal, I already know all that". You most likely do. Others might not. Application programmers often can qualify only as casual Boost users. And often it's not entirely their fault as they have a lot to know/care about beyond Boost (like their domain-specific stuff). Unfortunately, learning something new for those app. programmers is often secondary (unfortunate but fact) as they are too busy coding their domain-specific stuff. Therefore, learning something new can only be learnt if it passes some mental complexity level and if it fits some mentally allocated time. If learning/diversion spills over complexity/time limits, that new thing is dropped and so
mething is hand-coded the ugly way. I personally want (for selfish reasons) to see those guys engaged and using Boost rather than repelled by interface/deployment complexity.

Another thing is that #1 is twice as long (and IMHO ugly :-) ). In isolation it might be OK (the length it is). On a bigger scale you are suggesting I write twice as much code as I have to. With #1 I'll have to spend one hour writing code when with #2 I could spend only half an hour writing code and the remaining half an hour enjoying myself ;-). Then, I'll have twice as much code to proof-read, to debug, to maintain, to test. As it is pretty much what I do all day long, you just robbed me of half my working day (or made me work twice as hard). All that for what? Some abstract idea/ideal of keeping lexical_cast looking similar to static_cast?

Michael Fawcett

unread,
Feb 7, 2009, 2:01:02 AM2/7/09
to bo...@lists.boost.org
On Fri, Feb 6, 2009 at 11:02 PM, Vladimir Batov <ba...@people.net.au> wrote:
>>> int i = lexical_cast<optional<int> >(mystring).get_value_or(-1);
>>>
>>> Why is this so bad?
>>
>> Well, if you want lexical_cast (and Boost) *not* used in the wide, then keep
>> mounting these wonderful complexities and interfaces. Surely the users will
>> be very supportive of your effort.
>
> Well, that was somewhat terse and unfriendly. Apologies. I'll elaborate and give you metrics.
>
> 1. int i = lexical_cast<optional<int> >(mystring).get_value_or(-1);

Please, no.

> 2. int i = lexical_cast(mystring, -1);

Again, +1 from me. I have the exact same use case, and the same
desire as Vladimir.

--Michael Fawcett

Andrey Semashev

unread,
Feb 7, 2009, 5:19:56 AM2/7/09
to bo...@lists.boost.org
Vladimir Batov wrote:
>> ... I like the lexical_cast< int >("x", -1); syntax much more.
>>
>> If the syntax is considered unacceptable, I can suggest another
>> alternative:
>>
>> int x = lex_cast< int >("x").with_default(10);
>> int y = lex_cast< int >("y").or_default_constructed();
>
>
> I sympathize with the idealistic desire for lexical_cast to look like
> the dynamic_cast et al. The problem is that no matter how you make
> lexical_cast look it does not do what other language-supported casts do
> -- dynamic_cast el al work with *types*, lexical_cast works with
> *values*. Making lexical_cast look like what it is not (the "real"
> casts) has no practical value and is just misleading.

I disagree. Making lexical_cast behave similar to other casts makes
perfect sense. It does change the type of its argument just as well as
its physical representation.

> Now seemingly out of desperation people are venturing into
>
> lexical_cast<optional>
> lex_cast< int >("x").with_default(10);
> lex_cast< int >("y").or_default_constructed();
>
> It's just crazy from the usability point of view. Are you sure users
> will appreciate all that mounting complexity on top of lexical_cast? All
> that is needed
>
> lexical_cast(Source const&, Target const& =Target())

No, that kind of implementation seems unacceptable to me. I want
lexical_cast to throw exceptions just as often as I don't want it to.
And, of course, I'm against introducing a breaking change.

> or most likely a completely independent overload
>
> lexical_cast(Source const&, Target const&)

That would be my preferred way to implement this extension.

Andrey Semashev

unread,
Feb 7, 2009, 5:25:17 AM2/7/09
to bo...@lists.boost.org
Scott McMurray wrote:

> One very clear use:
>
> if (optional<int> oi = lexical_cast<optional<int> >(mystring)) {
> int i = *oi;
> ... use i ...
> } else {
> ... parse failed ...
> }
>
> And if you want defaults:
>
> int i = -1;
> if (optional<int> oi = lexical_cast<optional<int> >(mystring)) {
> i = *oi;
> }
> ... use i ...
>
> Or, using the helper:
>
> int i = lexical_cast<optional<int> >(mystring).get_value_or(-1);
>
> Why is this so bad?

Like I said:

1. It is longer and more clumsy than lexical_cast< int >(str, 1). It
does introduce enough scaffolding that user has to type to avoid
lexical_cast altogether in such cases.
2. It introduces dependency on optional.
3. It bans lexical_casting optionals.

Vladimir Batov

unread,
Feb 7, 2009, 8:17:14 AM2/7/09
to bo...@lists.boost.org
>> lexical_cast(Source const&, Target const& =Target())
>
> No, that kind of implementation seems unacceptable to me. I want
> lexical_cast to throw exceptions just as often as I don't want it to. And,
> of course, I'm against introducing a breaking change.
>
>> or most likely a completely independent overload
>>
>> lexical_cast(Source const&, Target const&)
>
> That would be my preferred way to implement this extension.

Yes, agreed. That the only IMHO way to implement that "extension" -- without
disturbing the existing lexical_cast. I threw the first one in almost
accidently. Kevlin argued (in a separate discussion) that

lexical_cast<Foo>(string)
lexical_cast(string, some_foo)

were distant syntactically and I argued that they were not as they could in
fact be two "sides" of the same "coin"

lexical_cast(Source const&, Target const& =Target())

Then, I brought it to this thread just to confuse things.

V.

Anders Dalvander

unread,
Feb 7, 2009, 8:17:31 AM2/7/09
to bo...@lists.boost.org
> some bashing snipped...

Why not compromise?

1. Make the lexical_cast changes for optional that Andrew Troschinetz
suggested.
2. Add the following convert_to.hpp file:

#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>

namespace boost
{
template <typename Target, typename Source>
inline Target convert_to(const Source& arg)
{
return lexical_cast< optional<Target> >(arg).get_value_or(Target());
}

template <typename Target, typename Source>
inline Target convert_to(const Source& arg, const Target& fallback)
{
return lexical_cast< optional<Target> >(arg).get_value_or(fallback);
}
}

3. Use convert_to instead of lexical_cast.
4. Everyone happy?

Regards,
Anders Dalvander

David Abrahams

unread,
Feb 8, 2009, 12:52:19 PM2/8/09
to bo...@lists.boost.org

on Mon Feb 02 2009, Alexander Nasonov <alnsn-AT-yandex.ru> wrote:

> Vladimir Batov <batov <at> people.net.au> writes:
>
>> With no volunteeres coming forward , I am considering extending the
>> lexical_cast interface as described below. Is there any chance of that
>> change integrated?
>
> I'm againt this change. See my other messages in this thread for details.

I am too. Vladimir, I believe the functionality you want is badly
needed, but it shouldn't be part of lexical_cast. lexical_cast is
conceptually simple and should remain that way. The proper interface
for the functionality you seek should be considered without reference to
lexical_cast.

In fact, if we put together all the badly needed functionality that
overlaps with lexical_cast, and give it appropriate interfaces, I'm not
entirely convinced that there would be much use for lexical_cast
anymore.

--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

Ben Muzal

unread,
Feb 8, 2009, 2:33:03 PM2/8/09
to bo...@lists.boost.org
> In fact, if we put together all the badly needed functionality that
> overlaps with lexical_cast, and give it appropriate interfaces, I'm not
> entirely convinced that there would be much use for lexical_cast
> anymore.


Really what is with all of the "slippery slope" arguments? People are
not asking for the kitchen sink. We just want a nothrow version of the
cast and to do that, a default value is needed.

I always use my own extension "lexical_cast_nothrow" operator anyway
that just catches the exception and returns a supplied default value
if necessary.

Lots of times there are cases when a default value simply will not be
acceptable, but quite often one will. Why can't it be easy to support
both models?

I had not even heard of the <optional> library until reading this
thread. I might update my little boost extension after checking to
see how <optional> affects performance and code bloat -- but really,
<optional> looks rather more complicated than necessary.

I heard once that google was experimented with the number of search
results that it returned. If they returned 100 results instead of 10,
the search took .4 seconds longer. They found that the extra delay
reduced the number of searches by 20% within the experimental group.

The moral of the story: some times it is the little conveniences that
count. I think that supplying a 'nothrow' version of lexical_cast is
one of those little conveniences that would definitely count.

--Ben

Ben Muzal

unread,
Feb 8, 2009, 2:43:27 PM2/8/09
to bo...@lists.boost.org
dynamic_cast<> has a implicit 'nothrow' version that returns the
default value of NULL. having a 'nothrow' version of lexical_cast
would not a all be out of line.

--Ben

David Abrahams

unread,
Feb 8, 2009, 2:57:50 PM2/8/09
to bo...@lists.boost.org

on Sun Feb 08 2009, Ben Muzal <bmuzal-AT-gmail.com> wrote:

>> In fact, if we put together all the badly needed functionality that
>> overlaps with lexical_cast, and give it appropriate interfaces, I'm not
>> entirely convinced that there would be much use for lexical_cast
>> anymore.
>
>
> Really what is with all of the "slippery slope" arguments?

That's not my concern. My concern is that I don't think lexical_cast is
a particularly good interface for its main uses, which could be thought
of as "to-string" and "from-string."

> People are not asking for the kitchen sink. We just want a nothrow
> version of the cast and to do that, a default value is needed.

I wouldn't say that. boost::optional is another option. In fact, if
boost::optional doesn't already provide the exact streaming operator you
need, I'd be a little surprised. If it has no streaming operator, we
could consider adding the needed one. If it has the wrong streaming
operator, it would be pretty easy to invent template nothrow, such that you
can write

optional<Foo> = lexical_cast<nothrow<Foo> >( something )

> I always use my own extension "lexical_cast_nothrow" operator anyway
> that just catches the exception and returns a supplied default value
> if necessary.

I think you can easily avoid that problem.

> Lots of times there are cases when a default value simply will not be
> acceptable, but quite often one will. Why can't it be easy to support
> both models?

I just don't think lexical_cast is the interface we need for most
convenient string conversions.

> I had not even heard of the <optional> library until reading this
> thread. I might update my little boost extension after checking to
> see how <optional> affects performance and code bloat -- but really,
> <optional> looks rather more complicated than necessary.

It has exactly the right semantics, and it tells you more than the
version with the default does. With the default, you can't tell whether
there was any valid input there or not, because the value represented in
the input could be the same as the default.

> I heard once that google was experimented with the number of search
> results that it returned. If they returned 100 results instead of 10,
> the search took .4 seconds longer. They found that the extra delay
> reduced the number of searches by 20% within the experimental group.
>
> The moral of the story: some times it is the little conveniences that
> count.

No doubt.

> I think that supplying a 'nothrow' version of lexical_cast is
> one of those little conveniences that would definitely count.

Maybe so, but I don't think lexical_cast is all that well-designed for
convenience to begin with, and tacking on little convenience features
isn't likely to yield a very clean interface.

--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

Vladimi...@wrsa.com.au

unread,
Feb 8, 2009, 3:44:49 PM2/8/09
to bo...@lists.boost.org, Vladimi...@wrsa.com.au
> That's not my concern. My concern is that I don't think lexical_cast is
> a particularly good interface for its main uses, which could be thought
> of as "to-string" and "from-string."

Dave, I am not sure what you see wrong with lexical_cast interface. Could
you elaborate? I am not using lexical_cast (due to throw, no default value
and the def.ctor requirement). So, I still keep using the analog I wrote a
while back and well before I ever heard of lexical_cast. Even though I
wrote it independently, the interface happened to be very close:

namespace aux
{
namespace string
{
template<class Type> std::string from (Type const&);
template<class Type, class String> bool is (String const&)
throw();
template<class Type, class String> Type to (String
const&);
template<class Type, class String> Type to (String const&,
Type const&);
}
}

That is,

string str = aux::string::from(-1);
int i1 = aux::string::to<int>(str); // throw
int i2 = aux::string::to<int>(str, -1); // no throw

As you can see it is pretty close to lexical_cast.

> ...


> I just don't think lexical_cast is the interface we need for most
> convenient string conversions.

It might be the case. However, I do not see any other practical
suggestions that we could act on. Therefore, in the end we end up with
nothing at all... again. That's been dragging for far too long.

> ...


> Maybe so, but I don't think lexical_cast is all that well-designed for
> convenience to begin with, and tacking on little convenience features
> isn't likely to yield a very clean interface.

I am not that concerned about the internal design as it can be worked on
and improved without rush behind the interface. If it is the interface
that is the issue, then let's look at it. Any suggestions? So far, I do
not see people arguing against that proposed "extension" offering anything
practical in return. That is not constructive as people end up with
nothing at all.

I am not counting the <optional> suggestion as it seems as an overkill and
it still has the default-constructability requirement.

Thanks,
Vladimir.

Andrey Semashev

unread,
Feb 8, 2009, 4:20:23 PM2/8/09
to bo...@lists.boost.org
David Abrahams wrote:
> on Sun Feb 08 2009, Ben Muzal <bmuzal-AT-gmail.com> wrote:
>
>>> In fact, if we put together all the badly needed functionality that
>>> overlaps with lexical_cast, and give it appropriate interfaces, I'm not
>>> entirely convinced that there would be much use for lexical_cast
>>> anymore.
>>
>> Really what is with all of the "slippery slope" arguments?
>
> That's not my concern. My concern is that I don't think lexical_cast is
> a particularly good interface for its main uses, which could be thought
> of as "to-string" and "from-string."

I disagree. lexical_cast was designed to be simple to use, and I think
it does it very well. The "to-string" and "from-string" conversions, in
their simple form, are just corner cases. If I want to simply parse an
int, I don't want to make up a Spirit grammar for that or even use
scanf. I need a C++-style of strtol, which is safe in terms of buffer
allocation and types. This is what lexical_cast tries to achieve and it
does, to some degree. I don't know of any other tools that come this
close to this goal, neither in Boost, nor outside of it.

>> People are not asking for the kitchen sink. We just want a nothrow
>> version of the cast and to do that, a default value is needed.
>
> I wouldn't say that. boost::optional is another option. In fact, if
> boost::optional doesn't already provide the exact streaming operator you
> need, I'd be a little surprised. If it has no streaming operator, we
> could consider adding the needed one. If it has the wrong streaming
> operator, it would be pretty easy to invent template nothrow, such that you
> can write
>
> optional<Foo> = lexical_cast<nothrow<Foo> >( something )

I've already expressed myself on this. I just want to add that optional
does define its streaming operators, and the way they work is no
compatible with the goal we're trying to achieve with this extension.

>> Lots of times there are cases when a default value simply will not be
>> acceptable, but quite often one will. Why can't it be easy to support
>> both models?
>
> I just don't think lexical_cast is the interface we need for most
> convenient string conversions.

Do you have a better interface in mind?

>> I had not even heard of the <optional> library until reading this
>> thread. I might update my little boost extension after checking to
>> see how <optional> affects performance and code bloat -- but really,
>> <optional> looks rather more complicated than necessary.
>
> It has exactly the right semantics, and it tells you more than the
> version with the default does. With the default, you can't tell whether
> there was any valid input there or not, because the value represented in
> the input could be the same as the default.

The point is, often I don't care if the default was actually read from
the string or taken from the argument. And I don't want to care (which
would be necessary if optional was used).
If I care whether the string was actually read, I use the throwing
version of lexical_cast.

Gennaro Prota

unread,
Feb 8, 2009, 4:42:51 PM2/8/09
to bo...@lists.boost.org
David Abrahams wrote:
> on Mon Feb 02 2009, Alexander Nasonov <alnsn-AT-yandex.ru> wrote:
>
>> Vladimir Batov <batov <at> people.net.au> writes:
>>
>>> With no volunteeres coming forward , I am considering extending the
>>> lexical_cast interface as described below. Is there any chance of that
>>> change integrated?
>> I'm againt this change. See my other messages in this thread for details.
>
> I am too. Vladimir, I believe the functionality you want is badly
> needed, but it shouldn't be part of lexical_cast. lexical_cast is
> conceptually simple and should remain that way.

lexical_cast was at best an experiment. In some limited contexts
a generic from_string and a generic to_string might make sense.
But a generic from/to anything, using a string as intermediate
representation, is something done just because it can be done,
not because it is useful or meaningfully specified.

I quacke at the idea that it is being used in a mission-critical
project.

> The proper interface for the functionality you seek should be
> considered without reference to lexical_cast.
>
> In fact, if we put together all the badly needed functionality
> that overlaps with lexical_cast, and give it appropriate
> interfaces, I'm not entirely convinced that there would be
> much use for lexical_cast anymore.

There isn't really much use anyway. It gives no control over the
format or, for that matters, over anything.

--
Genny

David Abrahams

unread,
Feb 8, 2009, 5:28:36 PM2/8/09
to bo...@lists.boost.org, Vladimi...@wrsa.com.au

on Sun Feb 08 2009, Vladimir.Batov-AT-wrsa.com.au wrote:

>> That's not my concern. My concern is that I don't think lexical_cast is
>> a particularly good interface for its main uses, which could be thought
>> of as "to-string" and "from-string."
>
> Dave, I am not sure what you see wrong with lexical_cast interface. Could
> you elaborate? I am not using lexical_cast (due to throw, no default value
> and the def.ctor requirement). So, I still keep using the analog I wrote a
> while back and well before I ever heard of lexical_cast. Even though I
> wrote it independently, the interface happened to be very close:
>
> namespace aux
> {
> namespace string
> {
> template<class Type> std::string from (Type const&);
> template<class Type, class String> bool is (String const&)
> throw();
> template<class Type, class String> Type to (String
> const&);
> template<class Type, class String> Type to (String const&,
> Type const&);
> }
> }

I rather like it.

> That is,
>
> string str = aux::string::from(-1);
> int i1 = aux::string::to<int>(str); // throw
> int i2 = aux::string::to<int>(str, -1); // no throw
>
> As you can see it is pretty close to lexical_cast.

Yeah, well it doesn't ever make you type "<string>." But also, it isn't
trying to be lexical_cast. lexical_cast takes one type's lexical
representation and tries to interpret that as another type. That's a
very odd kind of semantics that just happens to line up with something
very useful when one of the types is a string. I've never heard of
anyone using lexical_cast when one of the types was something else.
Have you?

>> ...
>> I just don't think lexical_cast is the interface we need for most
>> convenient string conversions.
>
> It might be the case. However, I do not see any other practical
> suggestions that we could act on. Therefore, in the end we end up with
> nothing at all... again. That's been dragging for far too long.

Let's start with something like your interface. Propose a utility
library. Jeff Garland had a really nice set of proposed extensions to
std::string that could live in the same space.

>> Maybe so, but I don't think lexical_cast is all that well-designed for
>> convenience to begin with, and tacking on little convenience features
>> isn't likely to yield a very clean interface.
>
> I am not that concerned about the internal design

I said "interface," not "implementation."

> as it can be worked on
> and improved without rush behind the interface. If it is the interface
> that is the issue, then let's look at it. Any suggestions? So far, I do
> not see people arguing against that proposed "extension" offering anything
> practical in return. That is not constructive as people end up with
> nothing at all.
>
> I am not counting the <optional> suggestion as it seems as an overkill

I think that's kinda twisted. lexical_cast is already _huge_ compared
to optional, since it drags in iostreams. Optional is a very basic
component.

> and it still has the default-constructability requirement.

Actually it doesn't. optional<T> is always default constructible as
empty, and even if T isn't default constructible you could always define

istream& operator>>(istream&, optional<T>&)

for some particular T.

Have you proposed some way to do away with default constructibility
somehow?

--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

David Abrahams

unread,
Feb 8, 2009, 5:41:50 PM2/8/09
to bo...@lists.boost.org

on Sun Feb 08 2009, Andrey Semashev <andrey.semashev-AT-gmail.com> wrote:

> David Abrahams wrote:
>> on Sun Feb 08 2009, Ben Muzal <bmuzal-AT-gmail.com> wrote:
>>
>>>> In fact, if we put together all the badly needed functionality that
>>>> overlaps with lexical_cast, and give it appropriate interfaces, I'm not
>>>> entirely convinced that there would be much use for lexical_cast
>>>> anymore.
>>>
>>> Really what is with all of the "slippery slope" arguments?
>>
>> That's not my concern. My concern is that I don't think lexical_cast is
>> a particularly good interface for its main uses, which could be thought
>> of as "to-string" and "from-string."
>
> I disagree. lexical_cast was designed to be simple to use, and I think it does it very
> well. The "to-string" and "from-string" conversions, in their simple form, are just
> corner cases.

Eh? What other uses has it got?!

> If I want to simply parse an int, I don't want to make up a Spirit
> grammar for that or even use scanf.

scanf is *way* lighter weight that lexical_cast.

> I need a C++-style of strtol, which is safe in
> terms of buffer allocation and types.

So write that.

> This is what lexical_cast tries to achieve and it does, to some
> degree. I don't know of any other tools that come this close to this
> goal, neither in Boost, nor outside of it.

So write one (just my opinion). lexical_cast means something very
strange and overly-general, and we should write something targeted at
the real-world uses people actually have.

>>> People are not asking for the kitchen sink. We just want a nothrow
>>> version of the cast and to do that, a default value is needed.
>>
>> I wouldn't say that. boost::optional is another option. In fact, if
>> boost::optional doesn't already provide the exact streaming operator you
>> need, I'd be a little surprised. If it has no streaming operator, we
>> could consider adding the needed one. If it has the wrong streaming
>> operator, it would be pretty easy to invent template nothrow, such that you
>> can write
>>
>> optional<Foo> = lexical_cast<nothrow<Foo> >( something )
>
> I've already expressed myself on this. I just want to add that optional does define
> its streaming operators, and the way they work is no compatible with the goal we're
> trying to achieve with this extension.

Then it's easy enough to define the derived template that *is*
compatible... although as I've said before I don't think lexical_cast is
the right tool for this job anyway.

>>> Lots of times there are cases when a default value simply will not be
>>> acceptable, but quite often one will. Why can't it be easy to support
>>> both models?
>>
>> I just don't think lexical_cast is the interface we need for most
>> convenient string conversions.
>
> Do you have a better interface in mind?

It would take some thought and discussion to perfect, but just off the
top of my head, I'd want something like this:

namespace str
{
template <class T>
struct value
{
operator T() const; // throws iff parse unsuccessful
bool parsed() const; // true iff parse succecssful
...
};

template <class String, class T>
string::value<T>
string::as<T>(String const&);

template <class String, class T>
typename enable_if<is_integral<T>, string::value<T> >::type
string::as<T>(String const&, unsigned base);

template <class T>
std::string
to_str(T const& x);

template <class String, class T>
String
to_str(T const& x);
}

>>> I had not even heard of the <optional> library until reading this
>>> thread. I might update my little boost extension after checking to
>>> see how <optional> affects performance and code bloat -- but really,
>>> <optional> looks rather more complicated than necessary.
>>
>> It has exactly the right semantics, and it tells you more than the
>> version with the default does. With the default, you can't tell whether
>> there was any valid input there or not, because the value represented in
>> the input could be the same as the default.
>
> The point is, often I don't care if the default was actually read from the string or
> taken from the argument.

Yes, but sometimes you will.

--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

David Abrahams

unread,
Feb 8, 2009, 5:44:09 PM2/8/09
to bo...@lists.boost.org

on Sun Feb 08 2009, Gennaro Prota <gennaro.prota-AT-yahoo.com> wrote:

> David Abrahams wrote:
>> on Mon Feb 02 2009, Alexander Nasonov <alnsn-AT-yandex.ru> wrote:
>>
>>> Vladimir Batov <batov <at> people.net.au> writes:
>>>
>>>> With no volunteeres coming forward , I am considering extending the lexical_cast
>>>> interface as described below. Is there any chance of that change integrated?
>>> I'm againt this change. See my other messages in this thread for details.
>>
>> I am too. Vladimir, I believe the functionality you want is badly
>> needed, but it shouldn't be part of lexical_cast. lexical_cast is
>> conceptually simple and should remain that way.
>
> lexical_cast was at best an experiment. In some limited contexts
> a generic from_string and a generic to_string might make sense.
> But a generic from/to anything, using a string as intermediate
> representation, is something done just because it can be done,
> not because it is useful or meaningfully specified.

Yes, that's what I've been saying. I don't particularly like the idea
of lexical_cast, and trying to stretch it to cover cases it wasn't
designed for will just put more important functionality in that bucket.

> I quacke at the idea that it is being used in a mission-critical
> project.

IMO that's an overreaction, but anyway...

>> The proper interface for the functionality you seek should be
>> considered without reference to lexical_cast.
>>
>> In fact, if we put together all the badly needed functionality
>> that overlaps with lexical_cast, and give it appropriate
>> interfaces, I'm not entirely convinced that there would be
>> much use for lexical_cast anymore.
>
> There isn't really much use anyway. It gives no control over the
> format or, for that matters, over anything.

...I think you're just making my point for me.

--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

Sebastian Redl

unread,
Feb 8, 2009, 5:48:01 PM2/8/09
to bo...@lists.boost.org
David Abrahams wrote:
> on Sun Feb 08 2009, Andrey Semashev <andrey.semashev-AT-gmail.com> wrote:
>
>
>> David Abrahams wrote:
>>
>>> That's not my concern. My concern is that I don't think lexical_cast is
>>> a particularly good interface for its main uses, which could be thought
>>> of as "to-string" and "from-string."
>>>
>> I disagree. lexical_cast was designed to be simple to use, and I think it does it very
>> well. The "to-string" and "from-string" conversions, in their simple form, are just
>> corner cases.
>>
>
> Eh? What other uses has it got?!
>
>
>> If I want to simply parse an int, I don't want to make up a Spirit
>> grammar for that or even use scanf.
>>
>
> scanf is *way* lighter weight that lexical_cast.
>
>
>> I need a C++-style of strtol, which is safe in
>> terms of buffer allocation and types.
>>
>
> So write that.
>
>
>> This is what lexical_cast tries to achieve and it does, to some
>> degree. I don't know of any other tools that come this close to this
>> goal, neither in Boost, nor outside of it.
>>
>
> So write one (just my opinion). lexical_cast means something very
> strange and overly-general, and we should write something targeted at
> the real-world uses people actually have.
>
Perhaps someone could simply implement the C++0x s2* and to_string
functions as described in the draft, 21.4 Numeric Conversions? They're
pretty trivial, and sufficient for all numeric use cases. They don't
work with user-defined types, though.

Sebastian

Vladimi...@wrsa.com.au

unread,
Feb 8, 2009, 6:03:58 PM2/8/09
to David Abrahams, bo...@lists.boost.org
> ...

> Yeah, well it doesn't ever make you type "<string>." But also, it isn't
> trying to be lexical_cast. lexical_cast takes one type's lexical
> representation and tries to interpret that as another type. That's a
> very odd kind of semantics that just happens to line up with something
> very useful when one of the types is a string. I've never heard of
> anyone using lexical_cast when one of the types was something else.
> Have you?

Yes, I readily admit that the idea indeed looked very odd when I looked at
the implementation... then I thought that smarter-than-me people looked
into it and gave their approval. Still, you are right mentioning that I
never had any inclanation to use lexical_cast<> beyond to/from-string
conversions.

> >> ...
> >> I just don't think lexical_cast is the interface we need for most
> >> convenient string conversions.
> >
> > It might be the case. However, I do not see any other practical
> > suggestions that we could act on. Therefore, in the end we end up with

> > nothing at all... again. That's been dragging for far too long.
>
> Let's start with something like your interface. Propose a utility
> library. Jeff Garland had a really nice set of proposed extensions to
> std::string that could live in the same space.

OK, I'll investigate.

> ...


> > I am not counting the <optional> suggestion as it seems as an overkill

>
> I think that's kinda twisted. lexical_cast is already _huge_ compared
> to optional, since it drags in iostreams. Optional is a very basic
> component.

I am not sure I can agree it is twisted. From the user point of view
lexical_cast is very straightforward. By throwing <optional> into the mix
you immediately increase overall complexity and the entry level.

> > and it still has the default-constructability requirement.
>
> Actually it doesn't. optional<T> is always default constructible as
> empty, and even if T isn't default constructible you could always define
>
> istream& operator>>(istream&, optional<T>&)
>
> for some particular T.

At the moment I cannot have another look at optional. When I looked at it
before, I saw it needed/expected T::T() somewhere to compile. I'll try it
again when I get a chance.

> Have you proposed some way to do away with default constructibility
> somehow?

Foo default_foo;
Foo foo = lexical_cast(str, default_foo);

(or whatever instead of lexical_cast) has no Foo::Foo() requirement.

Best,
V.

David Abrahams

unread,
Feb 8, 2009, 6:34:47 PM2/8/09
to Vladimi...@wrsa.com.au, bo...@lists.boost.org

on Sun Feb 08 2009, Vladimir.Batov-AT-wrsa.com.au wrote:

>> Have you proposed some way to do away with default constructibility
>> somehow?
>
> Foo default_foo;
> Foo foo = lexical_cast(str, default_foo);
>
> (or whatever instead of lexical_cast) has no Foo::Foo() requirement.

and... how is lexical_cast going to come up with an object into which it
can stream? Is it going to use default_foo? In that case, what if
streaming fails partway through? Are you assuming copyability?

--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

Vladimi...@wrsa.com.au

unread,
Feb 8, 2009, 6:52:31 PM2/8/09
to David Abrahams, bo...@lists.boost.org
> > Foo default_foo;
> > Foo foo = lexical_cast(str, default_foo);
> >
> > (or whatever instead of lexical_cast) has no Foo::Foo() requirement.
>
> and... how is lexical_cast going to come up with an object into which it
> can stream? Is it going to use default_foo? In that case, what if
> streaming fails partway through? Are you assuming copyability?

Yes, the copy-constructability requirement is still there. Currently
lexicac_cast does

if(interpreter << arg) {
Target result; // DEFAULT-CONSTRUCTED
if (interpreter >> result)
return result;
}
throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
return Target(); // DEFAULT-CONSTRUCTED

For the proposed "extended" interface I imagined something as
simple/minimal as

if(interpreter << arg) {
Target result(failure_value); // COPY-CONSTRUCTED
if (interpreter >> result)
return result;
}
return failure_value; // COPY-CONSTRUCTED

The likely reason I got so hooked up on extending lexical_cast (rather
than branching off) is that it already implements 95% of what I need/do.
With lexical_cast submitted for TR2 I had an impression that it was the
preferred interface we should be utilizing rather than branching off on
our own. Now I get the feeling that people are suggesting/implying we
should leave lexical_cast behind as an
interesting-but-not-quite-successful experiment (which I somewhat agree
with) and start fresh free of its shackles.

V.

David Abrahams

unread,
Feb 8, 2009, 7:59:20 PM2/8/09
to Vladimi...@wrsa.com.au, bo...@lists.boost.org

on Sun Feb 08 2009, Vladimir.Batov-AT-wrsa.com.au wrote:

> Now I get the feeling that people are suggesting/implying we should
> leave lexical_cast behind as an interesting-but-not-quite-successful
> experiment (which I somewhat agree with) and start fresh free of its
> shackles.

That's just my opinion. And of course, I could be wrong ;-)

--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

Deane Yang

unread,
Feb 8, 2009, 9:32:46 PM2/8/09
to bo...@lists.boost.org, Vladimi...@wrsa.com.au
David Abrahams wrote:
> on Sun Feb 08 2009, Vladimir.Batov-AT-wrsa.com.au wrote:
>
>> Now I get the feeling that people are suggesting/implying we should
>> leave lexical_cast behind as an interesting-but-not-quite-successful
>> experiment (which I somewhat agree with) and start fresh free of its
>> shackles.
>
> That's just my opinion. And of course, I could be wrong ;-)
>

As someone who originally supported Vladimir's original suggestion, I
would say that I agree with the idea of a fresh start.

Vladimi...@wrsa.com.au

unread,
Feb 8, 2009, 9:54:16 PM2/8/09
to Deane Yang, bo...@lists.boost.org
> David Abrahams wrote:
> > on Sun Feb 08 2009, Vladimir.Batov-AT-wrsa.com.au wrote:
> >
> >> Now I get the feeling that people are suggesting/implying we should
> >> leave lexical_cast behind as an interesting-but-not-quite-successful
> >> experiment (which I somewhat agree with) and start fresh free of its
> >> shackles.
> >
> > That's just my opinion. And of course, I could be wrong ;-)
> >
>
> As someone who originally supported Vladimir's original suggestion, I
> would say that I agree with the idea of a fresh start.

I understand. However, I feel uneasy about the easy we are planning to
brush lexical_cast off. That must be very disheartening for Kevlin (the
author) and Alex (Nasonov, the maintainer). Primarily for Alex as I feel
he's been putting quite an effort into it lately. Even though I *might* be
leaning towards a fresh start from the technical point of view, it does
not feel right morally. Even from purely technical point of view I feel
Alex'd be best qualified to make the move as I feel it'll be largely
lexical_cast implementation (at least initially) under a
different/better/stricter interface.

Alex, are you there? How do feel about it? Could you do it? As you can see
your effort won't be in vain and already there is quite a support for your
effort. I really want you to spearhead the effort.

V.

David Abrahams

unread,
Feb 8, 2009, 11:01:30 PM2/8/09
to bo...@lists.boost.org, Deane Yang

on Sun Feb 08 2009, Vladimir.Batov-AT-wrsa.com.au wrote:

>> David Abrahams wrote:
>> > on Sun Feb 08 2009, Vladimir.Batov-AT-wrsa.com.au wrote:
>> >
>> >> Now I get the feeling that people are suggesting/implying we should
>> >> leave lexical_cast behind as an interesting-but-not-quite-successful
>> >> experiment (which I somewhat agree with) and start fresh free of its
>> >> shackles.
>> >
>> > That's just my opinion. And of course, I could be wrong ;-)
>> >
>>
>> As someone who originally supported Vladimir's original suggestion, I
>> would say that I agree with the idea of a fresh start.
>
> I understand. However, I feel uneasy about the easy we are planning to
> brush lexical_cast off. That must be very disheartening for Kevlin (the
> author) and Alex (Nasonov, the maintainer). Primarily for Alex as I feel
> he's been putting quite an effort into it lately.

I'm not suggesting it be "brushed off," I'm just saying that whatever
it's intended to be, it isn't the tool that the many people who want
nothrow this-or-that are asking for. I don't believe any good can come
from an outraged user community trying to get the author and maintainer
to make it into something they don't believe it should be.

lexical_cast should remain consistent with the vision of its author and
maintainer. If many people need something else, they should have it.
Then lexical_cast can gain or lose users on its own merits.


--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

Andrey Semashev

unread,
Feb 9, 2009, 3:46:48 PM2/9/09
to bo...@lists.boost.org
My reply may be too late for the discussion, but I'll answer anyway...

David Abrahams wrote:

>>> That's not my concern. My concern is that I don't think lexical_cast is
>>> a particularly good interface for its main uses, which could be thought
>>> of as "to-string" and "from-string."
>> I disagree. lexical_cast was designed to be simple to use, and I think it does it very
>> well. The "to-string" and "from-string" conversions, in their simple form, are just
>> corner cases.
>
> Eh? What other uses has it got?!

To convert objects of different types between each other. I don't know
if conversion between types that are not strings is widely used or not.
Conversions between custom and fundamental floating point types come to
mind as an example.

>> If I want to simply parse an int, I don't want to make up a Spirit
>> grammar for that or even use scanf.
>
> scanf is *way* lighter weight that lexical_cast.

It may be lighter in terms of implementation and speed, but certainly
not in terms of interface clarity and safety. And anyway, lexical_cast
can potentially be faster than scanf, if it is optimized the way it was
for the "to-string" conversions.

>> I need a C++-style of strtol, which is safe in
>> terms of buffer allocation and types.
>
> So write that.
>
>> This is what lexical_cast tries to achieve and it does, to some
>> degree. I don't know of any other tools that come this close to this
>> goal, neither in Boost, nor outside of it.
>
> So write one (just my opinion). lexical_cast means something very
> strange and overly-general, and we should write something targeted at
> the real-world uses people actually have.

I'm quite happy with lexical_cast, except for this default-value issue.
Why would I write something new?

>>> I just don't think lexical_cast is the interface we need for most
>>> convenient string conversions.
>> Do you have a better interface in mind?
>
> It would take some thought and discussion to perfect, but just off the
> top of my head, I'd want something like this:
>
> namespace str
> {
> template <class T>
> struct value
> {
> operator T() const; // throws iff parse unsuccessful
> bool parsed() const; // true iff parse succecssful
> ...
> };
>
> template <class String, class T>
> string::value<T>
> string::as<T>(String const&);
>
> template <class String, class T>
> typename enable_if<is_integral<T>, string::value<T> >::type
> string::as<T>(String const&, unsigned base);
>
> template <class T>
> std::string
> to_str(T const& x);
>
> template <class String, class T>
> String
> to_str(T const& x);
> }

This does look pretty much like lexical_cast, a bit extended for string
conversions, though.

I'm not against a better support for parsing or formatting in Boost.
However, in case of simple needs, I think the potential of lexical_cast
is not yet exhausted. Adding another library with so much overlapping
functionality may confuse users.

David Abrahams

unread,
Feb 9, 2009, 3:56:21 PM2/9/09
to bo...@lists.boost.org

on Mon Feb 09 2009, Andrey Semashev <andrey.semashev-AT-gmail.com> wrote:

> My reply may be too late for the discussion, but I'll answer anyway...
>
> David Abrahams wrote:
>
>>>> That's not my concern. My concern is that I don't think lexical_cast is
>>>> a particularly good interface for its main uses, which could be thought
>>>> of as "to-string" and "from-string."
>>> I disagree. lexical_cast was designed to be simple to use, and I think it does it
> very
>>> well. The "to-string" and "from-string" conversions, in their simple form, are just
>>> corner cases.
>>
>> Eh? What other uses has it got?!
>
> To convert objects of different types between each other.


Yes, I meant what other real-world uses has it got?

> I don't know if conversion between types that are not strings is
> widely used or not.

Then take it from me, it isn't.

> Conversions between custom and fundamental floating point types come
> to mind as an example.

Yes, hypothetically. In reality, no way. Nobody who wrote a custom
floating point type would leave its conversion to double up to the
vagaries of iostreams, especially ones that hadn't had the right
manipulators applied.

> I'm quite happy with lexical_cast, except for this default-value
> issue. Why would I write something new?

Because where you want it to go clearly doesn't mesh with the vision of
the original author or the maintainer.

Maybe, but lexical_cast clearly isn't targeted at what some large
segment of users needs.

--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

Alexander Nasonov

unread,
Feb 10, 2009, 1:39:34 PM2/10/09
to bo...@lists.boost.org
<Vladimir.Batov <at> wrsa.com.au> writes:

> Alex, are you there? How do feel about it? Could you do it? As you can see
> your effort won't be in vain and already there is quite a support for your
> effort. I really want you to spearhead the effort.

Sorry guys,
My little boy is more important than all other things in the world. I will come
back to this discussion later.

PS NHS (National Health Services) stuff start counting days from day 0. So, a
day when a baby was born is day 0. Not all babys become programmers, though ;)

Alex

Reply all
Reply to author
Forward
0 new messages