Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions doc/decimal/charconv.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,18 @@ namespace decimal {
template <typename DecimalType>
constexpr boost::decimal::from_chars_result from_chars(const char* first, const char* last, DecimalType& value, boost::decimal::chars_format fmt = boost::decimal::chars_format::general) noexcept

#ifdef BOOST_DECIMAL_HAS_STD_STRING_VIEW

template <typename DecimalType>
constexpr boost::decimal::from_chars_result from_chars(std::string_view str, DecimalType& value, boost::decimal::chars_format fmt = boost::decimal::chars_format::general) noexcept

#else

template <typename DecimalType>
constexpr boost::decimal::from_chars_result from_chars(const std::string& str, DecimalType& value, boost::decimal::chars_format fmt = boost::decimal::chars_format::general) noexcept

#endif

#ifdef BOOST_DECIMAL_HAS_STD_CHARCONV

template <typename DecimalType>
Expand Down
2 changes: 2 additions & 0 deletions doc/decimal/config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,5 @@ This flag increases the performance of the basis operations (e.g. add, sub, mul,
- `BOOST_DECIMAL_HAS_STD_CHARCONV`: This macro is defined if header `<charconv>` exists and the language standard used is >= C++17
* We only need the structs and enums out of the header so we are not concerned with being overly restrictive about the feature test macros.
** Known compilers that support this lighter requirement are: GCC >= 10, Clang >= 13, and MSVC >= 14.2

- `BOOST_DECIMAL_HAS_STD_STRING_VIEW`: This macro is defined if header `<string_view>` exists and the langauge standard used is >= C++17
83 changes: 83 additions & 0 deletions include/boost/decimal/charconv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@

#if !defined(BOOST_DECIMAL_DISABLE_CLIB)

#ifndef BOOST_DECIMAL_BUILD_MODULE
#include <string>
#endif

namespace boost {
namespace decimal {

Expand Down Expand Up @@ -94,31 +98,103 @@ BOOST_DECIMAL_EXPORT constexpr auto from_chars(const char* first, const char* la
return detail::from_chars_general_impl(first, last, value, fmt);
}

#ifndef BOOST_DECIMAL_HAS_STD_STRING_VIEW
BOOST_DECIMAL_EXPORT inline auto from_chars(const std::string& str, decimal32& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(str.data(), str.data() + str.size(), value, fmt);
}
#else
BOOST_DECIMAL_EXPORT constexpr auto from_chars(std::string_view str, decimal32& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(str.data(), str.data() + str.size(), value, fmt);
}
#endif

BOOST_DECIMAL_EXPORT constexpr auto from_chars(const char* first, const char* last, decimal32_fast& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(first, last, value, fmt);
}

#ifndef BOOST_DECIMAL_HAS_STD_STRING_VIEW
BOOST_DECIMAL_EXPORT inline auto from_chars(const std::string& str, decimal32_fast& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(str.data(), str.data() + str.size(), value, fmt);
}
#else
BOOST_DECIMAL_EXPORT constexpr auto from_chars(std::string_view str, decimal32_fast& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(str.data(), str.data() + str.size(), value, fmt);
}
#endif

BOOST_DECIMAL_EXPORT constexpr auto from_chars(const char* first, const char* last, decimal64& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(first, last, value, fmt);
}

#ifndef BOOST_DECIMAL_HAS_STD_STRING_VIEW
BOOST_DECIMAL_EXPORT inline auto from_chars(const std::string& str, decimal64& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(str.data(), str.data() + str.size(), value, fmt);
}
#else
BOOST_DECIMAL_EXPORT constexpr auto from_chars(std::string_view str, decimal64& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(str.data(), str.data() + str.size(), value, fmt);
}
#endif

BOOST_DECIMAL_EXPORT constexpr auto from_chars(const char* first, const char* last, decimal64_fast& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(first, last, value, fmt);
}

#ifndef BOOST_DECIMAL_HAS_STD_STRING_VIEW
BOOST_DECIMAL_EXPORT inline auto from_chars(const std::string& str, decimal64_fast& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(str.data(), str.data() + str.size(), value, fmt);
}
#else
BOOST_DECIMAL_EXPORT constexpr auto from_chars(std::string_view str, decimal64_fast& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(str.data(), str.data() + str.size(), value, fmt);
}
#endif

BOOST_DECIMAL_EXPORT constexpr auto from_chars(const char* first, const char* last, decimal128& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(first, last, value, fmt);
}

#ifndef BOOST_DECIMAL_HAS_STD_STRING_VIEW
BOOST_DECIMAL_EXPORT inline auto from_chars(const std::string& str, decimal128& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(str.data(), str.data() + str.size(), value, fmt);
}
#else
BOOST_DECIMAL_EXPORT constexpr auto from_chars(std::string_view str, decimal128& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(str.data(), str.data() + str.size(), value, fmt);
}
#endif

BOOST_DECIMAL_EXPORT constexpr auto from_chars(const char* first, const char* last, decimal128_fast& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(first, last, value, fmt);
}

#ifndef BOOST_DECIMAL_HAS_STD_STRING_VIEW
BOOST_DECIMAL_EXPORT inline auto from_chars(const std::string& str, decimal128_fast& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(str.data(), str.data() + str.size(), value, fmt);
}
#else
BOOST_DECIMAL_EXPORT constexpr auto from_chars(std::string_view str, decimal128_fast& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(str.data(), str.data() + str.size(), value, fmt);
}
#endif

#ifdef BOOST_DECIMAL_HAS_STD_CHARCONV
BOOST_DECIMAL_EXPORT template <typename DecimalType>
constexpr auto from_chars(const char* first, const char* last, DecimalType& value, std::chars_format fmt) noexcept
Expand Down Expand Up @@ -147,6 +223,13 @@ constexpr auto from_chars(const char* first, const char* last, DecimalType& valu

return std::from_chars_result {boost_r.ptr, boost_r.ec};
}

BOOST_DECIMAL_EXPORT template <typename DecimalType>
constexpr auto from_chars(std::string_view str, DecimalType& value, std::chars_format fmt) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, DecimalType, std::from_chars_result)
{
return from_chars(str.data(), str.data() + str.size(), value, fmt);
}
#endif

// ---------------------------------------------------------------------------------------------------------------------
Expand Down
10 changes: 10 additions & 0 deletions include/boost/decimal/detail/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,16 @@ typedef unsigned __int128 uint128_t;
# define BOOST_DECIMAL_HAS_STD_CHARCONV
# endif
# endif

# if __has_include(<string_view>)
# ifndef BOOST_DECIMAL_BUILD_MODULE
# include <string_view>
# endif
# if __cpp_lib_string_view >= 201606L
# define BOOST_DECIMAL_HAS_STD_STRING_VIEW
# endif
# endif

#endif

// Since we should not be able to pull these in from the STL in module mode define them ourselves
Expand Down
1 change: 1 addition & 0 deletions modules/decimal.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ module;
#include <complex>
#include <compare>
#include <charconv>
#include <string_view>

// <stdfloat> is a C++23 feature that is not everywhere yet
#if __has_include(<stdfloat>)
Expand Down
25 changes: 25 additions & 0 deletions test/test_from_chars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ void test_non_finite_values()

const char* snan_str = "nan(snan)";
auto r = from_chars(snan_str, snan_str + std::strlen(snan_str), val);
BOOST_TEST(r);
BOOST_TEST(isnan(val));

const char* qnan_str = "nan";
Expand Down Expand Up @@ -318,6 +319,17 @@ void test_from_chars_general_std()

#endif

template <typename T>
void test_string_interface()
{
constexpr T correct_val {42};
std::string str {"42"};
T val;
const auto r = from_chars(str, val);
BOOST_TEST(r);
BOOST_TEST_EQ(val, correct_val);
}

int main()
{
test_from_chars_scientific<decimal32>();
Expand Down Expand Up @@ -362,12 +374,25 @@ int main()
test_hex_values<decimal32_fast>();
test_hex_values<decimal64_fast>();

test_string_interface<decimal32>();
test_string_interface<decimal64>();
test_string_interface<decimal32_fast>();
test_string_interface<decimal64_fast>();

#if !defined(BOOST_DECIMAL_REDUCE_TEST_DEPTH)
test_from_chars_scientific<decimal128>();
test_from_chars_fixed<decimal128>();
test_from_chars_general<decimal128>();
test_non_finite_values<decimal128>();
test_hex_values<decimal128>();
test_string_interface<decimal128>();

test_from_chars_scientific<decimal128_fast>();
test_from_chars_fixed<decimal128_fast>();
test_from_chars_general<decimal128_fast>();
test_non_finite_values<decimal128_fast>();
test_hex_values<decimal128_fast>();
test_string_interface<decimal128_fast>();
#endif

return boost::report_errors();
Expand Down
Loading