使用g++ 10.2.1调用std::from_chars时编译错误求助
std::from_chars不支持浮点数的编译问题 问题背景
GCC 10.2.1(Debian 10.2.1-6)的<charconv>头文件中,std::from_chars仅实现了整数类型的重载,尚未支持C++17标准要求的浮点数处理能力,因此编译使用该函数转换float/double的代码会触发匹配错误。
原代码及编译错误
原代码
#include <charconv> #include <concepts> #include <optional> #include <string_view> template<std::floating_point T> std::optional<T> to_float(std::string_view s) { T value; if (std::from_chars(s.data(), s.data() + s.size(), value).ec == std::errc{}) return value; return {}; } int main() { to_float<float>("0"); return 0; }
编译错误信息
在实例化‘std::optional<_Tp> to_float(std::string_view) [with T = float; std::string_view = std::basic_string_view
]’时:
main.cpp:633:92: 从此处要求
main.cpp:36:24: 错误:没有匹配的函数调用‘from_chars(std::basic_string_view::const_pointer, std::basic_string_view ::const_pointer, float&)’
36 | if (std::from_chars(s.data(), s.data() + s.size(), value).ec == std::errc{})
| ~~~~~~~~~~~~~~~~~~~~~~~~^
从main.cpp:25包含的文件中:
/usr/include/c++/10/charconv:595:5: 注意:候选:‘templatestd::__detail::__integer_from_chars_result_type<_Tp> std::from_chars(const char*, const char*, _Tp&, int)’
595 | from_chars(const char* __first, const char* __last, _Tp& __value,
| ^~~~~~~~~~
/usr/include/c++/10/charconv:595:5: 注意:模板参数推导/替换失败:
从/usr/include/c++/10/bits/move.h:57包含的文件中,
从/usr/include/c++/10/bits/stl_pair.h:59包含,
从/usr/include/c++/10/bits/stl_algobase.h:64包含,
从/usr/include/c++/10/vector:60包含:
/usr/include/c++/10/type_traits: 在替换‘template<bool _Cond, class _Tp> using enable_if_t = typename std::enable_if<_Cond, _Tp>::type [with bool _Cond = false; _Tp = std::from_chars_result]’时:
/usr/include/c++/10/charconv:584:11: 由‘templateusing __integer_from_chars_result_type = std::enable_if_t<std::or<std::or<std::is_same<typename std::remove_cv<_Tp>::type, signed char>, std::is_same<typename std::remove_cv<_Tp>::type, short int>, std::is_same<typename std::remove_cv<_Tp>::type, int>, std::is_same<typename std::remove_cv<_Tp>::type, long int>, std::is_same<typename std::remove_cv<_Tp>::type, long long int> >, std::or<std::is_same<typename std::remove_cv<_Tp>::type, unsigned char>, std::is_same<typename std::remove_cv<_Tp>::type, short unsigned int>, std::is_same<typename std::remove_cv<_Tp>::type, unsigned int>, std::is_same<typename std::remove_cv<_Tp>::type, long unsigned int>, std::is_same<typename std::remove_cv<_Tp>::type, long long unsigned int> >, std::is_same<char, typename std::remove_cv<_Tp>::type> >::value, std::from_chars_result> [with _Tp = float]’的替换需要
/usr/include/c++/10/charconv:595:5: 由‘templatestd::__detail::__integer_from_chars_result_type<_Tp> std::from_chars(const char*, const char*, _Tp&, int) [with _Tp = float]’的替换需要
main.cpp:36:24: 由‘std::optional<_Tp> to_float(std::string_view) [with T = float; std::string_view = std::basic_string_view]’的替换需要
main.cpp:633:92: 从此处要求
/usr/include/c++/10/type_traits:2554:11: 错误:‘struct std::enable_if<false, std::from_chars_result>’中没有名为‘type’的类型
2554 | using enable_if_t = typename enable_if<_Cond, _Tp>::type;
解决方案
由于无法升级GCC,可采用以下两种替代方案:
方案1:使用std::stof/std::stod/std::stold替代
利用标准库中成熟的字符串转浮点数函数,结合异常处理实现等价逻辑:
#include <concepts> #include <optional> #include <string_view> #include <stdexcept> #include <string> template<std::floating_point T> std::optional<T> to_float(std::string_view s) { try { if constexpr (std::is_same_v<T, float>) { return std::stof(std::string(s)); } else if constexpr (std::is_same_v<T, double>) { return std::stod(std::string(s)); } else if constexpr (std::is_same_v<T, long double>) { return std::stold(std::string(s)); } } catch (const std::invalid_argument&) { // 无法解析为有效浮点数 } catch (const std::out_of_range&) { // 数值超出目标类型范围 } return {}; } int main() { auto val = to_float<float>("0"); return 0; }
注:将std::string_view转为std::string是因为GCC10对std::stof系列函数的string_view重载支持不完善,转换后兼容性更强。
方案2:手动实现浮点数解析或使用兼容第三方库
如果需要避免异常开销或更精细的解析控制,可以手动实现简易的浮点数解析逻辑;也可以选择abseil、fmt等兼容GCC10的第三方库,调用其内置的字符串转浮点数接口。
补充说明
GCC从版本11开始才完整实现了<charconv>中std::from_chars的浮点数重载,这是GCC10的已知兼容性缺陷。若后续有升级可能,升级至GCC11+即可直接使用原代码。
内容的提问来源于stack exchange,提问作者0xbadf00d

