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}``
- 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
* ``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
- 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
+++++++++++++++++++++++++++

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script.
// Generated 2017-01-09 21:30:54.823287 UTC
// This header was generated with sol v2.15.7 (revision 969615f)
// Generated 2017-01-10 04:24:27.805667 UTC
// This header was generated with sol v2.15.7 (revision 490194f)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP
@ -8071,7 +8071,7 @@ namespace sol {
};
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{};
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>
struct is_constructor<constructors<Args...>> : std::true_type {};
struct is_non_factory_constructor<constructor_wrapper<Args...>> : std::true_type {};
template <typename... Args>
struct is_constructor<constructor_wrapper<Args...>> : std::true_type {};
template <>
struct is_non_factory_constructor<no_construction> : std::true_type {};
template <typename T>
struct is_constructor : is_non_factory_constructor<T> {};
template <typename... Args>
struct is_constructor<factory_wrapper<Args...>> : std::true_type {};
template <>
struct is_constructor<no_construction> : std::true_type {};
template <typename... 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>
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);
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>

View File

@ -501,7 +501,7 @@ namespace sol {
};
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{};
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>
struct is_constructor<constructors<Args...>> : std::true_type {};
struct is_non_factory_constructor<constructor_wrapper<Args...>> : std::true_type {};
template <typename... Args>
struct is_constructor<constructor_wrapper<Args...>> : std::true_type {};
template <>
struct is_non_factory_constructor<no_construction> : std::true_type {};
template <typename T>
struct is_constructor : is_non_factory_constructor<T> {};
template <typename... Args>
struct is_constructor<factory_wrapper<Args...>> : std::true_type {};
template <>
struct is_constructor<no_construction> : std::true_type {};
template <typename... 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>
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);
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>

View File

@ -235,6 +235,28 @@ void des(T& e) {
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") {
sol::state lua;
@ -944,6 +966,30 @@ t = thing(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") {
class class01 {
public: