Skip to content

Commit 4d6498d

Browse files
authored
Merge pull request #324 from cppalliance/317
Add `to_string` functions
2 parents eabfff6 + 0162243 commit 4d6498d

File tree

8 files changed

+191
-0
lines changed

8 files changed

+191
-0
lines changed

doc/modules/ROOT/nav.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
*** xref:api_reference.adoc#api_iostream[`<iostream>`]
2222
*** xref:api_reference.adoc#api_ios[`<ios>`]
2323
*** xref:api_reference.adoc#api_numeric[`<numeric>`]
24+
*** xref:api_reference.adoc#api_string[`<string>`]
2425
** xref:api_reference.adoc#api_macros[Macros]
2526
*** xref:api_reference.adoc#api_macro_literals[Literals]
2627
*** xref:api_reference.adoc#api_macro_configuration[Configuration]
@@ -47,6 +48,7 @@
4748
* xref:charconv.adoc[]
4849
* xref:stream.adoc[]
4950
* xref:numeric.adoc[]
51+
* xref:string.adoc[]
5052
* Benchmarks
5153
** xref:u128_benchmarks.adoc[]
5254
*** xref:u128_benchmarks.adoc#u128_linux[Linux]

doc/modules/ROOT/pages/api_reference.adoc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,16 @@ Listed by analogous STL header.
244244
| Midpoint between two values
245245
|===
246246

