![]() |
|
|||
File indexing completed on 2025-09-15 08:55:05
0001 //------------------------------- -*- C++ -*- -------------------------------// 0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details 0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT) 0004 //---------------------------------------------------------------------------// 0005 //! \file corecel/io/StringEnumMapper.hh 0006 //---------------------------------------------------------------------------// 0007 #pragma once 0008 0009 #include <string_view> 0010 #include <type_traits> 0011 #include <unordered_map> 0012 0013 #include "corecel/Assert.hh" 0014 #include "corecel/cont/Range.hh" 0015 0016 namespace celeritas 0017 { 0018 //---------------------------------------------------------------------------// 0019 /*! 0020 * Map strings to enums for user input. 0021 * 0022 * Note that since a map is built at construction time, instances of this class 0023 * should be \c static to amortize the cost. The strings being converted *must* 0024 * exceed the lifetime of this class. (Usually it references `const char*`.) 0025 * 0026 * \todo If the size of the strings is short and there aren't a lot of them, it 0027 * will be faster to use a fixed-size array and search over them. 0028 * 0029 * Example: 0030 * \code 0031 void from_json(const nlohmann::json& j, GeantSetupOptions& opts) 0032 { 0033 static auto gspl_from_string 0034 = StringEnumMapper<PhysicsList>::from_cstring_func( 0035 to_cstring, "physics list"); 0036 opts.physics = gspl_from_string(j.at("physics").get<std::string>()); 0037 } 0038 \endcode 0039 */ 0040 template<class T> 0041 class StringEnumMapper 0042 { 0043 static_assert(std::is_enum<T>::value, "not an enum type"); 0044 static_assert(static_cast<int>(T::size_) >= 0, "invalid enum type"); 0045 0046 public: 0047 //!@{ 0048 //! \name Type aliases 0049 using EnumCStringFuncPtr = char const*(T); 0050 //!@} 0051 0052 public: 0053 // Construct from a "to_cstring" function pointer 0054 static inline StringEnumMapper<T> 0055 from_cstring_func(EnumCStringFuncPtr, char const* desc = nullptr); 0056 0057 // Construct with a function that takes an enum and returns a stringlike 0058 template<class U> 0059 // NOLINTNEXTLINE(bugprone-forwarding-reference-overload) 0060 explicit inline StringEnumMapper(U&& enum_to_string, 0061 char const* desc = nullptr); 0062 0063 // Convert from a string 0064 inline T operator()(std::string_view s) const; 0065 0066 private: 0067 char const* description_; 0068 std::unordered_map<std::string_view, T> map_; 0069 }; 0070 0071 //---------------------------------------------------------------------------// 0072 // INLINE DEFINITIONS 0073 //---------------------------------------------------------------------------// 0074 /*! 0075 * Construct using a \c to_cstring function. 0076 */ 0077 template<class T> 0078 StringEnumMapper<T> 0079 StringEnumMapper<T>::from_cstring_func(EnumCStringFuncPtr fp, char const* desc) 0080 { 0081 CELER_EXPECT(fp); 0082 return StringEnumMapper<T>{fp, desc}; 0083 } 0084 0085 //---------------------------------------------------------------------------// 0086 /*! 0087 * Construct with a "stringify" function. 0088 * 0089 * The result just has to be implicitly convertible to a \c std::string_view . 0090 */ 0091 template<class T> 0092 template<class U> 0093 // NOLINTNEXTLINE(bugprone-forwarding-reference-overload) 0094 StringEnumMapper<T>::StringEnumMapper(U&& enum_to_string, char const* desc) 0095 : description_(desc) 0096 { 0097 map_.reserve(static_cast<std::size_t>(T::size_)); 0098 for (auto v : celeritas::range(T::size_)) 0099 { 0100 auto iter_inserted = map_.insert({enum_to_string(v), v}); 0101 CELER_ASSERT(iter_inserted.second); 0102 } 0103 } 0104 0105 //---------------------------------------------------------------------------// 0106 /*! 0107 * Convert a string_view to the corresponding enum. 0108 */ 0109 template<class T> 0110 T StringEnumMapper<T>::operator()(std::string_view s) const 0111 { 0112 auto result = map_.find(s); 0113 CELER_VALIDATE(result != map_.end(), 0114 << "invalid " << (description_ ? description_ : "value") 0115 << " '" << s << '\''); 0116 return result->second; 0117 } 0118 0119 //---------------------------------------------------------------------------// 0120 } // namespace celeritas
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |