Add support for constexpr string_view creation

This commit is contained in:
King_DuckZ 2021-05-28 02:06:28 +02:00
parent e62da38cf9
commit 422b475ce3
3 changed files with 74 additions and 21 deletions

View file

@ -168,6 +168,9 @@ namespace dhandy {
} }
}; };
template <typename I, I In, unsigned int Base, typename Tr>
inline constexpr const auto g_int_to_str = IntConversion<std::remove_cvref_t<I>, Base, Tr>::to_ary(In);
template <typename T> template <typename T>
[[gnu::always_inline,gnu::pure]] [[gnu::always_inline,gnu::pure]]
constexpr inline T negated_ifn (T n, bool negate) { constexpr inline T negated_ifn (T n, bool negate) {
@ -293,6 +296,11 @@ namespace dhandy {
template <typename C> template <typename C>
using ASCIITranslatorUpcase = ASCIITranslator<C, '0', 'A'>; using ASCIITranslatorUpcase = ASCIITranslator<C, '0', 'A'>;
template <typename I, I In, unsigned int Base=10, typename Tr=ASCIITranslator<char>>
constexpr inline const auto& buildtime_int_to_ary() {
return implem::g_int_to_str<I, In, Base, Tr>;
}
template <typename I, unsigned int Base=10, typename Tr=ASCIITranslator<char>> template <typename I, unsigned int Base=10, typename Tr=ASCIITranslator<char>>
constexpr inline auto int_to_ary (I in) { constexpr inline auto int_to_ary (I in) {
return implem::IntConversion<std::remove_cvref_t<I>, Base, Tr>::to_ary(in); return implem::IntConversion<std::remove_cvref_t<I>, Base, Tr>::to_ary(in);

View file

@ -26,47 +26,68 @@
namespace dhandy { namespace dhandy {
namespace implem { namespace implem {
template <typename T, typename F, bool SafeRetval> template <typename T, typename F, bool SafeRetval, typename Tr>
struct IntConv; struct IntConv;
template <typename F, bool SafeRetval> template <typename Tr>
struct IntConv<std::enable_if_t<std::is_integral_v<F>, std::string>, F, SafeRetval> { using IntConvString = std::basic_string<typename Tr::char_type>;
static std::string conv (const F& in) {
auto retval = dhandy::int_to_ary(in); template <typename Tr>
return std::string(retval.begin(), retval.end() - 1); using IntConvStringView = std::basic_string_view<typename Tr::char_type>;
template <typename F, bool SafeRetval, typename Tr>
struct IntConv<std::enable_if_t<std::is_integral_v<F>, IntConvString<Tr>>, F, SafeRetval, Tr> {
static IntConvString<Tr> conv (const F& in) {
auto retval = dhandy::int_to_ary<F, 10, Tr>(in);
return IntConvString<Tr>{retval.begin(), retval.end() - 1};
} }
}; };
template <typename F, bool SafeRetval> template <typename F, bool SafeRetval, typename Tr>
struct IntConv<std::enable_if_t<std::is_integral_v<F>, std::string_view>, F, SafeRetval> { struct IntConv<std::enable_if_t<std::is_integral_v<F>, IntConvStringView<Tr>>, F, SafeRetval, Tr> {
constexpr static std::string_view conv (const F& in) { constexpr static IntConvStringView<Tr> conv (const F& in) {
if (std::is_constant_evaluated() or not SafeRetval) if (std::is_constant_evaluated() or not SafeRetval)
return dhandy::int_to_ary(in).to_string_view(); return dhandy::int_to_ary<F, 10, Tr>(in).to_string_view();
else else
throw std::logic_error("Only callable in a constexpr context, call int_conv_temporary() instead if you know what you're doing"); throw std::logic_error("Only callable in a constexpr context, call int_conv_temporary() instead if you know what you're doing");
} }
}; };
template <typename T, bool SafeRetval> template <typename T, bool SafeRetval, typename Tr>
struct IntConv<T, std::enable_if_t<std::is_integral_v<T>, std::string>, SafeRetval> { struct IntConv<T, std::enable_if_t<std::is_integral_v<T>, IntConvString<Tr>>, SafeRetval, Tr> {
constexpr static T conv (const std::string& in) { constexpr static T conv (const IntConvString<Tr>& in) {
return dhandy::ary_to_int<T>(in.data(), in.data() + in.size()); return dhandy::ary_to_int<T, char, 10, Tr>(
in.data(),
in.data() + in.size()
);
} }
}; };
template <typename T, bool SafeRetval> template <typename T, bool SafeRetval, typename Tr>
struct IntConv<T, std::enable_if_t<std::is_integral_v<T>, std::string_view>, SafeRetval> { struct IntConv<T, std::enable_if_t<std::is_integral_v<T>, IntConvStringView<Tr>>, SafeRetval, Tr> {
constexpr static T conv (const std::string_view& in) { constexpr static T conv (const IntConvStringView<Tr>& in) {
return dhandy::ary_to_int<T>(in.data(), in.data() + in.size()); return dhandy::ary_to_int<T, char, 10, Tr>(
in.data(),
in.data() + in.size()
);
}
};
template <typename T, typename F, F In, bool SafeRetval, typename Tr>
struct IntConv<T, std::integral_constant<F, In>, SafeRetval, Tr> {
constexpr static T conv (const std::integral_constant<F, In>&) {
return dhandy::buildtime_int_to_ary<F, In, 10, Tr>().to_string_view();
} }
}; };
} //namespace implem } //namespace implem
template <typename To, typename From> template <typename To, typename From>
constexpr inline To int_conv (const From& from) { constexpr inline To int_conv (const From& from, bool all_caps=false) {
return implem::IntConv<To, From, true>::conv(from); if (all_caps)
return implem::IntConv<To, From, true, ASCIITranslatorUpcase<char>>::conv(from);
else
return implem::IntConv<To, From, true, ASCIITranslator<char>>::conv(from);
} }
template <typename To, typename From> template <typename To, typename From>
constexpr inline To int_conv_temporary (const From& from) { constexpr inline To int_conv_temporary (const From& from) {
return implem::IntConv<To, From, false>::conv(from); return implem::IntConv<To, From, false, ASCIITranslator<char>>::conv(from);
} }
} //namespace dhandy } //namespace dhandy

View file

@ -171,3 +171,27 @@ TEST_CASE ("Check char array to int conversions", "[i2s][int_conv]") {
AryConversionTestHelper<std::int64_t, 10>("-1", -1, false); AryConversionTestHelper<std::int64_t, 10>("-1", -1, false);
AryConversionTestHelper<std::int64_t, 10>("-510123123123", -510123123123, false); AryConversionTestHelper<std::int64_t, 10>("-510123123123", -510123123123, false);
} }
TEST_CASE ("Check upcase/downcase int to array conversions", "[i2s][int_conv]") {
using dhandy::int_conv;
using std::string_view;
using std::integral_constant;
constexpr auto bool1 = int_conv<string_view>(integral_constant<bool, true>{});
CHECK("1" == bool1);
constexpr auto bool2 = int_conv<string_view>(integral_constant<bool, false>{});
CHECK("0" == bool2);
constexpr auto int1 = int_conv<string_view>(integral_constant<int, 42>{});
CHECK("42" == int1);
constexpr auto int2 = int_conv<string_view>(integral_constant<unsigned int, 7777777>{});
CHECK("7777777" == int2);
constexpr auto int3 = int_conv<string_view>(integral_constant<int, -1234>{});
CHECK("-1234" == int3);
constexpr auto int4 = int_conv<string_view>(integral_constant<short int, -256>{});
CHECK("-256" == int4);
}