From c39940d37bfcd1dbc1096911abc8b0a902b50af6 Mon Sep 17 00:00:00 2001 From: andrei Date: Sat, 27 Jan 2024 00:20:58 +0200 Subject: [PATCH] item/tname: add some static_asserts to ensure sanity --- src/item_tname.cpp | 98 ++++++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 39 deletions(-) diff --git a/src/item_tname.cpp b/src/item_tname.cpp index 53d331f3602df..6620bdc324837 100644 --- a/src/item_tname.cpp +++ b/src/item_tname.cpp @@ -520,51 +520,71 @@ std::string category( item const &it, unsigned int /* quantity */, // function type that prints an element of tname::segments using decl_f_print_segment = std::string( item const &it, unsigned int quantity, segment_bitset const &segments ); -std::unordered_map const segment_map = { - { tname::segments::FAULTS, faults }, - { tname::segments::DIRT, dirt_symbol }, - { tname::segments::OVERHEAT, overheat_symbol }, - { tname::segments::FAVORITE_PRE, pre_asterisk }, - { tname::segments::DURABILITY, durability }, - { tname::segments::WHEEL_DIAMETER, wheel_diameter }, - { tname::segments::BURN, burn }, - { tname::segments::TYPE, label }, - { tname::segments::CATEGORY, category }, - { tname::segments::MODS, mods }, - { tname::segments::CRAFT, craft }, - { tname::segments::WHITEBLACKLIST, wbl_mark }, - { tname::segments::CHARGES, noop }, - { tname::segments::CONTENTS, contents }, - { tname::segments::FOOD_TRAITS, food_traits }, - { tname::segments::LOCATION_HINT, location_hint }, - { tname::segments::ETHEREAL, ethereal }, - { tname::segments::FOOD_STATUS, food_status }, - { tname::segments::FOOD_IRRADIATED, food_irradiated }, - { tname::segments::TEMPERATURE, temperature }, - { tname::segments::CLOTHING_SIZE, clothing_size }, - { tname::segments::FILTHY, filthy }, - { tname::segments::BROKEN, segment_broken }, - { tname::segments::CBM_STATUS, cbm_status }, - { tname::segments::UPS, ups }, - { tname::segments::WETNESS, wetness }, - { tname::segments::ACTIVE, active }, - { tname::segments::SEALED, sealed }, - { tname::segments::FAVORITE_POST, post_asterisk }, - { tname::segments::WEAPON_MODS, weapon_mods }, - { tname::segments::RELIC, relic_charges }, - { tname::segments::LINK, noop }, - { tname::segments::VARS, vars }, - { tname::segments::TECHNIQUES, noop }, - { tname::segments::TAGS, tags }, -}; - +constexpr size_t num_segments = static_cast( tname::segments::last_segment ); + +constexpr std::array get_segs_array() +{ + std::array arr{}; + arr[static_cast( tname::segments::FAULTS ) ] = faults; + arr[static_cast( tname::segments::DIRT ) ] = dirt_symbol; + arr[static_cast( tname::segments::OVERHEAT ) ] = overheat_symbol; + arr[static_cast( tname::segments::FAVORITE_PRE ) ] = pre_asterisk; + arr[static_cast( tname::segments::DURABILITY ) ] = durability; + arr[static_cast( tname::segments::WHEEL_DIAMETER ) ] = wheel_diameter; + arr[static_cast( tname::segments::BURN ) ] = burn; + arr[static_cast( tname::segments::WEAPON_MODS ) ] = weapon_mods; + arr[static_cast( tname::segments::TYPE ) ] = label; + arr[static_cast( tname::segments::CATEGORY ) ] = category; + arr[static_cast( tname::segments::MODS ) ] = mods; + arr[static_cast( tname::segments::CRAFT ) ] = craft; + arr[static_cast( tname::segments::WHITEBLACKLIST ) ] = wbl_mark; + arr[static_cast( tname::segments::CHARGES ) ] = noop; + arr[static_cast( tname::segments::FOOD_TRAITS ) ] = food_traits; + arr[static_cast( tname::segments::FOOD_STATUS ) ] = food_status; + arr[static_cast( tname::segments::FOOD_IRRADIATED ) ] = food_irradiated; + arr[static_cast( tname::segments::TEMPERATURE ) ] = temperature; + arr[static_cast( tname::segments::LOCATION_HINT ) ] = location_hint; + arr[static_cast( tname::segments::CLOTHING_SIZE ) ] = clothing_size; + arr[static_cast( tname::segments::ETHEREAL ) ] = ethereal; + arr[static_cast( tname::segments::FILTHY ) ] = filthy; + arr[static_cast( tname::segments::BROKEN ) ] = segment_broken; + arr[static_cast( tname::segments::CBM_STATUS ) ] = cbm_status; + arr[static_cast( tname::segments::UPS ) ] = ups; + arr[static_cast( tname::segments::TAGS ) ] = tags; + arr[static_cast( tname::segments::VARS ) ] = vars; + arr[static_cast( tname::segments::WETNESS ) ] = wetness; + arr[static_cast( tname::segments::ACTIVE ) ] = active; + arr[static_cast( tname::segments::SEALED ) ] = sealed; + arr[static_cast( tname::segments::FAVORITE_POST ) ] = post_asterisk; + arr[static_cast( tname::segments::RELIC ) ] = relic_charges; + arr[static_cast( tname::segments::LINK ) ] = noop; + arr[static_cast( tname::segments::TECHNIQUES ) ] = noop; + arr[static_cast( tname::segments::CONTENTS ) ] = contents; + + return arr; +} +constexpr bool all_segments_have_printers() +{ + for( decl_f_print_segment *printer : get_segs_array() ) { + if( printer == nullptr ) { + return false; + } + } + return true; +} } // namespace +static_assert( all_segments_have_printers(), + "every element of tname::segments (up to tname::segments::last_segment) " + "must map to a printer in segs_array" ); + namespace tname { std::string print_segment( tname::segments segment, item const &it, unsigned int quantity, segment_bitset const &segments ) { - return ( *segment_map.at( segment ) )( it, quantity, segments ); + static std::array const arr = get_segs_array(); + size_t const idx = static_cast( segment ); + return ( *arr.at( idx ) )( it, quantity, segments ); } } // namespace tname