#pragma once #include "string_literal.h" namespace saw { template struct parameter_pack_index; template struct parameter_pack_index { static constexpr size_t value = 0u; }; template struct parameter_pack_index { static constexpr size_t value = 1u + parameter_pack_index::value; }; template struct parameter_pack_type { static_assert(always_false, "Should've been caught by the specializations"); }; template struct parameter_pack_type<0, TN, T...> { using type = TN; }; template struct parameter_pack_type { static_assert(sizeof...(T) > 0, "Exhausted parameters"); static_assert(N > 0, "Invalid number. Should've been caught"); using type = typename parameter_pack_type::type; }; /* * Nightmare inducing compiler problems found here. Somehow non-type * string_literals cannot be resolved as non-type primitive template values can. * This is the workaround */ template struct parameter_key_pack_index_helper { static constexpr size_t value = (V == Key0) ? (0u) : (1u + parameter_key_pack_index_helper::value); }; template struct parameter_key_pack_index_helper { static constexpr size_t value = (V == Key0) ? (0u) : (1u); }; template struct parameter_key_pack_index { static constexpr size_t value = parameter_key_pack_index_helper::value; static_assert(value < sizeof...(Keys), "Provided string_literal doesn't exist in searched list"); }; template struct parameter_key_pack_type_helper { static constexpr string_literal literal = parameter_key_pack_type_helper::literal; }; template struct parameter_key_pack_type_helper { static constexpr string_literal literal = Key0; }; template struct parameter_key_pack_type { static constexpr string_literal literal = parameter_key_pack_type_helper::literal; static_assert(i < sizeof...(Keys), "Provided index is too large for list"); }; template struct parameter_pack_value_helper { static constexpr T value = parameter_pack_value_helper::value; }; template struct parameter_pack_value_helper { static constexpr T value = V0; }; template struct parameter_pack_value { static constexpr T value = parameter_pack_value_helper::value; static_assert(i < sizeof...(Values), "Provided index is too large for list"); }; template struct ct_multiply; template struct ct_multiply { static constexpr T value = 1; }; template struct ct_multiply { static constexpr T value = V0 * ct_multiply::value; }; namespace impl { template struct ct_convert_digits_table_helper { static constexpr std::array table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; static constexpr T value = table[i]; }; template struct ct_convert_digits_helper { static constexpr size_t size = ct_convert_digits_helper::size; static constexpr std::array value = ct_convert_digits_helper::value; }; template struct ct_convert_digits_helper<0, Base, Digs...> { static constexpr size_t size = sizeof...(Digs); static constexpr std::array value = {Digs...}; }; template struct ct_convert_digits_helper<0, Base> { static constexpr size_t size = 0; static constexpr std::array value = {0}; }; } template struct ct_convert_to_digits { static_assert(Base <= 16, "Only conversion up to hex is supported"); static constexpr size_t size = impl::ct_convert_digits_helper::size; static constexpr std::array value = impl::ct_convert_digits_helper::value; }; }