
Hi all, I recently discovered lexical_cast, and it's very nice and elegant. I'd like to put in a feature request, though: the ability to use a default value rather than throwing an exception on conversion failure. Basically, it would take a second argument that would be the value returned if the conversion fails. This could be used directly in the example, like: std::vector<short> args; while(*++argv) { args.push_back(lexical_cast<short>(*argv, 0)); } This eliminates the throwing and catching of an exception for cases where conversion failure is not an exceptional. I've attached a patch to lexical_cast.hpp found in Boost 1.32.0 -Dave

Did anyone ever get a chance to look at this feature and patch? I could do the documentation updates, too, if desired. -Dave On Apr 15, 2005, at 3:05 PM, Dave Dribin wrote:
Hi all,
I recently discovered lexical_cast, and it's very nice and elegant. I'd like to put in a feature request, though: the ability to use a default value rather than throwing an exception on conversion failure. Basically, it would take a second argument that would be the value returned if the conversion fails. This could be used directly in the example, like:
std::vector<short> args;
while(*++argv) { args.push_back(lexical_cast<short>(*argv, 0)); }
This eliminates the throwing and catching of an exception for cases where conversion failure is not an exceptional.
I've attached a patch to lexical_cast.hpp found in Boost 1.32.0
-Dave

I have earlier suggested that lexical_cast adds locale support so you can actually use it to parse something else than unformatted integers but the reply quoted the following text from the documentation: --- Start quote --- - It is also worth mentioning future non-directions: anything that involves adding extra arguments for a conversion operation is not being considered. A custom keyword cast, such as lexical_cast, is intended to look like a built-in cast operator: built-in cast operators take only a single operand. Where a higher degree of control is required over conversions, the standard stringstream offers a more appropriate path. Where non-stream-based conversions are required, lexical_cast is the wrong tool for the job, and so it won't be special-cased for such scenarios. --- End quote ---

In message <d755b4cc4649234beeb1cdbd730997e4@dribin.org>, Dave Dribin <dave-ml@dribin.org> writes
Did anyone ever get a chance to look at this feature and patch? I could do the documentation updates, too, if desired.
-Dave
On Apr 15, 2005, at 3:05 PM, Dave Dribin wrote:
Hi all,
I recently discovered lexical_cast, and it's very nice and elegant. I'd like to put in a feature request, though: the ability to use a default value rather than throwing an exception on conversion failure. Basically, it would take a second argument that would be the value returned if the conversion fails. This could be used directly in the example, like:
std::vector<short> args;
while(*++argv) { args.push_back(lexical_cast<short>(*argv, 0)); }
This eliminates the throwing and catching of an exception for cases where conversion failure is not an exceptional.
I've attached a patch to lexical_cast.hpp found in Boost 1.32.0
This issue of providing a default value in case of failure was discussed in the early days of lexical_cast, but not included. In fact, if you go back far enough, opting for the default or zero constructed value of the target rather than throwing an exception was the original behaviour. However, the accommodation of an additional argument was not included in lexical_cast in part for the simple reason that it ceases to look like a cast and in part because once you start down that road there are a number of additional arguments and options that you might want that are "reasonable". It was felt that much of this would be better off in a general conversions library that had no pretensions to being cast-like. Kevlin -- ____________________________________________________________ Kevlin Henney phone: +44 117 942 2990 mailto:kevlin@curbralan.com mobile: +44 7801 073 508 http://www.curbralan.com fax: +44 870 052 2289 Curbralan: Consultancy + Training + Development + Review ____________________________________________________________

On May 1, 2005, at 1:56 PM, Kevlin Henney wrote:
This issue of providing a default value in case of failure was discussed in the early days of lexical_cast, but not included. In fact, if you go back far enough, opting for the default or zero constructed value of the target rather than throwing an exception was the original behaviour.
However, the accommodation of an additional argument was not included in lexical_cast in part for the simple reason that it ceases to look like a cast and in part because once you start down that road there are a number of additional arguments and options that you might want that are "reasonable". It was felt that much of this would be better off in a general conversions library that had no pretensions to being cast-like.
I agree that the default behavior should throw an exception. It just seems silly to create a whole new library that could be done in an existing one with about 5 lines of code. And I'd prefer a multi-argument cast-like function than include yet *another* 3rd party library with my application. Anyhow, I have an idea or two as alternatives. If you're interested, lemme know, otherwise I'll drop the whole idea. :) -Dave

