Просмотр исходного кода

Generate user type identifiers during compile-time

Ole Krüger лет назад: 10
Родитель
Сommit
b20e765f73
1 измененных файлов с 25 добавлено и 37 удалено
  1. 25 37
      lib/luwra/usertypes.hpp

+ 25 - 37
lib/luwra/usertypes.hpp

@@ -13,19 +13,10 @@
 #include "functions.hpp"
 
 #include <map>
-#include <utility>
-#include <atomic>
-#include <cassert>
 
 LUWRA_NS_BEGIN
 
 namespace internal {
-	template <size_t>
-	std::atomic_size_t user_type_counter(0);
-
-	template <typename T>
-	std::string user_type_name = "";
-
 	template <typename T, typename... A>
 	int construct_user_type(State* state) {
 		return internal::Layout<int(A...)>::direct(
@@ -45,8 +36,15 @@ namespace internal {
 	}
 
 	template <typename T>
-	int stringify_user_type(State* state) {
-		return push(state, internal::user_type_name<T>);
+	std::string user_type_identifier =
+		"UD#" + std::to_string(uintmax_t(&destruct_user_type<T>));
+
+	template <typename T>
+	std::string stringify_user_type(T* val) {
+		return
+			internal::user_type_identifier<T>
+			+ "@"
+			+ std::to_string(uintmax_t(val));
 	}
 
 	template <typename T, typename R, R T::* property_pointer>
@@ -91,17 +89,13 @@ template <typename T>
 struct Value<T&> {
 	static inline
 	T& read(State* state, int n) {
-		assert(!internal::user_type_name<T>.empty());
-
 		return *static_cast<T*>(
-			luaL_checkudata(state, n, internal::user_type_name<T>.c_str())
+			luaL_checkudata(state, n, internal::user_type_identifier<T>.c_str())
 		);
 	}
 
 	template <typename... A> static inline
 	int push(State* state, A&&... args) {
-		assert(!internal::user_type_name<T>.empty());
-
 		void* mem = lua_newuserdata(state, sizeof(T));
 
 		if (!mem) {
@@ -113,7 +107,7 @@ struct Value<T&> {
 		new (mem) T(std::forward<A>(args)...);
 
 		// Set metatable for this type
-		luaL_getmetatable(state, internal::user_type_name<T>.c_str());
+		luaL_getmetatable(state, internal::user_type_identifier<T>.c_str());
 		lua_setmetatable(state, -2);
 
 		return 1;
@@ -129,22 +123,18 @@ template <typename T>
 struct Value<T*> {
 	static inline
 	T* read(State* state, int n) {
-		assert(!internal::user_type_name<T>.empty());
-
 		return static_cast<T*>(
-			luaL_checkudata(state, n, internal::user_type_name<T>.c_str())
+			luaL_checkudata(state, n, internal::user_type_identifier<T>.c_str())
 		);
 	}
 
 	static inline
 	int push(State* state, T* instance) {
-		assert(!internal::user_type_name<T>.empty());
-
 		// push instance as light user data
 		lua_pushlightuserdata(state, instance);
 
 		// Set metatable for this type
-		luaL_getmetatable(state, internal::user_type_name<T>.c_str());
+		luaL_getmetatable(state, internal::user_type_identifier<T>.c_str());
 		lua_setmetatable(state, -2);
 
 		return 1;
@@ -163,19 +153,16 @@ void register_user_type(
 	const std::map<const char*, CFunction>& meta_methods = {}
 ) {
 	// Setup an appropriate meta table name
-	if (internal::user_type_name<T>.empty())
-		internal::user_type_name<T> = "UD#" + std::to_string(internal::user_type_counter<0>++);
-
-	luaL_newmetatable(state, internal::user_type_name<T>.c_str());
+	luaL_newmetatable(state, internal::user_type_identifier<T>.c_str());
 
 	// Register methods
 	if (methods.size() > 0 && meta_methods.count("__index") == 0) {
-		lua_pushstring(state, "__index");
+		push(state, "__index");
 		lua_newtable(state);
 
 		for (auto& method: methods) {
-			lua_pushstring(state, method.first);
-			lua_pushcfunction(state, method.second);
+			push(state, method.first);
+			push(state, method.second);
 			lua_rawset(state, -3);
 		}
 
@@ -184,22 +171,22 @@ void register_user_type(
 
 	// Register garbage-collection hook
 	if (meta_methods.count("__gc") == 0) {
-		lua_pushstring(state, "__gc");
-		lua_pushcfunction(state, &internal::destruct_user_type<T>);
+		push(state, "__gc");
+		push(state, &internal::destruct_user_type<T>);
 		lua_rawset(state, -3);
 	}
 
 	// Register string representation function
 	if (meta_methods.count("__tostring") == 0) {
-		lua_pushstring(state, "__tostring");
-		lua_pushcfunction(state, &internal::stringify_user_type<T>);
+		push(state, "__tostring");
+		push(state, wrap_function<std::string(T*), &internal::stringify_user_type<T>>);
 		lua_rawset(state, -3);
 	}
 
 	// Insert meta methods
 	for (const auto& metamethod: meta_methods) {
-		lua_pushstring(state, metamethod.first);
-		lua_pushcfunction(state, metamethod.second);
+		push(state, metamethod.first);
+		push(state, metamethod.second);
 		lua_rawset(state, -3);
 	}
 
@@ -258,7 +245,8 @@ template <
 	typename R,
 	R T::* property_pointer
 >
-constexpr CFunction wrap_property = &internal::access_user_type_property<T, R, property_pointer>;
+constexpr CFunction wrap_property =
+	&internal::access_user_type_property<T, R, property_pointer>;
 
 LUWRA_NS_END