c++ - Fill runtime data at compile time with templates -


i have specific situation in prepare runtime structures @ compile time without need duplicate code.

i have 2 structs use register @ compile time types compiler wrote:

using typeid = u8;  template<typename t, typename type_id, type_id i> struct typehelper {   static constexpr type_id value = std::integral_constant<type_id, i>::value; };  template<typename t> struct type : typehelper<t, u8, __counter__> { static_assert(!std::is_same<t,t>::value, "must specialize type!"); }; 

these used in config header macro specialize type<t> multiple types require:

using type_size = unsigned char;  #define get_nth_macro(_1,_2,_3, name,...) name #define register_type(...) get_nth_macro(__va_args__, register_type3, register_type2, register_type1)(__va_args__)  #define register_type1(_type_) register_type2(_type_, _type_)  #define register_type2(_type_,_name_) \ constexpr typeid type_##_name_ = __counter__; \ template<> struct type<_type_> : typehelper<_type_, type_size, type_##_name_> { \   static constexpr const char* name = #_name_; \ };  register_type(void) register_type(s64) register_type(s32) 

so these expand

constexpr typeid type_void = 2;  template<> struct type<void> : typehelper<void, type_size, type_void> { static constexpr const char* name = "void"; };  constexpr typeid type_s64 = 3;  template<> struct type<s64> : typehelper<s64, type_size, type_s64> { static constexpr const char* name = "s64"; };  constexpr typeid type_s32 = 4; template<> struct type<s32> : typehelper<s32, type_size, type_s32> { static constexpr const char* name = "s32"; }; 

this working fine compiler requires runtime information these types, in addition must define auxiliary functions like

static typeid typeforident(const std::string& name); static const char* namefortype(typeid type); static void maptypename(typeid type, const std::string& name);  inline bool issigned(typeid type) {   return type == type<s8>::value || type == type<s16>::value ||   type == type<s32>::value || type == type<s64>::value; } 

and similar functions.

these functions must work without template arguments, typeid must normal argument. i'm required initialize such data in separate part of code, eg:

maptypename(type<s32>::value, "s32"); 

which uses static std::unordered_map<typeid, std::string>. of course implies must maintain twice code when of information available @ compile time through types defines.

i wondering if there's obscure trick i'm missing coalesce these register_type macro registers runtime information. haven't come yet maybe there's clever way manage this.

if not particularly concerned performance of registering run-time data map, use inline function returns reference static map instance, , generate "dummy" registrar instances in register_type macro fill map in constructor.


inline auto& registration_map() {     static std::unordered_map<int, std::string> m;     return m; }  struct registrar  {      registrar(int id, std::string s)      {         registration_map()[id] = std::move(s);        } };  template <typename t> struct typehelper { };  #define cat3_impl(a, b, c) ## b ## c #define cat3(a, b, c) cat3_impl(a, b, c)  #define register_type(id, type) \     template<> struct typehelper<type> { }; \     [[maybe_unused]] registrar cat3(unused_registrar_, __line__, type) {id, #type};  register_type(0, int) register_type(1, float) register_type(2, double)  int main() {     assert(registration_map()[0] == "int");     assert(registration_map()[1] == "float");     assert(registration_map()[2] == "double"); } 

full example on wandbox.


notes:

  • you may repeated registrations if same register_type included in multiple translation units.

  • cat3(unused_registrar_, __line__, type) used generate unique name not collide other register_type expansions.


Comments

Popular posts from this blog

php - How to add and update images or image url in Volusion using Volusion API -

javascript - IE9 error '$'is not defined -