Mmn. Always making lots and lots of small changes.

This commit is contained in:
ThePhD 2016-10-23 19:17:33 -04:00
parent 2ac711b7f8
commit 85329ca183
8 changed files with 190 additions and 47 deletions

View File

@ -61,7 +61,7 @@ author = 'ThePhD'
# The short X.Y version. # The short X.Y version.
version = '2.14' version = '2.14'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '2.14.10' release = '2.14.12'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

View File

@ -18,6 +18,11 @@ When you need to hit the ground running with Lua and C++, `Sol`_ is the go-to fr
:target: https://travis-ci.org/ThePhD/sol2 :target: https://travis-ci.org/ThePhD/sol2
:alt: build status :alt: build status
.. image:: https://badges.gitter.im/chat-sol2/Lobby.svg
target: https://gitter.im/chat-sol2/Lobby
:alt: chat about sol2 on gitter
get going: get going:
---------- ----------
@ -28,6 +33,7 @@ get going:
tutorial/all-the-things tutorial/all-the-things
tutorial/tutorial-top tutorial/tutorial-top
features features
usertypes
api/api-top api/api-top
mentions mentions
benchmarks benchmarks
@ -43,7 +49,7 @@ get going:
"I need feature X, maybe you have it?" "I need feature X, maybe you have it?"
-------------------------------------- --------------------------------------
Take a look at the :doc:`Features<features>` page: it links to much of the API. You can also just straight up browse the :doc:`api<api/api-top>` or ease in with the :doc:`tutorials<tutorial/tutorial-top>`. To know how function arguments are handled, see :ref:`this note<function-argument-handling>`. Don't see a feature you want? Send inquiries for support for a particular abstraction to the `issues`_ tracker. Take a look at the :doc:`Features<features>` page: it links to much of the API. You can also just straight up browse the :doc:`api<api/api-top>` or ease in with the :doc:`tutorials<tutorial/tutorial-top>`. To know more about the implementation for usertypes, see :doc:`here<usertypes>` To know how function arguments are handled, see :ref:`this note<function-argument-handling>`. Don't see a feature you want? Send inquiries for support for a particular abstraction to the `issues`_ tracker.
the basics: the basics:

View File

@ -108,6 +108,9 @@ A few things of note about the implementation: First, there's an auxiliary param
You can make something pushable into Lua, but not get-able in the same way if you only specialize one part of the system. If you need to retrieve it (as a return using one or multiple values from Lua), you should specialize the ``sol::stack::getter`` template class and the ``sol::stack::checker`` template class. If you need to push it into Lua at some point, then you'll want to specialize the ``sol::stack::pusher`` template class. The ``sol::lua_size`` template class trait needs to be specialized for both cases, unless it only pushes 1 item, in which case the default implementation will assume 1. You can make something pushable into Lua, but not get-able in the same way if you only specialize one part of the system. If you need to retrieve it (as a return using one or multiple values from Lua), you should specialize the ``sol::stack::getter`` template class and the ``sol::stack::checker`` template class. If you need to push it into Lua at some point, then you'll want to specialize the ``sol::stack::pusher`` template class. The ``sol::lua_size`` template class trait needs to be specialized for both cases, unless it only pushes 1 item, in which case the default implementation will assume 1.
.. note::
It is important to note here that the ``getter``, ``pusher`` and ``checker`` differentiate between a type ``T`` and a pointer to a type ``T*``. This means that if you want to work purely with, say, a ``T*`` handle that does not have the same semantics as just ``T``, you may need to specify checkers/getters/pushers for both ``T*`` and ``T``. The checkers for ``T*`` forward to the checkers for ``T``, but the getter for ``T*`` does not forward to the getter for ``T`` (e.g., because of ``int*`` not being quite the same as ``int``).
In general, this is fine since most getters/checkers only use 1 stack point. But, if you're doing more complex nested classes, it would be useful to use ``tracking.last`` to understand how many stack indices the last getter/checker operation did and increment it by ``index + tracking.last`` after using a ``stack::check<..>( L, index, tracking)`` call. In general, this is fine since most getters/checkers only use 1 stack point. But, if you're doing more complex nested classes, it would be useful to use ``tracking.last`` to understand how many stack indices the last getter/checker operation did and increment it by ``index + tracking.last`` after using a ``stack::check<..>( L, index, tracking)`` call.

25
docs/source/usertypes.rst Normal file
View File