In message <8dee398f92d54b9e2f27e107ee73052c@dribin.org>, Dave Dribin <dave-ml@dribin.org> writes
On May 1, 2005, at 1:56 PM, Kevlin Henney wrote:
This issue of providing a default value in case of failure was discussed in the early days of lexical_cast, but not included. In fact, if you go back far enough, opting for the default or zero constructed value of the target rather than throwing an exception was the original behaviour.
However, the accommodation of an additional argument was not included in lexical_cast in part for the simple reason that it ceases to look like a cast and in part because once you start down that road there are a number of additional arguments and options that you might want that are "reasonable". It was felt that much of this would be better off in a general conversions library that had no pretensions to being cast-like.
I agree that the default behavior should throw an exception. It just seems silly to create a whole new library that could be done in an existing one with about 5 lines of code. And I'd prefer a multi-argument cast-like function than include yet *another* 3rd party library with my application. Anyhow, I have an idea or two as alternatives. If you're interested, lemme know, otherwise I'll drop the whole idea. :)
I'd be interested to hear your ideas. Kevlin -- ____________________________________________________________ Kevlin Henney phone: +44 117 942 2990 mailto:kevlin@curbralan.com mobile: +44 7801 073 508 http://www.curbralan.com fax: +44 870 052 2289 Curbralan: Consultancy + Training + Development + Review ____________________________________________________________

On May 3, 2005, at 3:27 AM, Kevlin Henney wrote:
In message <8dee398f92d54b9e2f27e107ee73052c@dribin.org>, Dave Dribin <dave-ml@dribin.org> writes
On May 1, 2005, at 1:56 PM, Kevlin Henney wrote:
This issue of providing a default value in case of failure was discussed in the early days of lexical_cast, but not included. In fact, if you go back far enough, opting for the default or zero constructed value of the target rather than throwing an exception was the original behaviour.
However, the accommodation of an additional argument was not included in lexical_cast in part for the simple reason that it ceases to look like a cast and in part because once you start down that road there are a number of additional arguments and options that you might want that are "reasonable". It was felt that much of this would be better off in a general conversions library that had no pretensions to being cast-like.
I agree that the default behavior should throw an exception. It just seems silly to create a whole new library that could be done in an existing one with about 5 lines of code. And I'd prefer a multi-argument cast-like function than include yet *another* 3rd party library with my application. Anyhow, I have an idea or two as alternatives. If you're interested, lemme know, otherwise I'll drop the whole idea. :)
I'd be interested to hear your ideas.
Since it sounds like the main argument against adding a second argument is that it is no longer cast-like, the simplest idea is to rename lexical_cast so it is no longer cast-like. I was thinking convert_to would be nice and readable: int n = convert_to<int>("abc"); // Should throw an exception... bad_conversion? int n = convert_to<int>("abc", 0); // Should return 0 string s = convert_to<string>(5); The main issue with renaming, obviously, is backward compatibility. Of course, there's no need to remove lexical_cast right away, or at all, even. Maybe make it deprecated, or at least implemented in terms of convert_to. Thoughts? -Dave

On Thu, May 05, 2005 at 10:29:07AM -0500, Dave Dribin wrote:
On May 3, 2005, at 3:27 AM, Kevlin Henney wrote:
I'd be interested to hear your ideas.
Since it sounds like the main argument against adding a second argument is that it is no longer cast-like, the simplest idea is to rename lexical_cast so it is no longer cast-like. I was thinking convert_to would be nice and readable:
int n = convert_to<int>("abc"); // Should throw an exception... bad_conversion? int n = convert_to<int>("abc", 0); // Should return 0
string s = convert_to<string>(5);
The main issue with renaming, obviously, is backward compatibility. Of course, there's no need to remove lexical_cast right away, or at all, even. Maybe make it deprecated, or at least implemented in terms of convert_to.
If you want a function with a different name and a different behaviour, isn't that a different function? In which case, why even consider removing lexical_cast ? jon