247+
[#api_string]
248+
=== xref:string.adoc[`<string>`]
249+
[cols="1,2", options="header"]
250+
|===
251+
| Function | Description
252+
253+
| xref:string.adoc[`to_string`]
254+
| `std::string` conversion of base-10 values
255+
|===
256+
247257
[#api_macros]
248258
== Macros
249259

doc/modules/ROOT/pages/string.adoc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
////
2+
Copyright 2026 Matt Borland
3+
Distributed under the Boost Software License, Version 1.0.
4+
https://www.boost.org/LICENSE_1_0.txt
5+
////
6+
7+
[#String]
8+
= `<string>`
9+
:idprefix: string_
10+
11+
[source,c++]
12+
----
13+
#include <boost/int128/string.hpp>
14+
----
15+
16+
The following are functions analogous to those found in `<string>` for builtin integer types.
17+
18+
[source,c++]
19+
----
20+
#include <boost/int128/string.hpp>
21+
22+
namespace boost {
23+
namespace int128 {
24+
25+
inline std::string to_string(const int128_t& value);
26+
inline std::string to_string(const uint128_t& value);
27+
28+
} // namespace int128
29+
} // namespace boost
30+
----
31+
32+
Returns a `std::string` containing the decimal(base-10) representation of `value`.
33+
These functions may throw `std::bad_alloc` from the constructor of `std::string`.
34+

include/boost/int128.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@
1414
#include <boost/int128/limits.hpp>
1515
#include <boost/int128/climits.hpp>
1616
#include <boost/int128/cstdlib.hpp>
17+
#include <boost/int128/string.hpp>
1718

1819
#endif // BOOST_INT128_HPP

include/boost/int128/string.hpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2025 Matt Borland
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// https://www.boost.org/LICENSE_1_0.txt
4+
5+
#ifndef BOOST_INT128_STRING_HPP
6+
#define BOOST_INT128_STRING_HPP
7+
8+
#include <boost/int128/int128.hpp>
9+
#include <boost/int128/detail/mini_to_chars.hpp>
10+
11+
#ifndef BOOST_INT128_BUILD_MODULE
12+
13+
#include <string>
14+
15+
#endif
16+
17+
namespace boost {
18+
namespace int128 {
19+
20+
template <typename T>
21+
auto to_string(const T& value) -> std::enable_if_t<(std::is_same<T, int128_t>::value || std::is_same<T, uint128_t>::value), std::string>
22+
{
23+
char buffer[64U] {};
24+
const auto last {detail::mini_to_chars(buffer, value, 10, false)};
25+
return std::string{last, buffer + sizeof(buffer)};
26+
}
27+
28+
} // namespace int128
29+
} // namespace boost
30+
31+
#endif // BOOST_INT128_STRING_HPP

test/Jamfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ run test_div.cpp ;
8585

8686
run test_num_digits.cpp ;
8787
run test_spaceship_operator.cpp ;
88+
run test_to_string.cpp ;
8889

8990
# Make sure we run the examples as well
9091
run ../examples/construction.cpp ;
@@ -122,3 +123,4 @@ compile compile_tests/iostream_compile.cpp ;
122123
compile compile_tests/limits_compile.cpp ;
123124
compile compile_tests/literals_compile.cpp ;
124125
compile compile_tests/numeric_compile.cpp ;
126+
compile compile_tests/string_compile.cpp ;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2025 Matt Borland
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// https://www.boost.org/LICENSE_1_0.txt
4+
5+
#include <boost/int128/string.hpp>
6+
7+
int main()
8+
{
9+
return 0;
10+
}

test/test_to_string.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright 2026 Matt Borland
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// https://www.boost.org/LICENSE_1_0.txt
4+
5+
#include <boost/int128.hpp>
6+
#include <boost/int128/charconv.hpp>
7+
#include <boost/charconv.hpp>
8+
#include <boost/core/lightweight_test.hpp>
9+
#include <string>
10+
#include <limits>
11+
#include <array>
12+
#include <cstdint>
13+
14+
using namespace boost::int128;
15+
16+
template <typename T>
17+
void test()
18+
{
19+
constexpr T min {std::numeric_limits<T>::min()};
20+
constexpr T max {std::numeric_limits<T>::max()};
21+
constexpr std::array<T, 4> values = {{ min, max, T{0}, T{42} }};
22+
23+
for (const auto value : values)
24+
{
25+
char buffer[64];
26+
const auto r {boost::charconv::to_chars(buffer, buffer + sizeof(buffer), value, 10)};
27+
BOOST_TEST(r);
28+
*r.ptr = '\0';
29+
30+
const auto value_str {to_string(value)};
31+
32+
BOOST_TEST_CSTR_EQ(buffer, value_str.c_str());
33+
}
34+
}
35+
36+
template <typename T, std::enable_if_t<std::is_signed<T>::value, bool> = true>
37+
void test_builtin()
38+
{
39+
constexpr T min {std::numeric_limits<T>::min()};
40+
constexpr T max {std::numeric_limits<T>::max()};
41+
constexpr std::array<T, 4> values = {{ min, max, T{0}, T{42} }};
42+
43+
for (const auto value : values)
44+
{
45+
char buffer[64];
46+
const auto r {boost::charconv::to_chars(buffer, buffer + sizeof(buffer), value, 10)};
47+
BOOST_TEST(r);
48+
*r.ptr = '\0';
49+
50+
const auto value_str {to_string(int128_t{value})};
51+
52+
BOOST_TEST_CSTR_EQ(buffer, value_str.c_str());
53+
BOOST_TEST_CSTR_EQ(std::to_string(value).c_str(), value_str.c_str());
54+
}
55+
}
56+
57+
template <typename T, std::enable_if_t<std::is_unsigned<T>::value, bool> = true>
58+
void test_builtin()
59+
{
60+
constexpr T min {std::numeric_limits<T>::min()};
61+
constexpr T max {std::numeric_limits<T>::max()};
62+
constexpr std::array<T, 4> values = {{ min, max, T{0}, T{42} }};
63+
64+
for (const auto value : values)
65+
{
66+
char buffer[64];
67+
const auto r {boost::charconv::to_chars(buffer, buffer + sizeof(buffer), value, 10)};
68+
BOOST_TEST(r);
69+
*r.ptr = '\0';
70+
71+
{
72+
const auto value_str {to_string(int128_t{value})};
73+
74+
BOOST_TEST_CSTR_EQ(buffer, value_str.c_str());
75+
BOOST_TEST_CSTR_EQ(std::to_string(value).c_str(), value_str.c_str());
76+
}
77+
{
78+
const auto value_str {to_string(uint128_t{value})};
79+
80+
BOOST_TEST_CSTR_EQ(buffer, value_str.c_str());
81+
BOOST_TEST_CSTR_EQ(std::to_string(value).c_str(), value_str.c_str());
82+
}
83+
}
84+
}
85+
86+
int main()
87+
{
88+
test<uint128_t>();
89+
test<int128_t>();
90+
91+
test_builtin<std::int8_t>();
92+
test_builtin<std::uint8_t>();
93+
test_builtin<std::int16_t>();
94+
test_builtin<std::uint16_t>();
95+
test_builtin<std::int32_t>();
96+
test_builtin<std::uint32_t>();
97+
test_builtin<std::int64_t>();
98+
test_builtin<std::uint64_t>();
99+
100+
return boost::report_errors();
101+
}

0 commit comments

Comments
 (0)