Make code a bit more readable

Changed so that int_conv<string_view>() called on a
non-constexpr doesn't compiler anymore (because code
would try to go through a consteval method). It
wouldn't work anyways as the returned value would be
always garbage. If you want a string_view then you
must either give a constexpr input value or you must
call int_conv_raw and call to_string_view() yourself.
This is better than throwing a runtime exception (which
was working ok btw).

All the SafeRetVal stuff is not needed anymore.

Also no need for all that confusing sfinae, I can just
use a bool FromInt and specialise on that.
This commit is contained in:
King_DuckZ 2021-05-29 16:44:06 +02:00
parent a675624cab
commit 938c8fa9a4
2 changed files with 44 additions and 23 deletions

View file

@ -22,11 +22,10 @@
#include <type_traits>
#include <string>
#include <string_view>
#include <stdexcept>
namespace dhandy {
namespace implem {
template <typename T, typename F, bool SafeRetval, typename Tr>
template <typename T, typename F, typename Tr, bool FromInt=std::is_integral_v<F>>
struct IntConv;
template <typename Tr>
@ -35,24 +34,21 @@ namespace dhandy {
template <typename Tr>
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> {
template <typename F, typename Tr>
struct IntConv<IntConvString<Tr>, F, Tr, true> {
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, typename Tr>
struct IntConv<std::enable_if_t<std::is_integral_v<F>, IntConvStringView<Tr>>, F, SafeRetval, Tr> {
constexpr static IntConvStringView<Tr> conv (const F& in) {
if (std::is_constant_evaluated() or not SafeRetval)
template <typename F, typename Tr>
struct IntConv<IntConvStringView<Tr>, F, Tr, true> {
consteval static IntConvStringView<Tr> conv (const F& in) {
return dhandy::int_to_ary<F, 10, Tr>(in).to_string_view();
else
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, typename Tr>
struct IntConv<T, std::enable_if_t<std::is_integral_v<T>, IntConvString<Tr>>, SafeRetval, Tr> {
template <typename T, typename Tr>
struct IntConv<T, IntConvString<Tr>, Tr, false> {
constexpr static T conv (const IntConvString<Tr>& in) {
return dhandy::ary_to_int<T, char, 10, Tr>(
in.data(),
@ -60,8 +56,8 @@ namespace dhandy {
);
}
};
template <typename T, bool SafeRetval, typename Tr>
struct IntConv<T, std::enable_if_t<std::is_integral_v<T>, IntConvStringView<Tr>>, SafeRetval, Tr> {
template <typename T, typename Tr>
struct IntConv<T, IntConvStringView<Tr>, Tr, false> {
constexpr static T conv (const IntConvStringView<Tr>& in) {
return dhandy::ary_to_int<T, char, 10, Tr>(
in.data(),
@ -69,8 +65,8 @@ namespace dhandy {
);
}
};
template <typename T, typename F, F In, bool SafeRetval, typename Tr>
struct IntConv<T, std::integral_constant<F, In>, SafeRetval, Tr> {
template <typename T, typename F, F In, typename Tr, bool FromInt>
struct IntConv<T, std::integral_constant<F, In>, Tr, FromInt> {
constexpr static T conv (const std::integral_constant<F, In>&) {
return dhandy::buildtime_int_to_ary<F, In, 10, Tr>().to_string_view();
}
@ -80,14 +76,14 @@ namespace dhandy {
template <typename To, typename From>
constexpr inline To int_conv (const From& from, bool all_caps=false) {
if (all_caps)
return implem::IntConv<To, From, true, ASCIITranslatorUpcase<char>>::conv(from);
return implem::IntConv<To, From, ASCIITranslatorUpcase<char>>::conv(from);
else
return implem::IntConv<To, From, true, ASCIITranslator<char>>::conv(from);
return implem::IntConv<To, From, ASCIITranslator<char>>::conv(from);
}
template <typename To, typename From>
constexpr inline To int_conv_temporary (const From& from) {
return implem::IntConv<To, From, false, ASCIITranslator<char>>::conv(from);
template <typename From>
inline auto int_conv_raw (const From& from) {
return int_to_ary<From, 10, ASCIITranslator<char>>(from);
}
} //namespace dhandy

View file

@ -23,6 +23,7 @@
#include <cstdint>
#include <random>
#include <string>
#include <ctime>
template <typename T> using int_info_10 = dhandy::implem::int_info<T, 10>;
template <typename T> using int_info_16 = dhandy::implem::int_info<T, 16>;
@ -142,7 +143,7 @@ TEST_CASE ("Check int to char array conversions", "[s2i][int_conv]") {
{
//Try a random test, which should not compile as constexpr
std::mt19937 gen;
gen.seed(1234);
gen.seed(std::time(nullptr));
for (int z = 0; z < 10; ++z) {
const int num = gen();
CHECK(int_to_ary(num) == std::to_string(num));
@ -199,6 +200,30 @@ TEST_CASE ("Check char array to int conversions", "[i2s][int_conv]") {
AryConversionTestHelperIns<std::int32_t, 16>("aAbBc", 0xaabbc, true);
}
TEST_CASE ("Check string_view conversions work as expected", "[i2s][int_conv]") {
using dhandy::int_conv;
using dhandy::int_conv_raw;
using std::string_view;
using std::integral_constant;
using std::string;
constexpr auto str71 = int_conv<string_view>(integral_constant<short int, 71>{});
CHECK("71" == str71);
{
//test random number to force non-constexpr
std::mt19937 gen;
gen.seed(std::time(nullptr));
const int num = gen();
const string num_str {int_conv_raw(num).to_string_view()};
CHECK(num_str == std::to_string(num));
}
const auto str123 = int_conv<string>(123);
CHECK("123" == str123);
}
TEST_CASE ("Check upcase/downcase int to array conversions", "[i2s][int_conv]") {
using dhandy::int_conv;
using std::string_view;