diff --git a/include/sol/state_view.hpp b/include/sol/state_view.hpp index 3c3c6e2a..be62ff1a 100644 --- a/include/sol/state_view.hpp +++ b/include/sol/state_view.hpp @@ -652,9 +652,9 @@ namespace sol { return *this; } - template - usertype new_usertype(const std::string& name, optional no_default_constructor = nullopt) { - return global.new_usertype(name, std::move(no_default_constructor)); + template + usertype new_usertype(const std::string& name, Args&&... args) { + return global.new_usertype(name, std::forward(args)...); } template diff --git a/include/sol/table.hpp b/include/sol/table.hpp index d58d96ef..06224ff3 100644 --- a/include/sol/table.hpp +++ b/include/sol/table.hpp @@ -31,10 +31,11 @@ namespace sol { typedef table_core table; template - template - usertype basic_table_core::new_usertype(Key&& key, optional no_default_constructor /* = nullopt*/) { - int mt_index = u_detail::register_usertype(this->lua_state(), std::move(no_default_constructor)); + template + usertype basic_table_core::new_usertype(Key&& key, Args&&... args) { + int mt_index = u_detail::register_usertype(this->lua_state(), detail::any_is_constructor_v ? optional() : optional(no_constructor)); usertype mt(this->lua_state(), -mt_index); + mt. set(std::forward(key), mt); return mt; } diff --git a/include/sol/types.hpp b/include/sol/types.hpp index 6bff6c0e..37a57018 100644 --- a/include/sol/types.hpp +++ b/include/sol/types.hpp @@ -1208,7 +1208,10 @@ namespace sol { struct is_constructor> : is_constructor> {}; template - using has_constructor = meta::any>...>; + using any_is_constructor = meta::any>...>; + + template + using any_is_constructor_v = any_is_constructor::value; template struct is_destructor : std::false_type {}; diff --git a/include/sol/usertype_storage.hpp b/include/sol/usertype_storage.hpp index c5ce2e16..4070e3c7 100644 --- a/include/sol/usertype_storage.hpp +++ b/include/sol/usertype_storage.hpp @@ -147,7 +147,8 @@ namespace u_detail { struct usertype_storage_base { public: std::vector> storage; - detail::unordered_map string_keys; + std::vector> string_keys_storage; + detail::unordered_map string_keys; detail::unordered_map auxiliary_keys; reference value_index_table; reference reference_index_table; @@ -174,6 +175,13 @@ namespace u_detail { base_new_index.new_index = new_index_target_fail; } + void add_entry(string_view sv, index_call_storage ics) { + string_keys_storage.emplace_back(sv.begin(), sv.end()); + std::vector& sv_storage = string_keys_storage.back(); + string_view stored_sv(sv_storage.data(), sv_storage.size()); + string_keys.insert_or_assign(std::move(stored_sv), std::move(ics)); + } + void clear() { storage.clear(); string_keys.clear(); @@ -217,7 +225,7 @@ namespace u_detail { if (k_type == type::string) { index_call_storage* target = nullptr; { - std::string k = stack::get(L, 2); + string_view k = stack::get(L, 2); auto it = self.string_keys.find(k); if (it != self.string_keys.cend()) { target = &it->second; @@ -270,7 +278,7 @@ namespace u_detail { if (k_type == type::string) { index_call_storage* target = nullptr; { - std::string k = stack::get(L, 2); + string_view k = stack::get(L, 2); auto it = self.string_keys.find(k); if (it != self.string_keys.cend()) { target = &it->second; @@ -481,7 +489,7 @@ namespace u_detail { this->base_new_index = ics; } this->for_each_table(L, fet); - this->string_keys.insert_or_assign(std::move(s), std::move(ics)); + this->add_entry(s, std::move(ics)); } else { // the reference-based implementation might compare poorly and hash @@ -506,8 +514,7 @@ namespace u_detail { ics.binding_data = b.data(); ics.index = &b.index_call_with_; ics.new_index = &b.index_call_with_; - - this->string_keys.insert_or_assign(std::move(s), ics); + this->add_entry(s, std::move(ics)); } else { // its auxiliary and must be