Using call_constructor with a factories instance when creating a simple usertype results in no matching function call takes this number of arguments and the specified types when trying to use the call constructor from Lua. This seems to be the case regardless of any other factors I tested (number of arguments to the factory function, the existence/non-existence of a "new" function, SOL_CHECK_ARGUMENTS/SOL_SAFE_USERTYPE defs, etc).
Note: Using call_constructor with factories works fine with regular usertypes (although there's currently no tests for the call_constructor/factories combo in the sol test cases).
Test code:
#define CATCH_CONFIG_MAIN
#define SOL_CHECK_ARGUMENTS
#include <catch.hpp>
#include <sol.hpp>
TEST_CASE("simple_usertype call_constructor with factories")
{
struct FactoryTest {};
sol::state lua;
lua.open_libraries(sol::lib::base);
auto factories = sol::factories([]() { return FactoryTest(); });
lua.new_simple_usertype<FactoryTest>("FactoryTest",
sol::meta_function::construct, factories,
sol::call_constructor, factories
);
REQUIRE_NOTHROW(lua.script("a = FactoryTest.new()"));
REQUIRE_NOTHROW(lua.script("b = FactoryTest()"));
}
Results:
-------------------------------------------------------------------------------
simple_usertype call_constructor with factories
-------------------------------------------------------------------------------
main.cpp(6)
...............................................................................
main.cpp(21): FAILED:
REQUIRE_NOTHROW( lua.script("b = FactoryTest()") )
due to unexpected exception with message:
lua: error: [string "b = FactoryTest()"]:1: sol: no matching function call
takes this number of arguments and the specified types
Thanks for reporting. There are tests now for it and it's not fairly well-vetted. Try pulling from the latest or from:
Appreciate the quick fix. The simple test I posted above works, but I am having a weird issue with my real use case. Will investigate it a bit more and post a new test case for you.
Okay, this test is rather convoluted and strangely constructed, but hopefully it's useful in tracking down what's going on. Basically, a table of userdata, when passed to a factory constructor is detected as a table of structs (using sol::object::is) when going through new but not when going through the call_constructor. Seems like it's probably just a weird symptom of something only tangentially related, but who knows.
#define CATCH_CONFIG_MAIN
#define SOL_CHECK_ARGUMENTS
#include <catch.hpp>
#include <sol.hpp>
TEST_CASE("simple_usertype call_constructor with a factory that takes a table of userdata")
{
struct thing {};
struct FactoryTest {};
sol::state lua;
lua.open_libraries(sol::lib::base);
auto factories = sol::factories(
[](const sol::table& tbl) {
for (auto v : tbl)
{
REQUIRE(v.second.valid());
// This fails only when the call_constructor is used:
REQUIRE(v.second.is<thing>());
}
return FactoryTest();
}
);
lua.new_simple_usertype<FactoryTest>("FactoryTest",
sol::meta_function::construct, factories,
sol::call_constructor, factories
);
lua.new_simple_usertype<thing>("thing");
lua.script("things = {thing.new(), thing.new()}");
// This succeeds:
SECTION("new")
{
REQUIRE_NOTHROW(lua.script("a = FactoryTest.new(things)"));
}
// This fails:
SECTION("call_constructor")
{
REQUIRE_NOTHROW(lua.script("b = FactoryTest(things)"));
}
}
The result (omitted the atpanic error that results from REQUIRE failing during the lua.script call):
-------------------------------------------------------------------------------
simple_usertype call_constructor with a factory that takes a table of userdata
call_constructor
-------------------------------------------------------------------------------
main.cpp(44)
...............................................................................
main.cpp(22): FAILED:
REQUIRE( v.second.is<thing>() )
with expansion:
false
This is now fixed, sorry about that: pull from the latest.