mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
update all the examples
fix implicitly convertible function pointers from classes using `call_detail`'s `lua_call_wrapper` specificaly add documentation for working with `std::function`
This commit is contained in:
parent
a163ae7b33
commit
92a6fb8c11
@ -16,6 +16,9 @@ The examples folder also has a number of really great examples for you to see. T
|
||||
* `Certain operators`_ are detected and bound automatically for usertypes
|
||||
* You can use bitfields but it requires some finesse on your part. We have an example to help you get started `here, that uses a few tricks`_.
|
||||
* All usertypes are runtime extensible in both `Lua`_ and `C++`_
|
||||
- If you need dynamic callbacks or runtime overridable functions, have a ``std::function`` member variable and get/set it on the usertype object
|
||||
- ``std::function`` works as a member variable or in passing as an argument / returning as a value (you can even use it with ``sol::property``)
|
||||
- You can also create an entirely dynamic object: see the `dynamic_object example`_ for more details
|
||||
* You can use :doc:`filters<api/filters>` to control dependencies and streamline return values, as well as apply custom behavior to a functions return
|
||||
* Please note that the colon is necessary to "automatically" pass the ``this``/``self`` argument to Lua methods
|
||||
- ``obj:method_name()`` is how you call "member" methods in Lua
|
||||
@ -33,12 +36,14 @@ The examples folder also has a number of really great examples for you to see. T
|
||||
- Retrieve a plain ``T`` to get a copy
|
||||
- Return types and passing arguments to ``sol::function``-types use perfect forwarding and reference semantics, which means no copies happen unless you specify a value explicitly. See :ref:`this note for details<function-argument-handling>`.
|
||||
* You can set ``index`` and ``new_index`` freely on any usertype you like to override the default "if a key is missing, find it / set it here" functionality of a specific object of a usertype.
|
||||
- new_index and index will not be called if you try to manipulate the named usertype table directly. sol2's will be called to add that function to the usertype's function/variable lookup table.
|
||||
- new_index and index will be called if you attempt to call a key that does not exist on an actual userdata object (the C++ object) itself.
|
||||
- If you made a usertype named ``test``, this means ``t = test()``, with ``t.hi = 54`` will call your function, but ``test.hi = function () print ("hi");`` will instead the key ``hi`` to to that function for all ``test`` types
|
||||
- ``new_index`` and ``index`` will not be called if you try to manipulate the named usertype table directly. sol2's will be called to add that function to the usertype's function/variable lookup table.
|
||||
- ``new_index`` and ``index`` will be called if you attempt to call a key that does not exist on an actual userdata object (the C++ object) itself.
|
||||
- If you made a usertype named ``test``, this means ``t = test()``, with ``t.hi = 54`` will call your function, but ``test.hi = function () print ("hi"); end`` will instead set the key ``hi`` to to lookup that function for all ``test`` types
|
||||
* The first ``sizeof( void* )`` bytes is always a pointer to the typed C++ memory. What comes after is based on what you've pushed into the system according to :doc:`the memory specification for usertypes<api/usertype_memory>`. This is compatible with a number of systems other than just sol2, making it easy to interop with select other Lua systems.
|
||||
* Member methods, properties, variables and functions taking ``self&`` arguments modify data directly
|
||||
- Work on a copy by taking arguments or returning by value. Do not use r-value references: they do not mean anything in Lua code.
|
||||
- Work on a copy by taking arguments or returning by value.
|
||||
- Do not use r-value references: they do not mean anything in Lua code.
|
||||
- Move-only types can only be taken by reference: sol2 cannot know if/when to move a value (except when serializing with perfect forwarding *into* Lua)
|
||||
* The actual metatable associated with the usertype has a long name and is defined to be opaque by the Sol implementation.
|
||||
* The actual metatable inner workings is opaque and defined by the Sol implementation, and there are no internal docs because optimizations on the operations are applied based on heuristics we discover from performance testing the system.
|
||||
|
||||
@ -46,3 +51,4 @@ The examples folder also has a number of really great examples for you to see. T
|
||||
.. _Lua: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_advanced.cpp#L81
|
||||
.. _C++: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_simple.cpp#L51
|
||||
.. _Certain operators: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_automatic_operators.cpp
|
||||
.. _dynamic_object example: https://github.com/ThePhD/sol2/blob/develop/examples/dynamic_object.cpp
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <string>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
@ -1,5 +1,5 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#include "sol.hpp"
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <tuple>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <string>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
94
examples/pairs.cpp
Normal file
94
examples/pairs.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
struct my_thing {
|
||||
std::map<std::string, int> m{
|
||||
{ "bark", 20 },
|
||||
{ "woof", 60 },
|
||||
{ "borf", 30 },
|
||||
{ "awoo", 5 },
|
||||
};
|
||||
|
||||
my_thing() {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
struct lua_iterator_state {
|
||||
typedef std::map<std::string, int>::iterator it_t;
|
||||
it_t it;
|
||||
it_t last;
|
||||
std::reference_wrapper<my_thing> source;
|
||||
|
||||
lua_iterator_state(my_thing& mt) : it(mt.m.begin()), last(mt.m.end()), source(mt) {}
|
||||
};
|
||||
|
||||
std::tuple<sol::object, sol::object> my_next(sol::user<lua_iterator_state&> user_it_state, sol::this_state l) {
|
||||
// this gets called
|
||||
// to start the first iteration, and every
|
||||
// iteration there after
|
||||
|
||||
// the state you passed in my_pairs is argument 1
|
||||
// the key value is argument 2, but we do not
|
||||
// care about the key value here
|
||||
lua_iterator_state& it_state = user_it_state;
|
||||
my_thing& source = it_state.source;
|
||||
auto& it = it_state.it;
|
||||
if (it == it_state.last) {
|
||||
// return nil to signify that
|
||||
// there's nothing more to work with.
|
||||
return std::make_tuple(
|
||||
sol::object(sol::lua_nil),
|
||||
sol::object(sol::lua_nil)
|
||||
);
|
||||
}
|
||||
auto itderef = *it;
|
||||
// 2 values are returned (pushed onto the stack):
|
||||
// the key and the value
|
||||
// the state is left alone
|
||||
auto r = std::make_tuple(sol::object(l, sol::in_place, it->first), sol::object(l, sol::in_place, it->second));
|
||||
// the iterator must be moved forward one before we return
|
||||
std::advance(it, 1);
|
||||
return r;
|
||||
};
|
||||
|
||||
auto my_pairs(my_thing& mt) {
|
||||
// pairs expects 3 returns:
|
||||
// the "next" function on how to advance,
|
||||
// the "table" itself or some state,
|
||||
// and an initial key value (can be nil)
|
||||
|
||||
// prepare our state
|
||||
lua_iterator_state it_state(mt);
|
||||
// sol::user is a space/time optimization over regular usertypes,
|
||||
// it's incompatible with regular usertypes and stores the type T directly in lua without any pretty setup
|
||||
// saves space allocation and a single dereference
|
||||
return std::make_tuple(&my_next, sol::user<lua_iterator_state>(std::move(it_state)), sol::lua_nil);
|
||||
};
|
||||
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::cout << "===== pairs (advanced) =====" << std::endl;
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
lua.new_usertype<my_thing>("my_thing",
|
||||
sol::meta_function::pairs, my_pairs
|
||||
);
|
||||
|
||||
lua.safe_script(R"(
|
||||
local mt = my_thing.new()
|
||||
for k, v in pairs(mt) do
|
||||
print(k, v)
|
||||
end
|
||||
)");
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
96
examples/pairs_with_raw_functions.cpp
Normal file
96
examples/pairs_with_raw_functions.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
struct my_thing {
|
||||
std::map<std::string, int> m{
|
||||
{ "bark", 20 },
|
||||
{ "woof", 60 },
|
||||
{ "borf", 30 },
|
||||
{ "awoo", 5 },
|
||||
};
|
||||
|
||||
my_thing() {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
struct lua_iterator_state {
|
||||
typedef std::map<std::string, int>::iterator it_t;
|
||||
it_t it;
|
||||
it_t last;
|
||||
std::reference_wrapper<my_thing> source;
|
||||
|
||||
lua_iterator_state(my_thing& mt) : it(mt.m.begin()), last(mt.m.end()), source(mt) {}
|
||||
};
|
||||
|
||||
int my_next(lua_State* L) {
|
||||
// this gets called
|
||||
// to start the first iteration, and every
|
||||
// iteration there after
|
||||
// the state you passed in pairs is argument 1
|
||||
// the key value is argument 2
|
||||
// we do not care about the key value here
|
||||
lua_iterator_state& it_state = sol::stack::get<sol::user<lua_iterator_state>>(L, 1);
|
||||
my_thing& source = it_state.source;
|
||||
auto& it = it_state.it;
|
||||
if (it == it_state.last) {
|
||||
return sol::stack::push(L, sol::lua_nil);
|
||||
}
|
||||
auto itderef = *it;
|
||||
// 2 values are returned (pushed onto the stack):
|
||||
// the key and the value
|
||||
// the state is left alone
|
||||
int pushed = sol::stack::push(L, itderef.first);
|
||||
pushed += sol::stack::push_reference(L, itderef.second);
|
||||
std::advance(it, 1);
|
||||
return pushed;
|
||||
};
|
||||
|
||||
auto my_pairs(my_thing& mt) {
|
||||
// prepare our state
|
||||
lua_iterator_state it_state(mt);
|
||||
return std::make_tuple(&my_next, sol::user<lua_iterator_state>(std::move(it_state)), sol::lua_nil);
|
||||
// sol::user above is a space/time optimization over regular usertypes,
|
||||
// it's incompatible with regular usertypes and stores the type T directly in lua without any pretty setup
|
||||
// saves space allocation and a single dereference
|
||||
};
|
||||
|
||||
int my_pairs(lua_State* L) {
|
||||
my_thing& mt = sol::stack::get<my_thing>(L, 1);
|
||||
lua_iterator_state it_state(mt);
|
||||
// pairs expects 3 returns:
|
||||
// the "next" function on how to advance,
|
||||
// the "table" itself or some state,
|
||||
// and an initial key value (can be nil)
|
||||
|
||||
// next function controls iteration
|
||||
int pushed = sol::stack::push(L, my_next);
|
||||
pushed += sol::stack::push<sol::user<lua_iterator_state>>(L, std::move(it_state));
|
||||
pushed += sol::stack::push(L, sol::lua_nil);
|
||||
return pushed;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::cout << "===== pairs (using raw Lua C functions) (advanced) =====" << std::endl;
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
lua.new_usertype<my_thing>("my_thing",
|
||||
sol::meta_function::pairs, my_pairs
|
||||
);
|
||||
|
||||
lua.safe_script(R"(
|
||||
local mt = my_thing.new()
|
||||
for k, v in pairs(mt) do
|
||||
print(k, v)
|
||||
end
|
||||
)");
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
@ -1,6 +1,6 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main(int, char**) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <string>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#define SOL_CHECK_ARGUMENTS 1
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
@ -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-08-22 14:53:37.052568 UTC
|
||||
// This header was generated with sol v2.18.1 (revision 7164a8a)
|
||||
// Generated 2017-08-24 18:37:55.297938 UTC
|
||||
// This header was generated with sol v2.18.1 (revision a163ae7)
|
||||
// https://github.com/ThePhD/sol2
|
||||
|
||||
#ifndef SOL_SINGLE_INCLUDE_HPP
|
||||
@ -1088,16 +1088,34 @@ namespace sol {
|
||||
|
||||
namespace meta_detail {
|
||||
|
||||
template<typename T, bool isclass = std::is_class<unqualified_t<T>>::value>
|
||||
template<typename T, typename = void>
|
||||
struct is_callable : std::is_function<std::remove_pointer_t<T>> {};
|
||||
|
||||
template<typename T>
|
||||
struct is_callable<T, true> {
|
||||
struct is_callable<T, std::enable_if_t<std::is_class<unqualified_t<T>>::value && std::is_destructible<unqualified_t<T>>::value>> {
|
||||
using yes = char;
|
||||
using no = struct { char s[2]; };
|
||||
|
||||
struct F { void operator()(); };
|
||||
struct Derived : T, F { ~Derived() = default; };
|
||||
struct Derived : T, F { };
|
||||
template<typename U, U> struct Check;
|
||||
|
||||
template<typename V>
|
||||
static no test(Check<void (F::*)(), &V::operator()>*);
|
||||
|
||||
template<typename>
|
||||
static yes test(...);
|
||||
|
||||
static const bool value = sizeof(test<Derived>(0)) == sizeof(yes);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_callable<T, std::enable_if_t<std::is_class<unqualified_t<T>>::value && !std::is_destructible<unqualified_t<T>>::value>> {
|
||||
using yes = char;
|
||||
using no = struct { char s[2]; };
|
||||
|
||||
struct F { void operator()(); };
|
||||
struct Derived : T, F { ~Derived() = delete; };
|
||||
template<typename U, U> struct Check;
|
||||
|
||||
template<typename V>
|
||||
@ -3898,7 +3916,7 @@ namespace sol {
|
||||
|
||||
template <typename F, typename... Filters>
|
||||
struct filter_wrapper {
|
||||
typedef std::make_integer_sequence<std::size_t, sizeof...(Filters)> indices;
|
||||
typedef std::index_sequence_for<Filters...> indices;
|
||||
|
||||
F value;
|
||||
std::tuple<Filters...> filters;
|
||||
@ -4208,7 +4226,7 @@ namespace sol {
|
||||
U value;
|
||||
|
||||
user(U x) : value(std::move(x)) {}
|
||||
operator U* () { return std::addressof(value); }
|
||||
operator std::remove_reference_t<U>* () { return std::addressof(value); }
|
||||
operator U& () { return value; }
|
||||
operator const U& () const { return value; }
|
||||
};
|
||||
@ -7053,9 +7071,9 @@ namespace sol {
|
||||
|
||||
template<typename T>
|
||||
struct getter<user<T>> {
|
||||
static T& get(lua_State* L, int index, record& tracking) {
|
||||
static std::add_lvalue_reference_t<T> get(lua_State* L, int index, record& tracking) {
|
||||
tracking.use(1);
|
||||
return *static_cast<T*>(lua_touserdata(L, index));
|
||||
return *static_cast<std::remove_reference_t<T>*>(lua_touserdata(L, index));
|
||||
}
|
||||
};
|
||||
|
||||
@ -7726,7 +7744,14 @@ namespace sol {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pusher<T*, meta::disable_if_t<meta::all<is_container<meta::unqualified_t<T>>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> {
|
||||
struct pusher<T*, meta::disable_if_t<
|
||||
meta::any<
|
||||
is_container<meta::unqualified_t<T>>,
|
||||
std::is_function<meta::unqualified_t<T>>,
|
||||
std::is_base_of<reference, meta::unqualified_t<T>>,
|
||||
std::is_base_of<stack_reference, meta::unqualified_t<T>>
|
||||
>::value
|
||||
>> {
|
||||
template <typename... Args>
|
||||
static int push(lua_State* L, Args&&... args) {
|
||||
return pusher<detail::as_pointer_tag<T>>{}.push(L, std::forward<Args>(args)...);
|
||||
@ -9136,7 +9161,7 @@ namespace sol {
|
||||
|
||||
template <typename F, typename = void>
|
||||
struct wrapper {
|
||||
typedef lua_bind_traits<meta::unqualified_t<F>> traits_type;
|
||||
typedef lua_bind_traits<meta::unqualified_t<F>> traits_type;
|
||||
typedef typename traits_type::args_list args_list;
|
||||
typedef typename traits_type::args_list free_args_list;
|
||||
typedef typename traits_type::returns_list returns_list;
|
||||
@ -9779,14 +9804,30 @@ namespace sol {
|
||||
|
||||
template <typename F, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename = void>
|
||||
struct agnostic_lua_call_wrapper {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static int call(lua_State* L, Fx&& f, Args&&... args) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
static int convertible_call(std::true_type, lua_State* L, Fx&& f, Args&&... args) {
|
||||
typedef typename wrap::traits_type traits_type;
|
||||
typedef typename traits_type::function_pointer_type fp_t;
|
||||
fp_t fx = f;
|
||||
return agnostic_lua_call_wrapper<fp_t, is_index, is_variable, checked, boost, clean_stack>{}.call(L, fx, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static int convertible_call(std::false_type, lua_State* L, Fx&& f, Args&&... args) {
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
typedef typename wrap::free_args_list args_list;
|
||||
typedef typename wrap::caller caller;
|
||||
return stack::call_into_lua<checked, clean_stack>(returns_list(), args_list(), L, boost + 1, caller(), std::forward<Fx>(f), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static int call(lua_State* L, Fx&& f, Args&&... args) {
|
||||
typedef typename wrap::traits_type traits_type;
|
||||
typedef typename traits_type::function_pointer_type fp_t;
|
||||
return convertible_call(std::conditional_t<std::is_class<meta::unqualified_t<F>>::value, std::is_convertible<std::decay_t<Fx>, fp_t>, std::false_type>(), L, std::forward<Fx>(f), std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
|
||||
@ -11110,7 +11151,7 @@ namespace sol {
|
||||
|
||||
template<typename Signature>
|
||||
struct pusher<Signature, std::enable_if_t<meta::all<
|
||||
std::is_function<Signature>,
|
||||
std::is_function<std::remove_pointer_t<Signature>>,
|
||||
meta::neg<std::is_same<Signature, lua_CFunction>>,
|
||||
meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>
|
||||
#ifdef SOL_NOEXCEPT_FUNCTION_TYPE
|
||||
@ -13573,7 +13614,7 @@ namespace sol {
|
||||
auto& src = get_src(L);
|
||||
stack::push(L, next);
|
||||
stack::push<user<iter>>(L, src, deferred_traits::begin(L, src));
|
||||
stack::push(L, 1);
|
||||
stack::push(L, sol::lua_nil);
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
20
sol/call.hpp
20
sol/call.hpp
@ -230,14 +230,30 @@ namespace sol {
|
||||
|
||||
template <typename F, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename = void>
|
||||
struct agnostic_lua_call_wrapper {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static int call(lua_State* L, Fx&& f, Args&&... args) {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
static int convertible_call(std::true_type, lua_State* L, Fx&& f, Args&&... args) {
|
||||
typedef typename wrap::traits_type traits_type;
|
||||
typedef typename traits_type::function_pointer_type fp_t;
|
||||
fp_t fx = f;
|
||||
return agnostic_lua_call_wrapper<fp_t, is_index, is_variable, checked, boost, clean_stack>{}.call(L, fx, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static int convertible_call(std::false_type, lua_State* L, Fx&& f, Args&&... args) {
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
typedef typename wrap::free_args_list args_list;
|
||||
typedef typename wrap::caller caller;
|
||||
return stack::call_into_lua<checked, clean_stack>(returns_list(), args_list(), L, boost + 1, caller(), std::forward<Fx>(f), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Fx, typename... Args>
|
||||
static int call(lua_State* L, Fx&& f, Args&&... args) {
|
||||
typedef typename wrap::traits_type traits_type;
|
||||
typedef typename traits_type::function_pointer_type fp_t;
|
||||
return convertible_call(std::conditional_t<std::is_class<meta::unqualified_t<F>>::value, std::is_convertible<std::decay_t<Fx>, fp_t>, std::false_type>(), L, std::forward<Fx>(f), std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
|
||||
|
@ -960,7 +960,7 @@ namespace sol {
|
||||
auto& src = get_src(L);
|
||||
stack::push(L, next);
|
||||
stack::push<user<iter>>(L, src, deferred_traits::begin(L, src));
|
||||
stack::push(L, 1);
|
||||
stack::push(L, sol::lua_nil);
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ namespace sol {
|
||||
|
||||
template <typename F, typename... Filters>
|
||||
struct filter_wrapper {
|
||||
typedef std::make_integer_sequence<std::size_t, sizeof...(Filters)> indices;
|
||||
typedef std::index_sequence_for<Filters...> indices;
|
||||
|
||||
F value;
|
||||
std::tuple<Filters...> filters;
|
||||
|
@ -261,7 +261,7 @@ namespace sol {
|
||||
|
||||
template<typename Signature>
|
||||
struct pusher<Signature, std::enable_if_t<meta::all<
|
||||
std::is_function<Signature>,
|
||||
std::is_function<std::remove_pointer_t<Signature>>,
|
||||
meta::neg<std::is_same<Signature, lua_CFunction>>,
|
||||
meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>
|
||||
#ifdef SOL_NOEXCEPT_FUNCTION_TYPE
|
||||
|
@ -363,9 +363,9 @@ namespace sol {
|
||||
|
||||
template<typename T>
|
||||
struct getter<user<T>> {
|
||||
static T& get(lua_State* L, int index, record& tracking) {
|
||||
static std::add_lvalue_reference_t<T> get(lua_State* L, int index, record& tracking) {
|
||||
tracking.use(1);
|
||||
return *static_cast<T*>(lua_touserdata(L, index));
|
||||
return *static_cast<std::remove_reference_t<T>*>(lua_touserdata(L, index));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -137,7 +137,14 @@ namespace sol {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pusher<T*, meta::disable_if_t<meta::all<is_container<meta::unqualified_t<T>>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> {
|
||||
struct pusher<T*, meta::disable_if_t<
|
||||
meta::any<
|
||||
is_container<meta::unqualified_t<T>>,
|
||||
std::is_function<meta::unqualified_t<T>>,
|
||||
std::is_base_of<reference, meta::unqualified_t<T>>,
|
||||
std::is_base_of<stack_reference, meta::unqualified_t<T>>
|
||||
>::value
|
||||
>> {
|
||||
template <typename... Args>
|
||||
static int push(lua_State* L, Args&&... args) {
|
||||
return pusher<detail::as_pointer_tag<T>>{}.push(L, std::forward<Args>(args)...);
|
||||
|
@ -252,16 +252,34 @@ namespace sol {
|
||||
|
||||
namespace meta_detail {
|
||||
|
||||
template<typename T, bool isclass = std::is_class<unqualified_t<T>>::value>
|
||||
template<typename T, typename = void>
|
||||
struct is_callable : std::is_function<std::remove_pointer_t<T>> {};
|
||||
|
||||
template<typename T>
|
||||
struct is_callable<T, true> {
|
||||
struct is_callable<T, std::enable_if_t<std::is_class<unqualified_t<T>>::value && std::is_destructible<unqualified_t<T>>::value>> {
|
||||
using yes = char;
|
||||
using no = struct { char s[2]; };
|
||||
|
||||
struct F { void operator()(); };
|
||||
struct Derived : T, F { ~Derived() = default; };
|
||||
struct Derived : T, F { };
|
||||
template<typename U, U> struct Check;
|
||||
|
||||
template<typename V>
|
||||
static no test(Check<void (F::*)(), &V::operator()>*);
|
||||
|
||||
template<typename>
|
||||
static yes test(...);
|
||||
|
||||
static const bool value = sizeof(test<Derived>(0)) == sizeof(yes);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_callable<T, std::enable_if_t<std::is_class<unqualified_t<T>>::value && !std::is_destructible<unqualified_t<T>>::value>> {
|
||||
using yes = char;
|
||||
using no = struct { char s[2]; };
|
||||
|
||||
struct F { void operator()(); };
|
||||
struct Derived : T, F { ~Derived() = delete; };
|
||||
template<typename U, U> struct Check;
|
||||
|
||||
template<typename V>
|
||||
|
@ -325,7 +325,7 @@ namespace sol {
|
||||
U value;
|
||||
|
||||
user(U x) : value(std::move(x)) {}
|
||||
operator U* () { return std::addressof(value); }
|
||||
operator std::remove_reference_t<U>* () { return std::addressof(value); }
|
||||
operator U& () { return value; }
|
||||
operator const U& () const { return value; }
|
||||
};
|
||||
|
@ -28,7 +28,7 @@ namespace sol {
|
||||
|
||||
template <typename F, typename = void>
|
||||
struct wrapper {
|
||||
typedef lua_bind_traits<meta::unqualified_t<F>> traits_type;
|
||||
typedef lua_bind_traits<meta::unqualified_t<F>> traits_type;
|
||||
typedef typename traits_type::args_list args_list;
|
||||
typedef typename traits_type::args_list free_args_list;
|
||||
typedef typename traits_type::returns_list returns_list;
|
||||
|
Loading…
x
Reference in New Issue
Block a user