@ -0,0 +1,25 @@
usertypes
=========
Perhaps the most powerful feature of sol2, ``usertypes`` are the way sol2 and C++ communicate your classes to the Lua runtime and bind things between both tables and to specific blocks of C++ memory, allowing you to treat Lua userdata and other things like classes.
To learn more about usertypes, visit:
* :doc:`tutorial<tutorial/cxx-in-lua>`
* :doc:`customization point tutorial<tutorial/customization>`
* :doc:`api documentation<api/usertype>`
* :doc:`memory documentation<api/usertype_memory>`
There are also some notes about guarantees you can find about usertypes, and their associated userdata, below:
* You can push types classified as userdata before you register a usertype.
- You can register a usertype with the Lua runtime at any time sol2
- You can retrieve them from the Lua runtime as well through sol2
- Methods and properties will be added to the type only after you register it in the Lua runtime
* Types either copy once or move once into the memory location, if it is a value type. If it is a pointer, we store only the reference.
- This means take arguments of class types (not primitive types like strings or integers) by ``T&`` or ``T*`` to modify the data in Lua directly, or by plain ``T`` to get a copy
- Return types and passing arguments to ``sol::function`` 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>`.
* 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.
* Member methods, properties, variables and functions taking ``self&`` arguments modify data directly
- Work on a copy by taking or returning a copy by value.
* The actual metatable associated with the usertype has a long name and is defined to be opaque by the Sol implementation.

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 2016-10-21 21:30:36.718233 UTC // Generated 2016-10-23 21:02:40.993304 UTC
// This header was generated with sol v2.14.11 (revision 8c3ae42) // This header was generated with sol v2.14.12 (revision 2ac711b)
// https://github.com/ThePhD/sol2 // https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP #ifndef SOL_SINGLE_INCLUDE_HPP
@ -5063,7 +5063,7 @@ namespace sol {
template<typename T, typename> template<typename T, typename>
struct getter { struct getter {
static T& get(lua_State* L, int index, record& tracking) { static T& get(lua_State* L, int index, record& tracking) {
return getter<T&>{}.get(L, index, tracking); return getter<sol::detail::as_value_tag<T>>{}.get(L, index, tracking);
} }
}; };
@ -5459,7 +5459,7 @@ namespace sol {
}; };
template<typename T> template<typename T>
struct getter<T*> { struct getter<detail::as_value_tag<T>> {
static T* get_no_nil(lua_State* L, int index, record& tracking) { static T* get_no_nil(lua_State* L, int index, record& tracking) {
tracking.use(1); tracking.use(1);
void** pudata = static_cast<void**>(lua_touserdata(L, index)); void** pudata = static_cast<void**>(lua_touserdata(L, index));
@ -5478,28 +5478,49 @@ namespace sol {
T* obj = static_cast<T*>(udata); T* obj = static_cast<T*>(udata);
return obj; return obj;
} }
static T& get(lua_State* L, int index, record& tracking) {
return *get_no_nil(L, index, tracking);
}
};
template<typename T>
struct getter<detail::as_pointer_tag<T>> {
static T* get(lua_State* L, int index, record& tracking) { static T* get(lua_State* L, int index, record& tracking) {
type t = type_of(L, index); type t = type_of(L, index);
if (t == type::nil) { if (t == type::nil) {
tracking.use(1); tracking.use(1);
return nullptr; return nullptr;
} }
return get_no_nil(L, index, tracking); return getter<detail::as_value_tag<T>>::get_no_nil(L, index, tracking);
} }
}; };
template<typename T> template<typename T>
struct getter<non_null<T*>> { struct getter<non_null<T*>> {
static T* get(lua_State* L, int index, record& tracking) { static T* get(lua_State* L, int index, record& tracking) {
return getter<T*>::get_no_nil(L, index, tracking); return getter<detail::as_value_tag<T>>::get_no_nil(L, index, tracking);
} }
}; };
template<typename T> template<typename T>
struct getter<T&> { struct getter<T&> {
static T& get(lua_State* L, int index, record& tracking) { static T& get(lua_State* L, int index, record& tracking) {
return *getter<T*>::get_no_nil(L, index, tracking); return getter<detail::as_value_tag<T>>::get(L, index, tracking);
}
};
template<typename T>
struct getter<std::reference_wrapper<T>> {
static T& get(lua_State* L, int index, record& tracking) {
return getter<T>{}.get(L, index, tracking);
}
};
template<typename T>
struct getter<T*> {
static T* get(lua_State* L, int index, record& tracking) {
return getter<detail::as_pointer_tag<T>>::get(L, index, tracking);
} }
}; };
@ -5517,13 +5538,6 @@ namespace sol {
} }
}; };
template<typename T>
struct getter<std::reference_wrapper<T>> {
static T& get(lua_State* L, int index, record& tracking) {
return getter<T&>{}.get(L, index, tracking);
}
};
template<typename... Args> template<typename... Args>
struct getter<std::tuple<Args...>> { struct getter<std::tuple<Args...>> {
typedef std::tuple<decltype(stack::get<Args>(nullptr, 0))...> R; typedef std::tuple<decltype(stack::get<Args>(nullptr, 0))...> R;
@ -7427,11 +7441,50 @@ namespace sol {
} }
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
} }
template <std::size_t... M, typename Match, typename... Args>
inline int overload_match_arity_single(types<>, std::index_sequence<>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
}
template <typename Fx, std::size_t I, std::size_t... M, typename Match, typename... Args>
inline int overload_match_arity_single(types<Fx>, std::index_sequence<I>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits;
typedef meta::tuple_types<typename traits::return_type> return_types;
typedef typename traits::free_args_list args_list;
// compile-time eliminate any functions that we know ahead of time are of improper arity
if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) {
return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
}
if (traits::free_arity != fxarity) {
return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
}
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
}
template <typename Fx, typename Fx1, typename... Fxs, std::size_t I, std::size_t I1, std::size_t... In, std::size_t... M, typename Match, typename... Args>
inline int overload_match_arity_single(types<Fx, Fx1, Fxs...>, std::index_sequence<I, I1, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits;
typedef meta::tuple_types<typename traits::return_type> return_types;
typedef typename traits::free_args_list args_list;
// compile-time eliminate any functions that we know ahead of time are of improper arity
if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) {
return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
}
if (traits::free_arity != fxarity) {
return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
}
stack::record tracking{};
if (!stack::stack_detail::check_types<true>{}.check(args_list(), L, start, no_panic, tracking)) {
return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
}
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
}
} // overload_detail } // overload_detail
template <typename... Functions, typename Match, typename... Args> template <typename... Functions, typename Match, typename... Args>
inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
return overload_detail::overload_match_arity(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); return overload_detail::overload_match_arity_single(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
} }
template <typename... Functions, typename Match, typename... Args> template <typename... Functions, typename Match, typename... Args>

View File

@ -57,7 +57,7 @@ namespace sol {
template <typename Fx, std::size_t I, typename... R, typename... Args> template <typename Fx, std::size_t I, typename... R, typename... Args>
int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) const { int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) const {
detail::default_construct func{}; detail::default_construct func{};
return stack::call_into_lua<false>(r, a, L, start, func, obj); return stack::call_into_lua<stack::stack_detail::default_check_arguments>(r, a, L, start, func, obj);
} }
}; };
@ -85,11 +85,50 @@ namespace sol {
} }
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
} }
template <std::size_t... M, typename Match, typename... Args>
inline int overload_match_arity_single(types<>, std::index_sequence<>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
}
template <typename Fx, std::size_t I, std::size_t... M, typename Match, typename... Args>
inline int overload_match_arity_single(types<Fx>, std::index_sequence<I>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits;
typedef meta::tuple_types<typename traits::return_type> return_types;
typedef typename traits::free_args_list args_list;
// compile-time eliminate any functions that we know ahead of time are of improper arity
if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) {
return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
}
if (traits::free_arity != fxarity) {
return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
}
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
}
template <typename Fx, typename Fx1, typename... Fxs, std::size_t I, std::size_t I1, std::size_t... In, std::size_t... M, typename Match, typename... Args>
inline int overload_match_arity_single(types<Fx, Fx1, Fxs...>, std::index_sequence<I, I1, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits;
typedef meta::tuple_types<typename traits::return_type> return_types;
typedef typename traits::free_args_list args_list;
// compile-time eliminate any functions that we know ahead of time are of improper arity
if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) {
return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
}
if (traits::free_arity != fxarity) {
return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
}
stack::record tracking{};
if (!stack::stack_detail::check_types<true>{}.check(args_list(), L, start, no_panic, tracking)) {
return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
}
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
}
} // overload_detail } // overload_detail
template <typename... Functions, typename Match, typename... Args> template <typename... Functions, typename Match, typename... Args>
inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
return overload_detail::overload_match_arity(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); return overload_detail::overload_match_arity_single(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
} }
template <typename... Functions, typename Match, typename... Args> template <typename... Functions, typename Match, typename... Args>

View File

@ -267,21 +267,7 @@ namespace sol {
}; };
template <typename T, typename C> template <typename T, typename C>
struct checker<T*, type::userdata, C> { struct checker<detail::as_value_tag<T>, type::userdata, C> {
template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
const type indextype = type_of(L, index);
// Allow nil to be transformed to nullptr
if (indextype == type::nil) {
tracking.use(1);
return true;
}
return checker<meta::unqualified_t<T>, type::userdata, C>{}.check(types<meta::unqualified_t<T>>(), L, indextype, index, std::forward<Handler>(handler), tracking);
}
};
template <typename T, typename C>
struct checker<T, type::userdata, C> {
template <typename U, typename Handler> template <typename U, typename Handler>
static bool check(types<U>, lua_State* L, type indextype, int index, Handler&& handler, record& tracking) { static bool check(types<U>, lua_State* L, type indextype, int index, Handler&& handler, record& tracking) {
tracking.use(1); tracking.use(1);
@ -320,11 +306,28 @@ namespace sol {
lua_pop(L, 1); lua_pop(L, 1);
return true; return true;
} }
};
template <typename T, typename C>
struct checker<T, type::userdata, C> {
template <typename Handler> template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
const type indextype = type_of(L, index); const type indextype = type_of(L, index);
return check(types<T>(), L, indextype, index, std::forward<Handler>(handler), tracking); return checker<detail::as_value_tag<T>, type::userdata, C>{}.check(types<T>(), L, indextype, index, std::forward<Handler>(handler), tracking);
}
};
template <typename T, typename C>
struct checker<T*, type::userdata, C> {
template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
const type indextype = type_of(L, index);
// Allow nil to be transformed to nullptr
if (indextype == type::nil) {
tracking.use(1);
return true;
}
return checker<meta::unqualified_t<T>, type::userdata, C>{}.check(L, index, std::forward<Handler>(handler), tracking);
} }
}; };

View File

@ -41,7 +41,7 @@ namespace sol {
template<typename T, typename> template<typename T, typename>
struct getter { struct getter {
static T& get(lua_State* L, int index, record& tracking) { static T& get(lua_State* L, int index, record& tracking) {
return getter<T&>{}.get(L, index, tracking); return getter<sol::detail::as_value_tag<T>>{}.get(L, index, tracking);
} }
}; };
@ -437,7 +437,7 @@ namespace sol {
}; };
template<typename T> template<typename T>
struct getter<T*> { struct getter<detail::as_value_tag<T>> {
static T* get_no_nil(lua_State* L, int index, record& tracking) { static T* get_no_nil(lua_State* L, int index, record& tracking) {
tracking.use(1); tracking.use(1);
void** pudata = static_cast<void**>(lua_touserdata(L, index)); void** pudata = static_cast<void**>(lua_touserdata(L, index));
@ -456,28 +456,49 @@ namespace sol {
T* obj = static_cast<T*>(udata); T* obj = static_cast<T*>(udata);
return obj; return obj;
} }
static T& get(lua_State* L, int index, record& tracking) {
return *get_no_nil(L, index, tracking);
}
};
template<typename T>
struct getter<detail::as_pointer_tag<T>> {
static T* get(lua_State* L, int index, record& tracking) { static T* get(lua_State* L, int index, record& tracking) {
type t = type_of(L, index); type t = type_of(L, index);
if (t == type::nil) { if (t == type::nil) {
tracking.use(1); tracking.use(1);
return nullptr; return nullptr;
} }
return get_no_nil(L, index, tracking); return getter<detail::as_value_tag<T>>::get_no_nil(L, index, tracking);
} }
}; };
template<typename T> template<typename T>
struct getter<non_null<T*>> { struct getter<non_null<T*>> {
static T* get(lua_State* L, int index, record& tracking) { static T* get(lua_State* L, int index, record& tracking) {
return getter<T*>::get_no_nil(L, index, tracking); return getter<detail::as_value_tag<T>>::get_no_nil(L, index, tracking);
} }
}; };
template<typename T> template<typename T>
struct getter<T&> { struct getter<T&> {
static T& get(lua_State* L, int index, record& tracking) { static T& get(lua_State* L, int index, record& tracking) {
return *getter<T*>::get_no_nil(L, index, tracking); return getter<detail::as_value_tag<T>>::get(L, index, tracking);
}
};
template<typename T>
struct getter<std::reference_wrapper<T>> {
static T& get(lua_State* L, int index, record& tracking) {
return getter<T&>{}.get(L, index, tracking);
}
};
template<typename T>
struct getter<T*> {
static T* get(lua_State* L, int index, record& tracking) {
return getter<detail::as_pointer_tag<T>>::get(L, index, tracking);
} }
}; };
@ -495,13 +516,6 @@ namespace sol {
} }
}; };
template<typename T>
struct getter<std::reference_wrapper<T>> {
static T& get(lua_State* L, int index, record& tracking) {
return getter<T&>{}.get(L, index, tracking);
}
};
template<typename... Args> template<typename... Args>
struct getter<std::tuple<Args...>> { struct getter<std::tuple<Args...>> {
typedef std::tuple<decltype(stack::get<Args>(nullptr, 0))...> R; typedef std::tuple<decltype(stack::get<Args>(nullptr, 0))...> R;