On 5/5/05, Dave Dribin <dave-ml@dribin.org> wrote:
On May 3, 2005, at 3:27 AM, Kevlin Henney wrote:
In message <8dee398f92d54b9e2f27e107ee73052c@dribin.org>, Dave Dribin <dave-ml@dribin.org> writes
On May 1, 2005, at 1:56 PM, Kevlin Henney wrote:
This issue of providing a default value in case of failure was discussed in the early days of lexical_cast, but not included. In fact, if you go back far enough, opting for the default or zero constructed value of the target rather than throwing an exception was the original behaviour.
However, the accommodation of an additional argument was not included in lexical_cast in part for the simple reason that it ceases to look like a cast and in part because once you start down that road there are a number of additional arguments and options that you might want that are "reasonable". It was felt that much of this would be better off in a general conversions library that had no pretensions to being cast-like.
I agree that the default behavior should throw an exception. It just seems silly to create a whole new library that could be done in an existing one with about 5 lines of code. And I'd prefer a multi-argument cast-like function than include yet *another* 3rd party library with my application. Anyhow, I have an idea or two as alternatives. If you're interested, lemme know, otherwise I'll drop the whole idea. :)
I'd be interested to hear your ideas.
Since it sounds like the main argument against adding a second argument is that it is no longer cast-like, the simplest idea is to rename lexical_cast so it is no longer cast-like. I was thinking convert_to would be nice and readable:
int n = convert_to<int>("abc"); // Should throw an exception... bad_conversion? int n = convert_to<int>("abc", 0); // Should return 0
string s = convert_to<string>(5);
The main issue with renaming, obviously, is backward compatibility. Of course, there's no need to remove lexical_cast right away, or at all, even. Maybe make it deprecated, or at least implemented in terms of convert_to.
Thoughts?
-Dave
As an early whiner about issues of lexical_cast, I've seen these issues discussed many times. A few years ago there was a nice proposal/implementation of an extensible lexical_cast that could use other, more optimal, choices for certain conversions (http://lists.boost.org/MailArchives/boost/msg34342.php unfortunately the code seems to have been lost). lexical_convert was bandied about as a name for something providing default values, but I really like the name convert_to. This is a library I'd really like to see in boost.

