add functionality to have functions properly detected and the amount shifted over properly based on being a call constructor or not

This commit is contained in:
ThePhD 2017-01-09 23:25:28 -05:00
parent 490194f767
commit 66ad189797
5 changed files with 86 additions and 21 deletions

View File

@ -170,9 +170,10 @@ If you don't specify any constructor options at all and the type is `default_con
* ``{anything}, {some_factory_function}`` * ``{anything}, {some_factory_function}``
- Essentially binds whatever the function is to name ``{anything}`` - Essentially binds whatever the function is to name ``{anything}``
- When used WITH the ``sol::no_constructor`` option above (e.g. ``"new", sol::no_constructor`` and after that having ``"create", &my_creation_func``), one can remove typical constructor avenues and then only provide specific factory functions. Note that this combination is similar to using the ``sol::factories`` method mentioned earlier in this list. To control the destructor as well, see further below - When used WITH the ``sol::no_constructor`` option above (e.g. ``"new", sol::no_constructor`` and after that having ``"create", &my_creation_func``), one can remove typical constructor avenues and then only provide specific factory functions. Note that this combination is similar to using the ``sol::factories`` method mentioned earlier in this list. To control the destructor as well, see further below
* ``sol::call_constructor, {valid function / constructor / initializer / factory}`` * ``sol::call_constructor, {valid constructor / initializer / factory}``
- The purpose of this is to enable the syntax ``local v = my_class( 24 )`` and have that call a constructor; it has no other purpose - The purpose of this is to enable the syntax ``local v = my_class( 24 )`` and have that call a constructor; it has no other purpose
- This is compatible with luabind, kaguya and other Lua library syntaxes and looks similar to C++ syntax, but the general consensus in Programming with Lua and other places is to use a function named ``new`` - This is compatible with luabind, kaguya and other Lua library syntaxes and looks similar to C++ syntax, but the general consensus in Programming with Lua and other places is to use a function named ``new``
- Note that with the ``sol::call_constructor`` key, a construct type above must be specified. A free function without it will pass in the metatable describing this object as the first argument without that distinction, which can cause strange runtime errors.
usertype destructor options usertype destructor options
+++++++++++++++++++++++++++ +++++++++++++++++++++++++++

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script. // This file was generated with a script.
// Generated 2017-01-09 21:30:54.823287 UTC // Generated 2017-01-10 04:24:27.805667 UTC
// This header was generated with sol v2.15.7 (revision 969615f) // This header was generated with sol v2.15.7 (revision 490194f)
// https://github.com/ThePhD/sol2 // https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP #ifndef SOL_SINGLE_INCLUDE_HPP
@ -8071,7 +8071,7 @@ namespace sol {
}; };
static int call(lua_State* L, F& fx) { static int call(lua_State* L, F& fx) {
return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L), 1, fx); return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L) - boost, 1 + boost, fx);
} }
}; };
@ -10181,20 +10181,23 @@ namespace sol {
struct verified_tag {} const verified{}; struct verified_tag {} const verified{};
template <typename T> template <typename T>
struct is_constructor : std::false_type {}; struct is_non_factory_constructor : std::false_type {};
template <typename... Args>
struct is_non_factory_constructor<constructors<Args...>> : std::true_type {};
template <typename... Args> template <typename... Args>
struct is_constructor<constructors<Args...>> : std::true_type {}; struct is_non_factory_constructor<constructor_wrapper<Args...>> : std::true_type {};
template <typename... Args> template <>
struct is_constructor<constructor_wrapper<Args...>> : std::true_type {}; struct is_non_factory_constructor<no_construction> : std::true_type {};
template <typename T>
struct is_constructor : is_non_factory_constructor<T> {};
template <typename... Args> template <typename... Args>
struct is_constructor<factory_wrapper<Args...>> : std::true_type {}; struct is_constructor<factory_wrapper<Args...>> : std::true_type {};
template <>
struct is_constructor<no_construction> : std::true_type {};
template <typename... Args> template <typename... Args>
using has_constructor = meta::any<is_constructor<meta::unqualified_t<Args>>...>; using has_constructor = meta::any<is_constructor<meta::unqualified_t<Args>>...>;
@ -10419,8 +10422,14 @@ namespace sol {
template <std::size_t Idx, bool is_index = true, bool is_variable = false> template <std::size_t Idx, bool is_index = true, bool is_variable = false>
static int real_call_with(lua_State* L, usertype_metatable& um) { static int real_call_with(lua_State* L, usertype_metatable& um) {
typedef meta::unqualified_tuple_element_t<Idx - 1, Tuple> K;
typedef meta::unqualified_tuple_element_t<Idx, Tuple> F;
static const int boost =
!usertype_detail::is_non_factory_constructor<F>::value
&& std::is_same<K, call_construction>::value ?
1 : 0;
auto& f = std::get<Idx>(um.functions); auto& f = std::get<Idx>(um.functions);
return call_detail::call_wrapped<T, is_index, is_variable>(L, f); return call_detail::call_wrapped<T, is_index, is_variable, boost>(L, f);
} }
template <std::size_t Idx, bool is_index = true, bool is_variable = false> template <std::size_t Idx, bool is_index = true, bool is_variable = false>

View File

@ -501,7 +501,7 @@ namespace sol {
}; };
static int call(lua_State* L, F& fx) { static int call(lua_State* L, F& fx) {
return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L), 1, fx); return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L) - boost, 1 + boost, fx);
} }
}; };

