Ver código fonte

Add 'construct' function

This function allows you to construct a user type instance on the
stack and retrieve a reference to it.
Ole 10 anos atrás
pai
commit
0a69d863b7
2 arquivos alterados com 33 adições e 8 exclusões
  1. 30 1
      lib/luwra/usertypes.hpp
  2. 3 7
      tests/usertypes.cpp

+ 30 - 1
lib/luwra/usertypes.hpp

@@ -156,6 +156,35 @@ struct Value<U&> {
 	}
 };
 
+/**
+ * Construct a user type value on the stack.
+ * \note Instances created using this specialization are allocated and constructed as full user
+ *       data types in Lua. The default garbage-collecting hook will destruct the user type,
+ *       once it has been marked.
+ * \param state Lua state
+ * \param args  Constructor arguments
+ * \returns Reference to the constructed value
+ */
+template <typename U, typename... A> static inline
+internal::StripUserType<U>& construct(State* state, A&&... args) {
+	using T = internal::StripUserType<U>;
+
+	void* mem = lua_newuserdata(state, sizeof(T));
+
+	if (!mem) {
+		luaL_error(state, "Failed to allocate user type");
+		// 'luaL_error' will not return
+	}
+
+	// Construct
+	T* value = new (mem) T {std::forward<A>(args)...};
+
+	// Apply metatable for unqualified type T
+	internal::apply_user_type_meta_table<T>(state);
+
+	return *value;
+}
+
 /**
  * User type
  */
@@ -182,7 +211,7 @@ struct Value<U*> {
 	 * \param ptr   Pointer to the user type value
 	 * \returns Number of values that have been pushed
 	 */
-	static
+	static inline
 	size_t push(State* state, const T* ptr) {
 		return Value<T&>::push(state, *ptr);
 	}

+ 3 - 7
tests/usertypes.cpp

@@ -56,11 +56,9 @@ TEST_CASE("UserTypeFields") {
 	);
 
 	// Instantiation
-	luwra::Value<B&>::push(state, 1338);
+	B& value = luwra::construct<B>(state, 1338);
 	lua_setglobal(state, "value");
 
-	B& value = luwra::getGlobal<B&>(state, "value");
-
 	// Unqualified get
 	REQUIRE(luaL_dostring(state, "return value:n()") == 0);
 	puts(lua_tostring(state, -1));
@@ -134,11 +132,9 @@ TEST_CASE("UserTypeMethods") {
 	);
 
 	// Instantiation
-	luwra::Value<C&>::push(state, 1337);
+	C& value = luwra::construct<C>(state, 1337);
 	lua_setglobal(state, "value");
 
-	C& value = luwra::getGlobal<C&>(state, "value");
-
 	// Unqualified method
 	REQUIRE(luaL_dostring(state, "return value:foo1(63)") == 0);
 	REQUIRE(value.prop == 1400);
@@ -171,7 +167,7 @@ TEST_CASE("UserTypeGarbageCollectionRef") {
 	REQUIRE(shared_var.use_count() == 1);
 
 	// Copy construction
-	luwra::push<std::shared_ptr<int>&>(state, shared_var);
+	luwra::push(state, shared_var);
 	REQUIRE(shared_var.use_count() == 2);
 
 	// Garbage collection