Dave Dribin wrote:
Since it sounds like the main argument against adding a second argument is that it is no longer cast-like, the simplest idea is to rename lexical_cast so it is no longer cast-like. I was thinking convert_to would be nice and readable:
int n = convert_to<int>("abc"); // Should throw an exception... bad_conversion? int n = convert_to<int>("abc", 0); // Should return 0
string s = convert_to<string>(5);
The main issue with renaming, obviously, is backward compatibility. Of course, there's no need to remove lexical_cast right away, or at all, even. Maybe make it deprecated, or at least implemented in terms of convert_to.
The purpose of lexical cast is conversion through serializaton and deserialization. boost::lexical_cast is called lexical cast because it uses STL object serialization framework based on << and >> operators. Semantically convert_to is a different operation. Safe C++ way to do itoa has nothing to do with serialization. Also lexical_cast has an awful performance, because an intermediate string stream has to be created. I think we can leave lexical_cast alone as it is, but add separate functions for safe conversions between ascii and binary representation of numbers. These functions should be fast and properly named according to their semantic. Performance requirement can also force us to implement additional interface with error flag instead of throwing exceptions. convert_to<int>("abc") can be so fast that in some applications overhead of throwing an exception will be very noticeable. Theoretically, it's possible to speed up current boost::lexical_cast<size_t>("abc") by adding N^2 specializations for all POD flavours. Below is a hack I use to speed up boost::date_time (it uses boost::lexical_cast with atoi/itoa semantic internally). What do you think about performance issues? Should they be addressed in this and other boost libraries (like extremely slow boost::date_time and boost::tokenizer/token_iterator), or the most users don't need higher performance? Andrey ------------------- template<typename Target, typename Source> class lexical_caster { public: static Target cast(Source arg); // old << / >> } template<> class lexical_caster<unsigned short, std::string> { // fast specialization using classical loop with multiplies // I didn't find a very fast function like atoi, but with // some kind of conversion failure indication } template<typename Target, typename Source> Target lexical_cast(Source arg) { return lexical_caster<Target, Source>::cast(arg); }

On May 5, 2005, at 2:55 PM, Andrey Melnikov wrote:
Semantically convert_to is a different operation. Safe C++ way to do itoa has nothing to do with serialization.
Then why does the lexical cast documentation specifically compare itself to atoi and strtol: http://www.boost.org/libs/conversion/lexical_cast.htm As stated in the first paragraph on the motivation: "Sometimes a value must be converted to a literal text form, such as an int represented as a string, or vice-versa, when a string is interpreted as an int. Such examples are common when converting between data types internal to a program and representation external to a program, such as windows and configuration files." Working with windows and configuration files, in my experience, at least, requires handling of invalid values. They are the normal case, not an exceptional case. And from reading the lexical_cast documentation, you'd think this is the library to use. Apart from the name containing "cast", lexical_cast does what I need: converting numbers to and from strings.
I think we can leave lexical_cast alone as it is, but add separate functions for safe conversions between ascii and binary representation of numbers. These functions should be fast and properly named according to their semantic. Performance requirement can also force us to implement additional interface with error flag instead of throwing exceptions. convert_to<int>("abc") can be so fast that in some applications overhead of throwing an exception will be very noticeable.
That would work, as well. But I'm thinking that convert_to would need to fall back to lexical_cast for conversion that do not contain a string. If we want to concentrate on the conversion to and from strings, maybe names like string_to and to_string would be more appropriate: int n = string_to<int>("50"); int httpPort = string_to<int>("invalid conversion", 80); And the converse: string message = "Connecting to server: " + host + ":" + to_string(80); Actually, to_string cannot have an invalid conversion case, can it? It seems only going from a string can cause that. And as for performance being an issue, it probably is in some cases. In the cases where I've used string to int conversions and vice vera, performance has not been critical and stringstreams have been just fine, though. I started using lexical_cast because it made my stringstream code easier to read. -Dave

Dave Dribin wrote:
On May 5, 2005, at 2:55 PM, Andrey Melnikov wrote:
Semantically convert_to is a different operation. Safe C++ way to do itoa has nothing to do with serialization.
Working with windows and configuration files, in my experience, at least, requires handling of invalid values. They are the normal case, not an exceptional case. And from reading the lexical_cast documentation, you'd think this is the library to use. Apart from the name containing "cast", lexical_cast does what I need: converting numbers to and from strings.
I agree with the need for safe conversion function with error indication, and with other lexical_cast design goals stated in documentation. I just don't want slow approach with temporary std::stringstream to be used for simple conversions. Instead, I want faster lexical_cast() specializations for built-in types, and additional lexical_cast_nothrow() function.
I think we can leave lexical_cast alone as it is, but add separate functions for safe conversions between ascii and binary representation of numbers. These functions should be fast and properly named according to their semantic. Performance requirement can also force us to implement additional interface with error flag instead of throwing exceptions. convert_to<int>("abc") can be so fast that in some applications overhead of throwing an exception will be very noticeable.
That would work, as well. But I'm thinking that convert_to would need to fall back to lexical_cast for conversion that do not contain a string. If we want to concentrate on the conversion to and from strings, maybe names like string_to and to_string would be more appropriate:
int n = string_to<int>("50"); int httpPort = string_to<int>("invalid conversion", 80);
And the converse:
string message = "Connecting to server: " + host + ":" + to_string(80);
I introduced to_string and from_string not only because I dislike "lexical_cast" name. The main reason is that current extensibilty framework is too heavyweight. So I proposed to introduce a separate family of functions which wouldn't require operator << and operator >> (or, more precicely, ostream/stringstream) for extensibility. For example, an UDT could just specialize an internal template class to allow faster conversion using std::string, or use older extensibility framework with overloaded operator >>. On the one hand, implementation which uses std::string, can be much faster than implementation which uses std::stringstream. On the other hand, std::stringstream provides convenient methods to facilitate serialization of complex types. Can we stay with just lexical_cast, add lexical_cast_nothrow and lexical_cast_default, and have both extensibility methods implemented in a non-conflicting way?
Actually, to_string cannot have an invalid conversion case, can it? It seems only going from a string can cause that.
In case of user types it can. For example, an overloaded operator << can refuse to serialize an object with invalid state.
And as for performance being an issue, it probably is in some cases. In the cases where I've used string to int conversions and vice vera, performance has not been critical and stringstreams have been just fine, though. I started using lexical_cast because it made my stringstream code easier to read.
Well, function performance is always an issue only in some usage scenarios. I understand that parsing config files doesn't have high performance requirements. I actually don't use lexical_cast directly. I use boost::date_time on large data volumes, and it happened that overhead of using boost::date_time was significant even despite I/O was the bottleneck too. Performance profiling showed that date_time was among critical functions. When I looked inside the source, it turned out that I could increase overall performance a lot by patching boost::lexical_cast and boost::tokenizer libraries... Now I want these issues to be fixed in main boost source tree so I won't need to patch next releases myself to get the performance I need. Andrey

In message <427A7A31.8000504@simplexsoft.com>, Andrey Melnikov <melnikov@simplexsoft.com> writes
The purpose of lexical cast is conversion through serializaton and deserialization. boost::lexical_cast is called lexical cast because it uses STL object serialization framework based on << and >> operators.
Semantically convert_to is a different operation.
[...]
I think we can leave lexical_cast alone as it is, but add separate functions for safe conversions between ascii and binary representation of numbers. These functions should be fast and properly named according to their semantic. Performance requirement can also force us to implement additional interface with error flag instead of throwing exceptions. convert_to<int>("abc") can be so fast that in some applications overhead of throwing an exception will be very noticeable.
I think that the specialisation (conceptual as opposed to templated) perspective is the right way to go. lexical_cast caters for a general need, but not all specific needs (it is stream-based and not performance-centric), so functions that cater to more specific conversions -- convert_to with default, string_to, etc -- seem to make sense. It is not a load that lexical_cast should be carrying all of, IMHO. Kevlin -- ____________________________________________________________ Kevlin Henney phone: +44 117 942 2990 mailto:kevlin@curbralan.com mobile: +44 7801 073 508 http://www.curbralan.com fax: +44 870 052 2289 Curbralan: Consultancy + Training + Development + Review ____________________________________________________________

On May 12, 2005, at 8:59 AM, Kevlin Henney wrote:
I think that the specialisation (conceptual as opposed to templated) perspective is the right way to go. lexical_cast caters for a general need, but not all specific needs (it is stream-based and not performance-centric), so functions that cater to more specific conversions -- convert_to with default, string_to, etc -- seem to make sense. It is not a load that lexical_cast should be carrying all of, IMHO.
Unfortunately, writing a performance centric convert_to is not a load I want to carry. For me, the lexical_cast and hence stream-based performance is just fine for our app. All I want is a default value without littering my code with try/catch statements (of if statements, even). For now, I'm just going to patch my version of lexical_cast.hpp with my original patch or maybe move that to an external header that relies on the Boost internals. We don't mind if it doesn't quite look like a cast. I guess for us, no try/catch statements trumps quasi-cast semantics and non-optimal performance. If someone wants to tackle a performance centric convert_to or string_to, lemme know and I'll test it, but I'm not going to push this issue any more. -Dave

In message <2360aa6f4e6f12532502448436b50451@dribin.org>, Dave Dribin <dave-ml@dribin.org> writes
I'd be interested to hear your ideas.
Since it sounds like the main argument against adding a second argument is that it is no longer cast-like, the simplest idea is to rename lexical_cast so it is no longer cast-like. I was thinking convert_to would be nice and readable:
int n = convert_to<int>("abc"); // Should throw an exception... bad_conversion? int n = convert_to<int>("abc", 0); // Should return 0
string s = convert_to<string>(5);
The main issue with renaming, obviously, is backward compatibility. Of course, there's no need to remove lexical_cast right away, or at all, even. Maybe make it deprecated, or at least implemented in terms of convert_to.
Thoughts?
I think that as a named entity, lexical_cast is fairly well settled, so I am not sure that it could be replaced without a proper deprecation plan. Given the less frequent need for the defaulted form, I am not sure that such a significant is easily justified. However, when I consider what the most common use of a defaulted value would likely be, based on my own experience of similar features, other library designs and indeed your example above, it appears that in the event of non-conversion the explicitly default constructed value of the target type is the most common use. Creating an interface for that would be somewhat easier. There are essentially three practical options for doing this, as I see it (a couple of others come to mind, but don't qualify as being in line with the existing design): (1) Provide a wrapper type for the source on which lexical_cast is overloaded and will handle non-conversion separately, eg lexical_cast<T>(defaulted(a)) or lexical_cast<T>(nonthrowing(a)). (2) Specify a target type that indicates a non-throwing outcome. The following suggestion has come to me from a colleague of Thomas Witt's: lexical_cast< optional<T> >(a). (3) Define another cast-like function that is specifically named, eg nothrow_lexical_cast<T>(a). In terms of simplicity and directness my preference is for (3), although I am not wed to the name. I would be interested to hear any thoughts on this. Kevlin -- ____________________________________________________________ Kevlin Henney phone: +44 117 942 2990 mailto:kevlin@curbralan.com mobile: +44 7801 073 508 http://www.curbralan.com fax: +44 870 052 2289 Curbralan: Consultancy + Training + Development + Review ____________________________________________________________

On May 7, 2005, at 3:50 AM, Kevlin Henney wrote:
However, when I consider what the most common use of a defaulted value would likely be, based on my own experience of similar features, other library designs and indeed your example above, it appears that in the event of non-conversion the explicitly default constructed value of the target type is the most common use. Creating an interface for that would be somewhat easier.
There are essentially three practical options for doing this, as I see it (a couple of others come to mind, but don't qualify as being in line with the existing design):
(1) Provide a wrapper type for the source on which lexical_cast is overloaded and will handle non-conversion separately, eg lexical_cast<T>(defaulted(a)) or lexical_cast<T>(nonthrowing(a)).
(2) Specify a target type that indicates a non-throwing outcome. The following suggestion has come to me from a colleague of Thomas Witt's: lexical_cast< optional<T> >(a).
(3) Define another cast-like function that is specifically named, eg nothrow_lexical_cast<T>(a).
In terms of simplicity and directness my preference is for (3), although I am not wed to the name. I would be interested to hear any thoughts on this.
Personally, I think there is a need to to specify the default value, rather than rely on the default constructed value. For example: int httpPort = convert_to<int>(aString, 80); Maybe that can be done in similar vain to (1) or (2): int httpPort = lexical_cast<int>(default_value<int>(aString, 80)); I don't know templates well enough to know if that's possible. Seems like the implementation would need to convert 80 into a string, and then back to an int, though, as default_value would need to return a string in the above example, right? -Dave

In message <c36e3cc4d205f62b0ca8f74dfe7ca778@dribin.org>, Dave Dribin <dave-ml@dribin.org> writes
There are essentially three practical options for doing this, as I see it (a couple of others come to mind, but don't qualify as being in line with the existing design):
(1) Provide a wrapper type for the source on which lexical_cast is overloaded and will handle non-conversion separately, eg lexical_cast<T>(defaulted(a)) or lexical_cast<T>(nonthrowing(a)).
(2) Specify a target type that indicates a non-throwing outcome. The following suggestion has come to me from a colleague of Thomas Witt's: lexical_cast< optional<T> >(a).
(3) Define another cast-like function that is specifically named, eg nothrow_lexical_cast<T>(a).
In terms of simplicity and directness my preference is for (3), although I am not wed to the name. I would be interested to hear any thoughts on this.
Personally, I think there is a need to to specify the default value, rather than rely on the default constructed value. For example:
int httpPort = convert_to<int>(aString, 80);
Maybe that can be done in similar vain to (1) or (2):
int httpPort = lexical_cast<int>(default_value<int>(aString, 80));
I don't know templates well enough to know if that's possible. Seems like the implementation would need to convert 80 into a string, and then back to an int, though, as default_value would need to return a string in the above example, right?
I think that the optional approach (2) would be more appropriate if this proves to be a killer need. It is lighter in weight in terms of syntax and implementation, and is ultimately more general purpose. However, the example above doesn't seem to be quite the killer example given that 0 is readily identifiable as an inappropriate port number. Yes, it's a convenience, but the convert_to (or perhaps convert_else) syntax is simpler than using either (2) or (3). Kevlin -- ____________________________________________________________ Kevlin Henney phone: +44 117 942 2990 mailto:kevlin@curbralan.com mobile: +44 7801 073 508 http://www.curbralan.com fax: +44 870 052 2289 Curbralan: Consultancy + Training + Development + Review ____________________________________________________________

On May 12, 2005, at 9:05 AM, Kevlin Henney wrote:
Personally, I think there is a need to to specify the default value, rather than rely on the default constructed value. For example:
int httpPort = convert_to<int>(aString, 80);
Maybe that can be done in similar vain to (1) or (2):
int httpPort = lexical_cast<int>(default_value<int>(aString, 80));
I don't know templates well enough to know if that's possible. Seems like the implementation would need to convert 80 into a string, and then back to an int, though, as default_value would need to return a string in the above example, right?
I think that the optional approach (2) would be more appropriate if this proves to be a killer need. It is lighter in weight in terms of syntax and implementation, and is ultimately more general purpose.
However, the example above doesn't seem to be quite the killer example given that 0 is readily identifiable as an inappropriate port number. Yes, it's a convenience, but the convert_to (or perhaps convert_else) syntax is simpler than using either (2) or (3).
I think it's a killer need. Yes, in the case above 0 is inappropriate, but there could be cases when you'd rather use -1. The point is each application and situation is different. There's not one single inappropriate value for all types. For strings, would you use the empty string? This is an issue with value semantics since NULL isn't an option. And even if there was a universally inappropriate value, now my code is littered with: if (var == INAPPROPRIATE_VALUE) { var = DEFAULT_VALUE; } instead of just supplying it in the lexical_cast<> itself (which is already doing the checking). This makes the code harder to read than it needs to by, IMO. -Dave

In message <b80ef8127943216dce23846c4d491ff4@dribin.org>, Dave Dribin <dave-ml@dribin.org> writes
On May 12, 2005, at 9:05 AM, Kevlin Henney wrote:
Personally, I think there is a need to to specify the default value, rather than rely on the default constructed value. For example:
int httpPort = convert_to<int>(aString, 80);
Maybe that can be done in similar vain to (1) or (2):
int httpPort = lexical_cast<int>(default_value<int>(aString, 80));
I don't know templates well enough to know if that's possible. Seems like the implementation would need to convert 80 into a string, and then back to an int, though, as default_value would need to return a string in the above example, right?
I think that the optional approach (2) would be more appropriate if this proves to be a killer need. It is lighter in weight in terms of syntax and implementation, and is ultimately more general purpose. [...] I think it's a killer need. Yes, in the case above 0 is inappropriate, but there could be cases when you'd rather use -1. The point is each application and situation is different. There's not one single inappropriate value for all types. For strings, would you use the empty string? This is an issue with value semantics since NULL isn't an option. And even if there was a universally inappropriate value, now my code is littered with:
if (var == INAPPROPRIATE_VALUE) { var = DEFAULT_VALUE; }
instead of just supplying it in the lexical_cast<> itself (which is already doing the checking). This makes the code harder to read than it needs to by, IMO.
Having given this some more thought, I am more convinced that to provide this functionality the suggestion of using optional is the better one. This makes clear in a declarative sense what is going on, but does not get drawn into what a suitable interpretation of non-conversion might be (assign a default, log an error, etc). The next version of lexical_cast is due to be committed to CVS real-soon now. It fixes a couple of defects and improvements, but no new key functionality. If there is interest in supporting optionality as I've just described it, then the version after the next would be the earliest appropriate time to introduce it. Kevlin -- ____________________________________________________________ Kevlin Henney phone: +44 117 942 2990 mailto:kevlin@curbralan.com mobile: +44 7801 073 508 http://www.curbralan.com fax: +44 870 052 2289 Curbralan: Consultancy + Training + Development + Review ____________________________________________________________
participants (6)
-
Andrey Melnikov
-
Dave Dribin
-
Jonathan Wakely
-
Kevlin Henney
-
Martin
-
Thomas Matelich