View File

@ -187,20 +187,23 @@ namespace sol {
struct verified_tag {} const verified{}; struct verified_tag {} const verified{};
template <typename T> template <typename T>
struct is_constructor : std::false_type {}; struct is_non_factory_constructor : std::false_type {};
template <typename... Args>
struct is_non_factory_constructor<constructors<Args...>> : std::true_type {};
template <typename... Args> template <typename... Args>
struct is_constructor<constructors<Args...>> : std::true_type {}; struct is_non_factory_constructor<constructor_wrapper<Args...>> : std::true_type {};
template <typename... Args> template <>
struct is_constructor<constructor_wrapper<Args...>> : std::true_type {}; struct is_non_factory_constructor<no_construction> : std::true_type {};
template <typename T>
struct is_constructor : is_non_factory_constructor<T> {};
template <typename... Args> template <typename... Args>
struct is_constructor<factory_wrapper<Args...>> : std::true_type {}; struct is_constructor<factory_wrapper<Args...>> : std::true_type {};
template <>
struct is_constructor<no_construction> : std::true_type {};
template <typename... Args> template <typename... Args>
using has_constructor = meta::any<is_constructor<meta::unqualified_t<Args>>...>; using has_constructor = meta::any<is_constructor<meta::unqualified_t<Args>>...>;
@ -425,8 +428,14 @@ namespace sol {
template <std::size_t Idx, bool is_index = true, bool is_variable = false> template <std::size_t Idx, bool is_index = true, bool is_variable = false>
static int real_call_with(lua_State* L, usertype_metatable& um) { static int real_call_with(lua_State* L, usertype_metatable& um) {
typedef meta::unqualified_tuple_element_t<Idx - 1, Tuple> K;
typedef meta::unqualified_tuple_element_t<Idx, Tuple> F;
static const int boost =
!usertype_detail::is_non_factory_constructor<F>::value
&& std::is_same<K, call_construction>::value ?
1 : 0;
auto& f = std::get<Idx>(um.functions); auto& f = std::get<Idx>(um.functions);
return call_detail::call_wrapped<T, is_index, is_variable>(L, f); return call_detail::call_wrapped<T, is_index, is_variable, boost>(L, f);
} }
template <std::size_t Idx, bool is_index = true, bool is_variable = false> template <std::size_t Idx, bool is_index = true, bool is_variable = false>

View File

@ -235,6 +235,28 @@ void des(T& e) {
e.~T(); e.~T();
} }
struct matrix_xf {
float a, b;
static matrix_xf from_lua_table(sol::table t) {
matrix_xf m;
m.a = t[1][1];
m.b = t[1][2];
return m;
}
};
struct matrix_xi {
int a, b;
static matrix_xi from_lua_table(sol::table t) {
matrix_xi m;
m.a = t[1][1];
m.b = t[1][2];
return m;
}
};
TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") { TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") {
sol::state lua; sol::state lua;
@ -944,6 +966,30 @@ t = thing(256)
REQUIRE(y.v == 256); REQUIRE(y.v == 256);
} }
TEST_CASE("usertype/call_constructor-factories", "make sure tables can be passed to factory-based call constructors") {
sol::state lua;
lua.open_libraries();
lua.new_usertype<matrix_xf>("mat",
sol::call_constructor, sol::factories(&matrix_xf::from_lua_table)
);
lua.script("m = mat{ {1.1, 2.2} }");
lua.new_usertype<matrix_xi>("mati",
sol::call_constructor, sol::factories(&matrix_xi::from_lua_table)
);
lua.script("mi = mati{ {1, 2} }");
matrix_xf& m = lua["m"];
REQUIRE(m.a == 1.1f);
REQUIRE(m.b == 2.2f);
matrix_xi& mi = lua["mi"];
REQUIRE(mi.a == 1);
REQUIRE(mi.b == 2);
}
TEST_CASE("usertype/call_constructor_2", "prevent metatable regression") { TEST_CASE("usertype/call_constructor_2", "prevent metatable regression") {
class class01 { class class01 {
public: public: