-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Helper functions for conversions that are locale independent #233
Comments
I've found https://github.com/fastfloat/fast_float which provides MIT-licensed implementation of the floating-point variants of From the benchmarks it has in the README, it seems it is the fastest available option. |
I wrote a shim for the functionality that should be working generally at least since GCC 7 (shimming the support via fast_float). I think something similar could be used here.
#include <charconv>
void fn()
{
double d;
const char* s = "1.0";
std::from_chars(s, s + 3, d);
}
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
try_compile(HAS_FROM_CHARS_FLOAT
${CMAKE_BINARY_DIR}/from_chars ${CMAKE_CURRENT_SOURCE_DIR}/cmake/from_chars_try_compile.cpp
CXX_STANDARD 17)
...
if (HAS_FROM_CHARS_FLOAT)
target_compile_definitions(target PRIVATE HAS_FROM_CHARS_FLOAT=1)
endif()
#pragma once
#include <system_error>
namespace cras
{
enum chars_format
{
scientific = 1 << 0,
fixed = 1 << 2,
hex = 1 << 3,
general = fixed | scientific
};
struct from_chars_result
{
const char* ptr;
::std::errc ec;
};
::cras::from_chars_result from_chars(const char* first, const char* last, float& value,
::cras::chars_format fmt = ::cras::chars_format::general) noexcept;
::cras::from_chars_result from_chars(const char* first, const char* last, double& value,
::cras::chars_format fmt = ::cras::chars_format::general) noexcept;
}
#include "from_chars.h"
#if defined(HAS_FROM_CHARS_FLOAT) && HAS_FROM_CHARS_FLOAT == 1
#include <charconv>
namespace cras
{
cras::from_chars_result from_chars(const char* first, const char* last, float& value,
const cras::chars_format fmt) noexcept
{
auto result = std::from_chars(first, last, value, static_cast<std::chars_format>(fmt));
return {result.ptr, result.ec};
}
cras::from_chars_result from_chars(const char* first, const char* last, double& value,
const cras::chars_format fmt) noexcept
{
auto result = std::from_chars(first, last, value, static_cast<std::chars_format>(fmt));
return {result.ptr, result.ec};
}
}
#else
#include <fast_float/fast_float.h>
namespace cras
{
cras::from_chars_result from_chars(const char* first, const char* last, float& value,
const cras::chars_format fmt) noexcept
{
auto result = fast_float::from_chars(first, last, value, static_cast<fast_float::chars_format>(fmt));
return {result.ptr, result.ec};
}
cras::from_chars_result from_chars(const char* first, const char* last, double& value,
const cras::chars_format fmt) noexcept
{
auto result = fast_float::from_chars(first, last, value, static_cast<fast_float::chars_format>(fmt));
return {result.ptr, result.ec};
}
}
#endif |
Interesting, maybe we could vendor that on |
Desired behavior
Different software in the Ignition family uses all kind of C/C++ functions to convert between types that are locale dependent and make functionality to fail under non C locales. Examples are:
Trying to complete the list (split due to limitations in github search) based on https://www.gnu.org/software/libc/manual/html_node/Parsing-of-Numbers.html:
Alternatives considered
There is a native function in C++17 https://en.cppreference.com/w/cpp/utility/to_chars which is not available in all supported platforms at this time. The
boost::lexical_cast
could be an option but would be ideal not to depend on boost if possible.Implementation suggestion
I think that the best approach would be to implement helper functions that encapsulate the implementation in this
ign-common
repository. The implementation can rely onto_chars
if C++17 is available or use other workarounds (see ros/urdfdom_headers#42).A similar work was done for sdformat years ago. Following the locale_fix test can lead to details.
The text was updated successfully, but these errors were encountered: