2016-06-04 09:40:23 +08:00
// The MIT License (MIT)
2016-06-20 07:02:40 +08:00
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
2016-06-04 09:40:23 +08:00
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# ifndef SOL_CALL_HPP
# define SOL_CALL_HPP
# include "wrapper.hpp"
# include "property.hpp"
# include "stack.hpp"
2016-06-20 07:02:40 +08:00
namespace sol {
namespace call_detail {
template < bool b , typename F >
inline decltype ( auto ) pick ( std : : integral_constant < bool , b > , F & & f ) {
return std : : forward < F > ( f ) ;
2016-06-07 03:46:53 +08:00
}
2016-06-20 07:02:40 +08:00
template < typename R , typename W >
inline auto & pick ( std : : true_type , property_wrapper < R , W > & f ) {
return f . read ;
}
template < typename R , typename W >
inline auto & pick ( std : : false_type , property_wrapper < R , W > & f ) {
return f . write ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
template < typename T , typename List >
struct void_call ;
template < typename T , typename . . . Args >
struct void_call < T , types < Args . . . > > {
static void call ( Args . . . ) { }
} ;
template < typename T , int additional_pop = 0 >
struct constructor_match {
T * obj ;
constructor_match ( T * obj ) : obj ( obj ) { }
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 {
detail : : default_construct func { } ;
return stack : : call_into_lua < additional_pop , false > ( r , a , L , start , func , obj ) ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
} ;
template < typename T >
inline int destruct ( lua_State * L ) {
T * obj = stack : : get < non_null < T * > > ( L , 1 ) ;
std : : allocator < T > alloc { } ;
alloc . destroy ( obj ) ;
return 0 ;
}
namespace overload_detail {
template < std : : size_t . . . M , typename Match , typename . . . Args >
inline int overload_match_arity ( sol : : types < > , std : : index_sequence < > , std : : index_sequence < M . . . > , Match & & , lua_State * L , int , int , Args & & . . . ) {
return luaL_error ( L , " sol: no matching function call takes this number of arguments and the specified types " ) ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
template < typename Fx , typename . . . Fxs , std : : size_t I , std : : size_t . . . In , std : : size_t . . . M , typename Match , typename . . . Args >
inline int overload_match_arity ( sol : : types < Fx , Fxs . . . > , std : : index_sequence < I , 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 ;
typedef typename args_list : : indices args_indices ;
// 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 < Fxs . . . > ( ) , std : : index_sequence < 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 < Fxs . . . > ( ) , std : : index_sequence < In . . . > ( ) , std : : index_sequence < traits : : arity , M . . . > ( ) , std : : forward < Match > ( matchfx ) , L , fxarity , start , std : : forward < Args > ( args ) . . . ) ;
}
if ( ! stack : : stack_detail : : check_types < true > ( ) . check ( args_list ( ) , args_indices ( ) , L , start , no_panic ) ) {
return overload_match_arity ( types < Fxs . . . > ( ) , std : : index_sequence < 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 ) . . . ) ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
} // overload_detail
2016-06-07 03:46:53 +08:00
2016-06-20 07:02:40 +08:00
template < typename . . . Functions , typename Match , typename . . . 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 ) . . . ) ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
template < typename . . . Functions , typename Match , typename . . . Args >
inline int overload_match ( Match & & matchfx , lua_State * L , int start , Args & & . . . args ) {
int fxarity = lua_gettop ( L ) - ( start - 1 ) ;
return overload_match_arity < Functions . . . > ( std : : forward < Match > ( matchfx ) , L , fxarity , start , std : : forward < Args > ( args ) . . . ) ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
template < typename T , typename . . . TypeLists , typename Match , typename . . . Args >
inline int construct ( Match & & matchfx , lua_State * L , int fxarity , int start , Args & & . . . args ) {
// use same overload resolution matching as all other parts of the framework
return overload_match_arity < decltype ( void_call < T , TypeLists > : : call ) . . . > ( std : : forward < Match > ( matchfx ) , L , fxarity , start , std : : forward < Args > ( args ) . . . ) ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
template < typename T , typename . . . TypeLists >
inline int construct ( lua_State * L ) {
static const auto & meta = usertype_traits < T > : : metatable ;
int argcount = lua_gettop ( L ) ;
call_syntax syntax = argcount > 0 ? stack : : get_call_syntax ( L , meta , 1 ) : call_syntax : : dot ;
argcount - = static_cast < int > ( syntax ) ;
2016-06-08 08:32:10 +08:00
2016-06-20 07:02:40 +08:00
T * * pointerpointer = reinterpret_cast < T * * > ( lua_newuserdata ( L , sizeof ( T * ) + sizeof ( T ) ) ) ;
T * & referencepointer = * pointerpointer ;
T * obj = reinterpret_cast < T * > ( pointerpointer + 1 ) ;
referencepointer = obj ;
reference userdataref ( L , - 1 ) ;
userdataref . pop ( ) ;
construct < T , TypeLists . . . > ( constructor_match < T > ( obj ) , L , argcount , 1 + static_cast < int > ( syntax ) ) ;
userdataref . push ( ) ;
luaL_getmetatable ( L , & meta [ 0 ] ) ;
if ( type_of ( L , - 1 ) = = type : : nil ) {
lua_pop ( L , 1 ) ;
return luaL_error ( L , " sol: unable to get usertype metatable " ) ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
lua_setmetatable ( L , - 2 ) ;
return 1 ;
2016-06-08 08:32:10 +08:00
}
2016-06-20 07:02:40 +08:00
template < typename F , bool is_index , bool is_variable , typename = void >
struct agnostic_lua_call_wrapper {
static int var_call ( std : : true_type , lua_State * L , F & f ) {
typedef wrapper < meta : : unqualified_t < F > > wrap ;
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 < is_index ? 1 : 2 > ( returns_list ( ) , args_list ( ) , L , is_index ? 2 : 3 , caller ( ) , f ) ;
}
2016-06-08 08:32:10 +08:00
2016-06-20 07:02:40 +08:00
static int var_call ( std : : false_type , lua_State * L , F & f ) {
typedef wrapper < meta : : unqualified_t < F > > wrap ;
typedef typename wrap : : free_args_list args_list ;
typedef typename wrap : : returns_list returns_list ;
typedef typename wrap : : caller caller ;
return stack : : call_into_lua ( returns_list ( ) , args_list ( ) , L , 1 , caller ( ) , f ) ;
}
static int call ( lua_State * L , F & f ) {
return var_call ( std : : integral_constant < bool , is_variable > ( ) , L , f ) ;
}
} ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < typename F , bool is_index , bool is_variable >
struct agnostic_lua_call_wrapper < F , is_index , is_variable , std : : enable_if_t < std : : is_member_function_pointer < F > : : value > > {
static int call ( lua_State * L , F & f ) {
typedef wrapper < meta : : unqualified_t < F > > wrap ;
typedef typename wrap : : returns_list returns_list ;
typedef typename wrap : : args_list args_list ;
typedef typename wrap : : caller caller ;
typedef typename wrap : : object_type object_type ;
2016-06-04 09:40:23 +08:00
# ifdef SOL_SAFE_USERTYPE
2016-06-20 07:02:40 +08:00
object_type * o = stack : : get < object_type * > ( L , 1 ) ;
if ( o = = nullptr ) {
return luaL_error ( L , " sol: received null for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax) " ) ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
return stack : : call_into_lua < is_variable ? 2 : 1 > ( returns_list ( ) , args_list ( ) , L , is_variable ? 3 : 2 , caller ( ) , f , * o ) ;
2016-06-04 09:40:23 +08:00
# else
2016-06-20 07:02:40 +08:00
object_type & o = stack : : get < object_type & > ( L , 1 ) ;
return stack : : call_into_lua < is_variable ? 2 : 1 > ( returns_list ( ) , args_list ( ) , L , is_variable ? 3 : 2 , caller ( ) , f , o ) ;
2016-06-04 09:40:23 +08:00
# endif // Safety
2016-06-20 07:02:40 +08:00
}
} ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < bool is_index , bool is_variable , typename C >
struct agnostic_lua_call_wrapper < lua_r_CFunction , is_index , is_variable , C > {
static int call ( lua_State * L , lua_r_CFunction f ) {
return f ( L ) ;
}
} ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < bool is_index , bool is_variable , typename C >
struct agnostic_lua_call_wrapper < lua_CFunction , is_index , is_variable , C > {
static int call ( lua_State * L , lua_CFunction f ) {
return f ( L ) ;
}
} ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < bool is_index , bool is_variable , typename C >
struct agnostic_lua_call_wrapper < no_prop , is_index , is_variable , C > {
static int call ( lua_State * L , no_prop & ) {
return luaL_error ( L , is_index ? " sol: cannot read from a writeonly property " : " sol: cannot write to a readonly property " ) ;
}
} ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < typename F , bool is_variable >
struct agnostic_lua_call_wrapper < F , false , is_variable , std : : enable_if_t < std : : is_member_object_pointer < F > : : value > > {
typedef sol : : lua_bind_traits < F > traits_type ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
static int call_assign ( std : : true_type , lua_State * L , F & f ) {
typedef wrapper < meta : : unqualified_t < F > > wrap ;
typedef typename wrap : : args_list args_list ;
typedef typename wrap : : object_type object_type ;
typedef typename wrap : : caller caller ;
2016-06-04 09:40:23 +08:00
# ifdef SOL_SAFE_USERTYPE
2016-06-20 07:02:40 +08:00
object_type * o = stack : : get < object_type * > ( L , 1 ) ;
if ( o = = nullptr ) {
if ( is_variable ) {
return luaL_error ( L , " sol: received nil for 'self' argument (bad '.' access?) " ) ;
}
return luaL_error ( L , " sol: received nil for 'self' argument (pass 'self' as first argument) " ) ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
return stack : : call_into_lua < is_variable ? 2 : 1 > ( types < void > ( ) , args_list ( ) , L , is_variable ? 3 : 2 , caller ( ) , f , * o ) ;
2016-06-04 09:40:23 +08:00
# else
2016-06-20 07:02:40 +08:00
object_type & o = stack : : get < object_type & > ( L , 1 ) ;
return stack : : call_into_lua < is_variable ? 2 : 1 > ( types < void > ( ) , args_list ( ) , L , is_variable ? 3 : 2 , caller ( ) , f , o ) ;
2016-06-04 09:40:23 +08:00
# endif // Safety
2016-06-20 07:02:40 +08:00
}
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
static int call_assign ( std : : false_type , lua_State * L , F & ) {
return luaL_error ( L , " sol: cannot write to this variable: copy assignment/constructor not available " ) ;
}
2016-06-07 03:46:53 +08:00
2016-06-20 07:02:40 +08:00
static int call_const ( std : : false_type , lua_State * L , F & f ) {
typedef typename traits_type : : return_type R ;
return call_assign ( std : : is_assignable < std : : add_lvalue_reference_t < meta : : unqualified_t < R > > , R > ( ) , L , f ) ;
}
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
static int call_const ( std : : true_type , lua_State * L , F & ) {
return luaL_error ( L , " sol: cannot write to a readonly (const) variable " ) ;
}
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
static int call ( lua_State * L , F & f ) {
return call_const ( std : : is_const < typename traits_type : : return_type > ( ) , L , f ) ;
}
} ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < typename F , bool is_variable >
struct agnostic_lua_call_wrapper < F , true , is_variable , std : : enable_if_t < std : : is_member_object_pointer < F > : : value > > {
typedef sol : : lua_bind_traits < F > traits_type ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
static int call ( lua_State * L , F & f ) {
typedef wrapper < meta : : unqualified_t < F > > wrap ;
typedef typename wrap : : object_type object_type ;
typedef typename wrap : : returns_list returns_list ;
typedef typename wrap : : caller caller ;
# ifdef SOL_SAFE_USERTYPE
object_type * o = stack : : get < object_type * > ( L , 1 ) ;
if ( o = = nullptr ) {
if ( is_variable ) {
return luaL_error ( L , " sol: 'self' argument is nil (bad '.' access?) " ) ;
}
return luaL_error ( L , " sol: 'self' argument is nil (pass 'self' as first argument) " ) ;
}
return stack : : call_into_lua < is_variable ? 2 : 1 > ( returns_list ( ) , types < > ( ) , L , is_variable ? 3 : 2 , caller ( ) , f , * o ) ;
# else
object_type & o = stack : : get < object_type & > ( L , 1 ) ;
return stack : : call_into_lua < is_variable ? 2 : 1 > ( returns_list ( ) , types < > ( ) , L , is_variable ? 3 : 2 , caller ( ) , f , o ) ;
# endif // Safety
}
} ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < bool is_index , bool is_variable , typename C >
struct agnostic_lua_call_wrapper < no_construction , is_index , is_variable , C > {
static int call ( lua_State * L , no_construction & ) {
return luaL_error ( L , " sol: cannot call this constructor (tagged as non-constructible) " ) ;
2016-06-04 09:40:23 +08:00
}
2016-06-20 07:02:40 +08:00
} ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < typename . . . Args , bool is_index , bool is_variable , typename C >
struct agnostic_lua_call_wrapper < bases < Args . . . > , is_index , is_variable , C > {
static int call ( lua_State * , bases < Args . . . > & ) {
// Uh. How did you even call this, lul
return 0 ;
}
} ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < typename T , typename F , bool is_index , bool is_variable , typename = void >
struct lua_call_wrapper : agnostic_lua_call_wrapper < F , is_index , is_variable > { } ;
template < typename T , typename . . . Args , bool is_index , bool is_variable , typename C >
struct lua_call_wrapper < T , sol : : constructor_list < Args . . . > , is_index , is_variable , C > {
typedef sol : : constructor_list < Args . . . > F ;
static int call ( lua_State * L , F & ) {
2016-06-22 13:20:38 +08:00
const auto & metakey = usertype_traits < T > : : metatable ;
2016-06-20 07:02:40 +08:00
int argcount = lua_gettop ( L ) ;
call_syntax syntax = argcount > 0 ? stack : : get_call_syntax ( L , metakey , 1 ) : call_syntax : : dot ;
argcount - = static_cast < int > ( syntax ) ;
2016-06-07 03:46:53 +08:00
T * * pointerpointer = reinterpret_cast < T * * > ( lua_newuserdata ( L , sizeof ( T * ) + sizeof ( T ) ) ) ;
reference userdataref ( L , - 1 ) ;
T * & referencepointer = * pointerpointer ;
T * obj = reinterpret_cast < T * > ( pointerpointer + 1 ) ;
referencepointer = obj ;
2016-06-20 07:02:40 +08:00
construct < T , Args . . . > ( constructor_match < T , 1 > ( obj ) , L , argcount , 1 + static_cast < int > ( syntax ) ) ;
2016-06-07 03:46:53 +08:00
userdataref . push ( ) ;
2016-06-20 07:02:40 +08:00
luaL_getmetatable ( L , & metakey [ 0 ] ) ;
2016-06-11 09:14:43 +08:00
if ( type_of ( L , - 1 ) = = type : : nil ) {
2016-06-07 03:46:53 +08:00
lua_pop ( L , 1 ) ;
2016-06-20 07:02:40 +08:00
return luaL_error ( L , " sol: unable to get usertype metatable " ) ;
2016-06-07 03:46:53 +08:00
}
2016-06-20 07:02:40 +08:00
lua_setmetatable ( L , - 2 ) ;
2016-06-07 03:46:53 +08:00
return 1 ;
}
} ;
2016-06-20 07:02:40 +08:00
template < typename T , typename . . . Cxs , bool is_index , bool is_variable , typename C >
struct lua_call_wrapper < T , sol : : constructor_wrapper < Cxs . . . > , is_index , is_variable , C > {
typedef sol : : constructor_wrapper < Cxs . . . > F ;
struct onmatch {
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 , F & f ) {
2016-06-22 13:20:38 +08:00
const auto & metakey = usertype_traits < T > : : metatable ;
2016-06-20 07:02:40 +08:00
T * * pointerpointer = reinterpret_cast < T * * > ( lua_newuserdata ( L , sizeof ( T * ) + sizeof ( T ) ) ) ;
reference userdataref ( L , - 1 ) ;
T * & referencepointer = * pointerpointer ;
T * obj = reinterpret_cast < T * > ( pointerpointer + 1 ) ;
referencepointer = obj ;
auto & func = std : : get < I > ( f . set ) ;
stack : : call_into_lua < 1 , false > ( r , a , L , start , func , detail : : implicit_wrapper < T > ( obj ) ) ;
userdataref . push ( ) ;
2016-06-22 13:20:38 +08:00
luaL_getmetatable ( L , & metakey [ 0 ] ) ;
2016-06-20 07:02:40 +08:00
if ( type_of ( L , - 1 ) = = type : : nil ) {
lua_pop ( L , 1 ) ;
std : : string err = " sol: unable to get usertype metatable for " ;
err + = usertype_traits < T > : : name ;
return luaL_error ( L , err . c_str ( ) ) ;
}
lua_setmetatable ( L , - 2 ) ;
return 1 ;
}
} ;
static int call ( lua_State * L , F & f ) {
call_syntax syntax = stack : : get_call_syntax ( L , usertype_traits < T > : : metatable ) ;
int syntaxval = static_cast < int > ( syntax ) ;
int argcount = lua_gettop ( L ) - syntaxval ;
return construct < T , meta : : pop_front_type_t < meta : : function_args_t < Cxs > > . . . > ( onmatch ( ) , L , argcount , 1 + syntaxval , f ) ;
}
2016-06-07 03:46:53 +08:00
2016-06-20 07:02:40 +08:00
} ;
2016-06-07 03:46:53 +08:00
2016-06-20 07:02:40 +08:00
template < typename T , typename Fx , bool is_index , bool is_variable >
struct lua_call_wrapper < T , sol : : destructor_wrapper < Fx > , is_index , is_variable , std : : enable_if_t < std : : is_void < Fx > : : value > > {
typedef sol : : destructor_wrapper < Fx > F ;
2016-06-07 03:46:53 +08:00
2016-06-20 07:02:40 +08:00
static int call ( lua_State * L , F & ) {
return destruct < T > ( L ) ;
}
} ;
2016-06-07 03:46:53 +08:00
2016-06-20 07:02:40 +08:00
template < typename T , typename Fx , bool is_index , bool is_variable >
struct lua_call_wrapper < T , sol : : destructor_wrapper < Fx > , is_index , is_variable , std : : enable_if_t < ! std : : is_void < Fx > : : value > > {
typedef sol : : destructor_wrapper < Fx > F ;
2016-06-07 03:46:53 +08:00
2016-06-20 07:02:40 +08:00
static int call ( lua_State * L , F & f ) {
T * obj = stack : : get < non_null < T * > > ( L ) ;
f . fx ( detail : : implicit_wrapper < T > ( obj ) ) ;
return 0 ;
}
} ;
2016-06-07 03:46:53 +08:00
2016-06-20 07:02:40 +08:00
template < typename T , typename . . . Fs , bool is_index , bool is_variable , typename C >
struct lua_call_wrapper < T , overload_set < Fs . . . > , is_index , is_variable , C > {
typedef overload_set < Fs . . . > F ;
2016-06-08 08:32:10 +08:00
2016-06-20 07:02:40 +08:00
struct on_match {
template < typename Fx , std : : size_t I , typename . . . R , typename . . . Args >
int operator ( ) ( types < Fx > , index_value < I > , types < R . . . > , types < Args . . . > , lua_State * L , int , int , F & fx ) {
auto & f = std : : get < I > ( fx . set ) ;
return lua_call_wrapper < T , Fx , is_index , is_variable > { } . call ( L , f ) ;
}
} ;
static int call ( lua_State * L , F & fx ) {
return overload_match_arity < Fs . . . > ( on_match ( ) , L , lua_gettop ( L ) , 1 , fx ) ;
2016-06-08 08:32:10 +08:00
}
} ;
2016-06-20 07:02:40 +08:00
template < typename T , bool is_index , bool is_variable , typename Fx >
int call_wrapped ( lua_State * L , Fx & & fx ) {
return lua_call_wrapper < T , meta : : unqualified_t < Fx > , is_index , is_variable > { } . call ( L , std : : forward < Fx > ( fx ) ) ;
2016-06-08 08:32:10 +08:00
}
2016-06-20 07:02:40 +08:00
template < typename T , typename = void >
struct is_var_bind : std : : false_type { } ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < typename T >
struct is_var_bind < T , std : : enable_if_t < std : : is_member_object_pointer < T > : : value > > : std : : true_type { } ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < >
struct is_var_bind < no_prop > : std : : true_type { } ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < typename R , typename W >
struct is_var_bind < property_wrapper < R , W > > : std : : true_type { } ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
} // call_detail
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < typename T >
struct is_variable_binding : call_detail : : is_var_bind < meta : : unqualified_t < T > > { } ;
2016-06-04 09:40:23 +08:00
2016-06-20 07:02:40 +08:00
template < typename T >
struct is_function_binding : meta : : neg < is_variable_binding < T > > { } ;
2016-06-04 09:40:23 +08:00
} // sol
# endif // SOL_CALL_HPP