I am trying to convert std::string_view
to float without an intermediate conversion to std::string
(which will cause extra heap allocation) with a C 20 compiler.
#include <iostream>
#include <charconv>
int main() {
std::string_view s = "123.4";
float x;
std::from_chars(s.data(), s.data() s.size(), x);
std::cout << x << std::endl;
}
But I am unable to compile this code:
error: no matching function for call to 'from_chars(std::basic_string_view<char>::const_pointer, std::basic_string_view<char>::const_pointer, float&)'
What I am doing wrong?
CodePudding user response:
GCC's C standard library implementation first supported std::from_chars
for float
in GCC 11.1. 10.x won't support it.
Since you're not checking for success, and you know your string is null-terminated, you can use atof()
instead, which is similarly unsafe. If you want proper checking for parsing errors, use strtof
, which will give you similar information to from_chars
as to whether the input matched properly:
#include <iostream>
#include <cstdlib>
int main() {
std::string_view s = "123.4";
char * end;
float x = std::strtof(s.data(), &end);
if (end != s.data() s.size())
{
std::cout << "Parse error";
}
else
{
std::cout << x << std::endl;
}
}
CodePudding user response:
If and only if you know that your string view is null terminated, you can use this
float x = static_cast<float>(atof(s.data()));
CodePudding user response:
Look into charconv header. For example GCC have next guard in it
#if defined __cpp_lib_to_chars || _GLIBCXX_HAVE_USELOCALE
So it can be not implemented, or your compiler not configured to use at least C 17 standard. I.e. no -std=c 20
for GCC and Clang or /std:c latest
for Microsoft VC command line options passed to your compiler, or your implementation i.e. port not implementing this functionality and not fully implement a standard.
You always can replace from_chars with strtof c function.
For example:
#include <iostream>
#include <string_view>
#include <system_error>
#include <cmath>
#include <charconv>
#include <cstdlib>
int main(int argc, const char** argv)
{
std::string_view sv("12.345678");
#ifdef __cpp_lib_to_chars
float result = NAN;
auto conv_ret = std::from_chars(sv.data(), (sv.data() sv.size()), result);
std::error_code ec = std::make_error_code(conv_ret.ec);
#else
char *endp = nullptr;
float result = std::strtof(sv.data(), &endp);
std::error_code ec;
if (errno == ERANGE) {
ec = std::make_error_code(std::errc::result_out_of_range);
}
#endif
if(ec) {
std::cerr << ec.message() << std::endl;
return ec.value();
}
std::cout << "Float: " << result << std::endl;
return 0;
}
CodePudding user response:
error: no matching function for call to 'from_chars(std::basic_string_view<char>::const_pointer, std::basic_string_view<char>::const_pointer, float&)'
Tried following code based on above error:
#if defined(CYGWIN_NT) || defined(AIX71) || defined(SUNOS)
#include <iostream>
using namespace std;
#elif defined(LINUX) || defined(HPUX11)
#include <iostream.h>
#else
#error handle iostream/iostream.h error.
#endif
#include <charconv>
int main()
{
string_view s = "123.4";
// Always better to initialize.
float x = 0.0f;
from_chars(s.data(), s.data() s.size(), x);
cout << x << endl;
return 0;
}
// Sample compilation:
// echo g -Wall 73333331.cpp -D$(uname -s | sed "s/-[0-9].*.[0-9].*-[0-9].*//;") -std=c 20 -o ./a.out
// g -Wall 73333331.cpp -DCYGWIN_NT -std=c 20 -o ./a.out
// ./a.out
// 123.4