Skip to content

Commit 2f21d9b

Browse files
committed
Add constexpr support for assignment from string
1 parent 484eb39 commit 2f21d9b

File tree

1 file changed

+30
-13
lines changed

1 file changed

+30
-13
lines changed

include/boost/multiprecision/cpp_int.hpp

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,23 @@ namespace detail {
132132

133133
alloc.deallocate(data, n);
134134
}
135+
136+
static BOOST_MP_CXX14_CONSTEXPR std::size_t constexpr_strlen(const char* str)
137+
{
138+
# ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
139+
if (BOOST_MP_IS_CONST_EVALUATED(str)) {
140+
const char* end = str;
141+
142+
while (*end != '\0') {
143+
end++;
144+
}
145+
146+
return end - str;
147+
}
148+
# endif
149+
150+
return std::strlen(str);
151+
}
135152
} // Namespace detail
136153

137154
template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, bool trivial = false>
@@ -1756,9 +1773,9 @@ struct cpp_int_backend
17561773
}
17571774

17581775
private:
1759-
void do_assign_string(const char* s, const std::integral_constant<bool, true>&)
1776+
BOOST_MP_CXX14_CONSTEXPR void do_assign_string(const char* s, const std::integral_constant<bool, true>&)
17601777
{
1761-
std::size_t n = s ? std::strlen(s) : 0;
1778+
std::size_t n = s ? detail::constexpr_strlen(s) : 0;
17621779
*this = 0;
17631780
unsigned radix = 10;
17641781
bool isneg = false;
@@ -1784,7 +1801,7 @@ struct cpp_int_backend
17841801
}
17851802
if (n)
17861803
{
1787-
unsigned val;
1804+
unsigned val = 0;
17881805
while (*s)
17891806
{
17901807
if (*s >= '0' && *s <= '9')
@@ -1807,11 +1824,11 @@ struct cpp_int_backend
18071824
if (isneg)
18081825
this->negate();
18091826
}
1810-
void do_assign_string(const char* s, const std::integral_constant<bool, false>&)
1827+
BOOST_MP_CXX14_CONSTEXPR void do_assign_string(const char* s, const std::integral_constant<bool, false>&)
18111828
{
18121829
using default_ops::eval_add;
18131830
using default_ops::eval_multiply;
1814-
std::size_t n = s ? std::strlen(s) : 0;
1831+
std::size_t n = s ? detail::constexpr_strlen(s) : 0;
18151832
*this = static_cast<limb_type>(0u);
18161833
unsigned radix = 10;
18171834
bool isneg = false;
@@ -1847,9 +1864,9 @@ struct cpp_int_backend
18471864
{
18481865
while (*s == '0')
18491866
++s;
1850-
std::size_t bitcount = 4 * std::strlen(s);
1851-
limb_type val;
1852-
std::size_t limb, shift;
1867+
std::size_t bitcount = 4 * detail::constexpr_strlen(s);
1868+
limb_type val = 0;
1869+
std::size_t limb = 0, shift = 0;
18531870
if (bitcount > 4)
18541871
bitcount -= 4;
18551872
else
@@ -1889,9 +1906,9 @@ struct cpp_int_backend
18891906
{
18901907
while (*s == '0')
18911908
++s;
1892-
std::size_t bitcount = 3 * std::strlen(s);
1893-
limb_type val;
1894-
std::size_t limb, shift;
1909+
std::size_t bitcount = 3 * detail::constexpr_strlen(s);
1910+
limb_type val = 0;
1911+
std::size_t limb = 0, shift = 0;
18951912
if (bitcount > 3)
18961913
bitcount -= 3;
18971914
else
@@ -1950,7 +1967,7 @@ struct cpp_int_backend
19501967
limb_type block = 0;
19511968
for (unsigned i = 0; i < digits_per_block_10; ++i)
19521969
{
1953-
limb_type val;
1970+
limb_type val = 0;
19541971
if (*s >= '0' && *s <= '9')
19551972
val = static_cast<limb_type>(*s - '0');
19561973
else
@@ -1980,7 +1997,7 @@ struct cpp_int_backend
19801997
}
19811998

19821999
public:
1983-
cpp_int_backend& operator=(const char* s)
2000+
BOOST_MP_CXX14_CONSTEXPR cpp_int_backend& operator=(const char* s)
19842001
{
19852002
do_assign_string(s, trivial_tag());
19862003
return *this;

0 commit comments

Comments
 (0)