4
\$\begingroup\$

I love boost::lexical_cast but its usage of exceptions there is not preferred in most situations I use it.

I have implemented a version and it seems to work but I want to share it here to hopefully find any defects and/or simply find improvements.

template<typename T1, typename T2>
T1 lexical_cast(T2 const& value, T1 const& defaultValue = T1{})
{
    T1 convertedValue;
    std::stringstream ss;
    if (!(ss << value) || !(ss >> convertedValue))
    {
        return defaultValue;
    }

    return convertedValue;
}

Here is the code on Coliru where I've been testing.

\$\endgroup\$
  • \$\begingroup\$ Have you looked at Boost.Convert? ⟪choice of immediate or delayed exception-throwing and non-throwing conversion-failure processing⟫ \$\endgroup\$ – JDługosz Jun 22 '18 at 8:33
2
\$\begingroup\$

Since you have an already working lexical cast. Why not just wrap that?

namespace MyStuff
{
    template<typename T1, typename T2>
    T1 lexical_cast(T2 const& value, T1 const& defaultValue = T1{})
    {
        try
        {
            return boost::lexical_cast<T1,T2>(value);
        }
        catch(...) // Ignore all exceptions and use default.
        {
            return defaultValue;
        }
    }
}

The reason I would not advocate writing your own is the actually complicity of all the edge cases. Though your code embodies what is happening the actual code has not reflected this in a long time (you have basically written the deprecated version of boost::lexical cast).

Also the boost version has a whole bunch of special case optimizations.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ The goal is to avoid exceptions. While I agree with your point about not reinventing the wheel, simply hiding the exception does not remove the performance impact. \$\endgroup\$ – void.pointer Feb 5 '15 at 15:19
  • \$\begingroup\$ I don't see exceptions being a real cost when you consider what we are doing - reading from a stream a slow operation most of the time. But I have not timed it. If you have some real data about the extra cost I would love to see it. Also is the extra cost greater than the speed saved by all the specializations specifically designed to increase the speed. \$\endgroup\$ – Martin York Feb 5 '15 at 19:07
  • \$\begingroup\$ Also note: There is no extra cost if the exception is not thrown. So if you have good sanitized input then it will run faster than your code because of the specialization designed to increase speed in the boost::lexical_cast \$\endgroup\$ – Martin York Feb 7 '15 at 0:19
  • \$\begingroup\$ You're missing the point. When I'm parsing a large XML file, for example, I don't need thousands of exceptions to occur which would negatively impact parse times. Exceptions are for exceptional situations, and in this case they are not exceptional (some failures are expected and can be recovered without the usage of exceptions). \$\endgroup\$ – void.pointer Feb 8 '15 at 21:52
  • \$\begingroup\$ @void.pointer: What I actually asked in the last comment do you have any data to support that there is actually a negative impact on parse time? Assuming you know what you have parsed and thus know it is a number already then why is boost::lexical_cast going to throw. \$\endgroup\$ – Martin York Feb 8 '15 at 22:41
1
\$\begingroup\$

I know I am quite late, but try_lexical_convert() can be utilized:

using boost::conversion::try_lexical_convert;
if(try_lexical_convert(source, target)) {
   // ...
}
| improve this answer | |
\$\endgroup\$
  • 5
    \$\begingroup\$ Could you explain to the OP how this code could be incorporated with his/her code? Should that function be used instead of lexical_cast or before/after it? \$\endgroup\$ – Sᴀᴍ Onᴇᴌᴀ Jun 21 '18 at 15:47
  • 1
    \$\begingroup\$ The OP can figure it out by self, because it's enough to know the function name. I add answer there so as google searching for 'lexical_cast without exceptions' will give this sweet short answer. \$\endgroup\$ – my_stk_oflw_account Jun 22 '18 at 9:53
  • 2
    \$\begingroup\$ You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process. Please read Why are alternative solutions not welcome? \$\endgroup\$ – Sᴀᴍ Onᴇᴌᴀ Jun 22 '18 at 17:18
  • 1
    \$\begingroup\$ Upvoted. This is a fantastic answer. According to Boost docs, lexical_cast is imlemented internally using try_lexical_convert. \$\endgroup\$ – Contango Sep 22 '19 at 19:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.