diff --git a/CMakeLists.txt b/CMakeLists.txt index 630b63dd..217d3ceb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,17 +95,6 @@ else() set(IS_X64 TRUE) endif() -# # # General project output locations -if (IS_X86 OR CMAKE_SIZEOF_VOID_P EQUAL 4) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x86/lib") - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x86/bin") - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x86/bin") -else() - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x64/lib") - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x64/bin") - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x64/bin") -endif() - # # # sol2 Source Groups # # Sources everyone is going to need @@ -202,6 +191,17 @@ endif() # # # Tests, Examples and other CI suites that come with sol2 if (DO_TESTS OR DO_EXAMPLES) + # # # General project output locations + if (IS_X86 OR CMAKE_SIZEOF_VOID_P EQUAL 4) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x86/lib") + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x86/bin") + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x86/bin") + else() + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x64/lib") + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x64/bin") + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x64/bin") + endif() + # # # Libraries # Here, we pull in all the necessary libraries for building examples and tests # Find threading library @@ -214,6 +214,9 @@ if (DO_TESTS OR DO_EXAMPLES) endif() set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE) + else() + string(REGEX REPLACE "/W[0-4]" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) + string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) endif() find_package(Threads REQUIRED) diff --git a/cmake/Modules/FindLuaBuild/LuaVanilla.cmake b/cmake/Modules/FindLuaBuild/LuaVanilla.cmake index f48f52f6..78e6aa34 100644 --- a/cmake/Modules/FindLuaBuild/LuaVanilla.cmake +++ b/cmake/Modules/FindLuaBuild/LuaVanilla.cmake @@ -165,7 +165,6 @@ endif() # # Potential compiler variables if (MSVC) - set(LUA_VANILLA_LUA_LUAC_COMPILER_OPTIONS "/W1") if (BUILD_LUA_AS_DLL) set(LUA_VANILLA_DLL_DEFINE LUA_BUILD_AS_DLL) else() @@ -378,8 +377,6 @@ else() target_compile_definitions(${luainterpreter} PRIVATE LUA_USE_LINUX) endif() -target_compile_options(${luainterpreter} - PRIVATE ${LUA_VANILLA_LUA_LUAC_COMPILER_OPTIONS}) target_link_libraries(${luainterpreter} PRIVATE ${liblua}) if (CMAKE_DL_LIBS) target_link_libraries(${luainterpreter} PRIVATE ${CMAKE_DL_LIBS}) @@ -403,8 +400,6 @@ set_target_properties(${luacompiler} OUTPUT_NAME luac-${LUA_VANILLA_VERSION}) target_include_directories(${luacompiler} PRIVATE "${LUA_VANILLA_INCLUDE_DIRS}") -target_compile_options(${luacompiler} - PRIVATE ${LUA_VANILLA_LUA_LUAC_COMPILER_OPTIONS}) target_compile_definitions(${luacompiler} PUBLIC LUA_COMPAT_ALL ${LUA_VANILLA_DLL_DEFINE} PRIVATE LUA_COMPAT_ALL ${LUA_VANILLA_DLL_DEFINE}) diff --git a/cmake/Modules/FindLuaJIT.cmake b/cmake/Modules/FindLuaJIT.cmake deleted file mode 100644 index 8ef3dbdc..00000000 --- a/cmake/Modules/FindLuaJIT.cmake +++ /dev/null @@ -1,173 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -#.rst: -# FindLuaJIT -# ------- -# -# -# -# Locate LuaJIT library. This module defines -# -# :: -# -# LUAJIT_FOUND - if false, do not try to link to LuaJIT -# LUAJIT_LIBRARIES - both lua and lualib -# LUAJIT_INCLUDE_DIR - where to find lua.h and luajit.h -# LUAJIT_VERSION_STRING - the version of LuaJIT found -# LUAJIT_VERSION_MAJOR - the major version of LuaJIT -# LUAJIT_VERSION_MINOR - the minor version of LuaJIT -# LUAJIT_VERSION_PATCH - the patch version of LuaJIT -# LUAJIT_LUA_VERSION_STRING - the version of Lua the found LuaJIT is compatible with -# -# -# -# Note that the expected include convention is -# -# :: -# -# #include "lua.h" -# -# and not -# -# :: -# -# #include -# -# This is because, the lua location is not standardized and may exist in -# locations other than lua/ - -unset(_luajit_include_subdirs) -unset(_luajit_append_versions) -unset(_luajit_library_names) - -include(${CMAKE_CURRENT_LIST_DIR}/FindLua/set_version_vars.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/FindLua/version_check.cmake) - -_lua_set_version_vars(luajit "jit") - -find_path(LUAJIT_INCLUDE_DIR luajit.h - HINTS - ENV LUAJIT_DIR - PATH_SUFFIXES ${_luajit_include_subdirs} include/luajit include - PATHS - ${LUAJIT_DIR} - ~/Library/Frameworks - /Library/Frameworks - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave - /opt - /usr - /usr/local # Homebrew -) - -if (LUAJIT_INCLUDE_DIR AND EXISTS "${LUAJIT_INCLUDE_DIR}/lua.h") - _lua_check_header_version("${LUAJIT_INCLUDE_DIR}/lua.h" "LUAJIT") -endif () - -if (NOT LUAJIT_VERSION_STRING) - foreach (subdir IN LISTS _luajit_include_subdirs) - unset(LUAJIT_INCLUDE_PREFIX CACHE) - find_path(LUAJIT_INCLUDE_PREFIX ${subdir}/lua.h - HINTS - ENV LUA_DIR - PATHS - ${LUA_DIR} - ~/Library/Frameworks - /Library/Frameworks - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave - /opt - /usr - /usr/local # Homebrew - ) - if (LUAJIT_INCLUDE_PREFIX) - _lua_check_header_version("${LUAJIT_INCLUDE_PREFIX}/${subdir}/lua.h" "LUAJIT") - if (LUAJIT_VERSION_STRING) - set(LUAJIT_INCLUDE_DIR "${LUAJIT_INCLUDE_PREFIX}/${subdir}") - break() - endif () - endif () - endforeach () -endif () -unset(_luajit_include_subdirs) -unset(_luajit_append_versions) - -if (LUAJIT_INCLUDE_DIR AND EXISTS "${LUAJIT_INCLUDE_DIR}/luajit.h") - # LuaJIT defines two preprocessor macros: - # LUA_VERSION -> version string with lua version in it - # LUA_VERSION_NUM -> numeric representation, i.e. 20003 for 2.0.3 - # This just parses the LUAJIT_VERSION macro and extracts the version. - file(STRINGS "${LUAJIT_INCLUDE_DIR}/luajit.h" version_strings - REGEX "^#define[ \t]+LUAJIT_VERSION?[ \t]+(\"LuaJIT [0-9\\.]+(-(beta|alpha)[0-9]*)?\").*") - - string(REGEX REPLACE ".*;#define[ \t]+LUAJIT_VERSION[ \t]+\"LuaJIT ([0-9\\.]+(-(beta|alpha)[0-9]*)?)\"[ \t]*;.*" "\\1" LUAJIT_VERSION_STRING_SHORT ";${version_strings};") - string(REGEX REPLACE ".*;([0-9]+\\.[0-9]+\\.[0-9]+(-(beta|alpha)[0-9]*)?);.*" "\\1" luajit_version_num ";${LUAJIT_VERSION_STRING_SHORT};") - - string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.(-(beta|alpha)[0-9]*)?$" "\\1" LUAJIT_VERSION_MAJOR "${luajit_version_num}") - string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9](-(beta|alpha)[0-9]*)?$" "\\1" LUAJIT_VERSION_MINOR "${luajit_version_num}") - string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+(-(beta|alpha)[0-9]*)?)$" "\\1" LUAJIT_VERSION_PATCH "${luajit_version_num}") - - # We can also set the LUAJIT_LUA_VERSION_* fields that are found by FindLua. - # We do this as LuaJIT claims full compatibility with a certain LUA version. - _lua_check_header_version("${LUAJIT_INCLUDE_DIR}/lua.h" "LUAJIT_LUA_") - - set(LUAJIT_VERSION_STRING "${LUAJIT_LUA_VERSION_STRING} (${LUAJIT_VERSION_STRING_SHORT})") -endif() - -find_library(LUAJIT_LIBRARY - NAMES ${_luajit_library_names} luajit lua - HINTS - ENV LUAJIT_DIR - PATH_SUFFIXES lib - PATHS - ${LUAJIT_DIR} - ~/Library/Frameworks - /Library/Frameworks - /sw - /opt/local - /opt/csw - /opt - /usr - /usr/local # Homebrew -) -unset(_luajit_library_names) - -if (LUAJIT_LIBRARY) - # include the math library for Unix - if (UNIX AND NOT APPLE AND NOT BEOS) - find_library(LUAJIT_MATH_LIBRARY m) - set(LUAJIT_LIBRARIES "${LUAJIT_LIBRARY};${LUAJIT_MATH_LIBRARY}") - # For Windows and Mac, don't need to explicitly include the math library - else () - set(LUAJIT_LIBRARIES "${LUAJIT_LIBRARY}") - endif () - - set(LUAJIT_LIBRARY_DIR ) - foreach (lib ${LUAJIT_LIBRARIES}) - get_filename_component(lib_dir ${lib} DIRECTORY CACHE) - list(APPEND LUAJIT_LIBRARY_DIR ${lib_dir}) - endforeach () - list(REMOVE_DUPLICATES LUAJIT_LIBRARY_DIR) -endif () - -if(APPLE) - # Not sure why this is true, but its mentioned here: - # http://luajit.org/install.html#embed - set(LUAJIT_LINK_FLAGS "-pagezero_size 10000 -image_base 100000000") -else() - set(LUAJIT_LINK_FLAGS "") -endif() - -include(FindPackageHandleStandardArgs) -# handle the QUIETLY and REQUIRED arguments and set LuaJIT_FOUND to TRUE if -# all listed variables are TRUE -FIND_PACKAGE_HANDLE_STANDARD_ARGS(LuaJIT - FOUND_VAR LuaJIT_FOUND - REQUIRED_VARS LUAJIT_LIBRARIES LUAJIT_INCLUDE_DIR LUAJIT_LIBRARY_DIR - VERSION_VAR LUAJIT_VERSION_STRING) - -mark_as_advanced(LUAJIT_INCLUDE_DIR LUAJIT_LIBRARY LUAJIT_LIBRARY_DIR LUAJIT_MATH_LIBRARY LUAJIT_LINK_FLAGS) - diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 11e33808..19c6a3b0 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -85,8 +85,9 @@ function (MAKE_EXAMPLE example_source_file example_suffix target_sol) else() target_compile_options(${example_name} PRIVATE -std=c++1z - -Wno-noexcept-type -Wno-unknown-warning -Wno-unknown-warning-option - -Wall -Wextra -Wpedantic -pedantic -pedantic-errors) + -Wall -Wpendatic -Werror -pedantic -pedantic-errors + -Wno-noexcept-type + -Wno-unknown-warning -Wno-unknown-warning-option) endif() target_link_libraries(${example_name} diff --git a/examples/interop/LuaBridge/CMakeLists.txt b/examples/interop/LuaBridge/CMakeLists.txt index e3582a16..f6c8187d 100644 --- a/examples/interop/LuaBridge/CMakeLists.txt +++ b/examples/interop/LuaBridge/CMakeLists.txt @@ -46,8 +46,7 @@ function (make_luabridge_interop_example target_library example_suffix) else() target_compile_options(${example_name} PRIVATE -std=c++1z -w - -Wno-noexcept-type -Wno-unknown-warning -Wno-unknown-warning-option - -Wall -Wextra -Wpedantic -pedantic -pedantic-errors) + -Wno-unknown-warning -Wno-unknown-warning-option) endif() if (CMAKE_DL_LIBS) diff --git a/examples/interop/kaguya/CMakeLists.txt b/examples/interop/kaguya/CMakeLists.txt index 6976b07e..27a98464 100644 --- a/examples/interop/kaguya/CMakeLists.txt +++ b/examples/interop/kaguya/CMakeLists.txt @@ -44,9 +44,8 @@ function (make_kaguya_interop_example target_library example_suffix) _CRT_SECURE_NO_WARNINGS _CRT_SECURE_NO_DEPRECATE) else() target_compile_options(${example_name} - PRIVATE -std=c++1z -w - -Wno-noexcept-type -Wno-unknown-warning -Wno-unknown-warning-option - -Wall -Wextra -Wpedantic -pedantic -pedantic-errors) + PRIVATE -std=c++1z -w + -Wno-unknown-warning -Wno-unknown-warning-option) endif() if (CMAKE_DL_LIBS) diff --git a/examples/interop/luwra/CMakeLists.txt b/examples/interop/luwra/CMakeLists.txt index e1c8ab8e..aea6c7d2 100644 --- a/examples/interop/luwra/CMakeLists.txt +++ b/examples/interop/luwra/CMakeLists.txt @@ -45,8 +45,7 @@ function (make_luwra_interop_example target_library example_suffix) else() target_compile_options(${example_name} PRIVATE -std=c++1z -w - -Wno-noexcept-type -Wno-unknown-warning -Wno-unknown-warning-option - -Wall -Wextra -Wpedantic -pedantic -pedantic-errors) + -Wno-unknown-warning -Wno-unknown-warning-option) endif() if (CMAKE_DL_LIBS) diff --git a/examples/interop/tolua/CMakeLists.txt b/examples/interop/tolua/CMakeLists.txt index fe3b1616..3c45eb5f 100644 --- a/examples/interop/tolua/CMakeLists.txt +++ b/examples/interop/tolua/CMakeLists.txt @@ -45,8 +45,7 @@ function(make_tolua_interop_example target_library example_suffix) else() target_compile_options(${example_name} PRIVATE -std=c++1z -w - -Wno-noexcept-type -Wno-unknown-warning -Wno-unknown-warning-option - -Wall -Wextra -Wpedantic -pedantic -pedantic-errors) + -Wno-unknown-warning -Wno-unknown-warning-option) endif() if (CMAKE_DL_LIBS) diff --git a/examples/require_dll_example/CMakeLists.txt b/examples/require_dll_example/CMakeLists.txt index da930f99..667e889a 100644 --- a/examples/require_dll_example/CMakeLists.txt +++ b/examples/require_dll_example/CMakeLists.txt @@ -62,8 +62,9 @@ function(make_require_from_dll_example target_lib example_lib_name_suffix) else() target_compile_options(${example_lib_name} PRIVATE -std=c++1z - -Wno-noexcept-type -Wno-unknown-warning -Wno-unknown-warning-option - -Wall -Wextra -Wpedantic -pedantic -pedantic-errors) + -Wall -Wextra -Wpedantic -pedantic -pedantic-errors + -Wno-noexcept-type + -Wno-unknown-warning -Wno-unknown-warning-option) if (IS_X86) target_compile_options(${example_lib_name} BEFORE PRIVATE -m32) endif() @@ -92,8 +93,9 @@ function(make_require_from_dll_example target_lib example_lib_name_suffix) else() target_compile_options(${example_name} PRIVATE -std=c++1z - -Wno-noexcept-type -Wno-unknown-warning -Wno-unknown-warning-option - -Wall -Wextra -Wpedantic -pedantic -pedantic-errors) + -Wall -Wextra -Wpedantic -pedantic -pedantic-errors + -Wno-noexcept-type + -Wno-unknown-warning -Wno-unknown-warning-option) endif() if(CMAKE_DL_LIBS) diff --git a/include/sol/bind_traits.hpp b/include/sol/bind_traits.hpp index 14095536..ff56b8a1 100644 --- a/include/sol/bind_traits.hpp +++ b/include/sol/bind_traits.hpp @@ -507,7 +507,7 @@ namespace meta { template struct callable_traits { - typedef std::conditional_t::value, std::add_lvalue_reference_t, R> return_type; + typedef std::conditional_t, std::add_lvalue_reference_t, R> return_type; typedef return_type Arg; typedef T object_type; using signature_type = R(T::*); diff --git a/include/sol/call.hpp b/include/sol/call.hpp index c31626ca..e572002f 100644 --- a/include/sol/call.hpp +++ b/include/sol/call.hpp @@ -24,10 +24,10 @@ #ifndef SOL_CALL_HPP #define SOL_CALL_HPP +#include "property.hpp" #include "protect.hpp" #include "wrapper.hpp" #include "trampoline.hpp" -#include "property.hpp" #include "filters.hpp" #include "stack.hpp" @@ -39,31 +39,34 @@ namespace sol { namespace filter_detail { template inline void handle_filter(static_stack_dependencies, lua_State* L, int&) { - if (sizeof...(In) == 0) { + if constexpr (sizeof...(In) == 0) { + (void)L; return; } - absolute_index ai(L, I); - if (type_of(L, ai) != type::userdata) { - return; - } - lua_createtable(L, static_cast(sizeof...(In)), 0); - stack_reference deps(L, -1); - auto per_dep = [&L, &deps](int i) { + else { + absolute_index ai(L, I); + if (type_of(L, ai) != type::userdata) { + return; + } + lua_createtable(L, static_cast(sizeof...(In)), 0); + stack_reference deps(L, -1); + auto per_dep = [&L, &deps](int i) { #if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK - luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); #endif // make sure stack doesn't overflow - lua_pushvalue(L, i); - luaL_ref(L, deps.stack_index()); - }; - (void)per_dep; - (void)detail::swallow { int(), (per_dep(In), int())... }; - lua_setuservalue(L, ai); + lua_pushvalue(L, i); + luaL_ref(L, deps.stack_index()); + }; + (void)per_dep; + (void)detail::swallow{ int(), (per_dep(In), int())... }; + lua_setuservalue(L, ai); + } } template inline void handle_filter(returns_self_with, lua_State* L, int& pushed) { pushed = stack::push(L, raw_index(1)); - handle_filter(static_stack_dependencies< -1, In...>(), L, pushed); + handle_filter(static_stack_dependencies<-1, In...>(), L, pushed); } inline void handle_filter(const stack_dependencies& sdeps, lua_State* L, int&) { @@ -99,12 +102,12 @@ namespace sol { template inline auto& pick(std::true_type, property_wrapper& f) { - return f.read; + return f.read(); } template inline auto& pick(std::false_type, property_wrapper& f) { - return f.write; + return f.write(); } template @@ -120,13 +123,12 @@ namespace sol { struct constructor_match { T* obj_; - constructor_match(T* o) - : obj_(o) { + constructor_match(T* o) : obj_(o) { } template int operator()(types, meta::index_value, types r, types a, lua_State* L, int, int start) const { - detail::default_construct func {}; + detail::default_construct func{}; return stack::call_into_lua(r, a, L, start, func, obj_); } }; @@ -138,67 +140,153 @@ namespace sol { } template - inline int overload_match_arity(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits> traits; - typedef meta::tuple_types 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 (!traits::runtime_variadics_t::value && meta::find_in_pack_v, meta::index_value...>::value) { - return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); - } - if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { - return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); - } - stack::record tracking {}; - if (!stack::stack_detail::check_types {}.check(args_list(), L, start, no_panic, tracking)) { - return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); - } - return matchfx(types(), meta::index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); - } - - template - inline int overload_match_arity_single(types<>, std::index_sequence<>, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); - } - - template - inline int overload_match_arity_single(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + inline int overload_match_arity(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, + int fxarity, int start, Args&&... args) { typedef lua_bind_traits> traits; typedef meta::tuple_types 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 constexpr (!traits::runtime_variadics_t::value && meta::find_in_pack_v, meta::index_value...>::value) { - return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + return overload_match_arity(types(), + std::index_sequence(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); } - if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { - return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + else { + if constexpr (!traits::runtime_variadics_t::value) { + if (traits::free_arity != fxarity) { + return overload_match_arity(types(), + std::index_sequence(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); + } + } + stack::record tracking{}; + stack::stack_detail::check_types ct{}; + if (!ct.check(args_list(), L, start, no_panic, tracking)) { + return overload_match_arity(types(), + std::index_sequence(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); + } + return matchfx(types(), meta::index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); } - return matchfx(types(), meta::index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); } - template - inline int overload_match_arity_single(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + template + inline int overload_match_arity_single( + types<>, std::index_sequence<>, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + return overload_match_arity(types<>(), + std::index_sequence<>(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); + } + + template + inline int overload_match_arity_single( + types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { typedef lua_bind_traits> traits; typedef meta::tuple_types 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 (!traits::runtime_variadics_t::value && meta::find_in_pack_v, meta::index_value...>::value) { - return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + if constexpr (!traits::runtime_variadics_t::value + && meta::find_in_pack_v, meta::index_value...>::value) { + return overload_match_arity(types<>(), + std::index_sequence<>(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); } if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { - return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); - } - stack::record tracking {}; - if (!stack::stack_detail::check_types {}.check(args_list(), L, start, no_panic, tracking)) { - return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + return overload_match_arity(types<>(), + std::index_sequence<>(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); } return matchfx(types(), meta::index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); } + + template + inline int overload_match_arity_single(types, std::index_sequence, std::index_sequence, Match&& matchfx, + lua_State* L, int fxarity, int start, Args&&... args) { + typedef lua_bind_traits> traits; + typedef meta::tuple_types 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 constexpr (!traits::runtime_variadics_t::value && meta::find_in_pack_v, meta::index_value...>::value) { + return overload_match_arity(types(), + std::index_sequence(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); + } + else { + if constexpr (!traits::runtime_variadics_t::value) { + if (traits::free_arity != fxarity) { + return overload_match_arity(types(), + std::index_sequence(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); + } + } + stack::record tracking{}; + stack::stack_detail::check_types ct{}; + if (!ct.check(args_list(), L, start, no_panic, tracking)) { + return overload_match_arity(types(), + std::index_sequence(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); + } + return matchfx(types(), meta::index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); + } + } } // namespace overload_detail template inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - return overload_detail::overload_match_arity_single(types(), std::make_index_sequence(), std::index_sequence<>(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + return overload_detail::overload_match_arity_single(types(), + std::make_index_sequence(), + std::index_sequence<>(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); } template @@ -210,7 +298,8 @@ namespace sol { template inline int construct_match(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::call)...>(std::forward(matchfx), L, fxarity, start, std::forward(args)...); + return overload_match_arity::call)...>( + std::forward(matchfx), L, fxarity, start, std::forward(args)...); } template @@ -230,7 +319,7 @@ namespace sol { stack::stack_detail::undefined_metatable umf(L, &meta[0]); umf(); - return 1; + return 1; } template @@ -240,88 +329,69 @@ namespace sol { template struct agnostic_lua_call_wrapper { - typedef wrapper> wrap; - - template - 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 {}.call(L, fx, std::forward(args)...); - } - - template - 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(returns_list(), args_list(), L, boost + 1, caller(), std::forward(f), std::forward(args)...); - } + using wrap = wrapper>; template 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>::value, std::is_convertible, fp_t>, std::false_type>(), L, std::forward(f), std::forward(args)...); - } - }; - - template - struct agnostic_lua_call_wrapper::value>> { - template - static int call(lua_State* L, Fx&& f, Args&&... args) { - if constexpr(is_index) { - return stack::push(L, std::forward(f), std::forward(args)...); + if constexpr(is_lua_reference_v>) { + if constexpr (is_index) { + return stack::push(L, std::forward(f), std::forward(args)...); + } + else { + std::forward(f) = stack::unqualified_get(L, boost + (is_variable ? 3 : 1)); + return 0; + } } else { - std::forward(f) = stack::unqualified_get(L, boost + (is_variable ? 3 : 1)); - return 0; + using traits_type = typename wrap::traits_type; + using fp_t = typename traits_type::function_pointer_type; + constexpr bool is_function_pointer_convertible + = std::is_class_v> && std::is_convertible_v, fp_t>; + if constexpr (is_function_pointer_convertible) { + fp_t fx = f; + return agnostic_lua_call_wrapper{}.call( + L, fx, std::forward(args)...); + } + else { + using returns_list = typename wrap::returns_list; + using args_list = typename wrap::free_args_list; + using caller = typename wrap::caller; + return stack::call_into_lua( + returns_list(), args_list(), L, boost + 1, caller(), std::forward(f), std::forward(args)...); + } } } }; - template - struct agnostic_lua_call_wrapper, true, is_variable, checked, boost, clean_stack, C> { + template + struct agnostic_lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack, C> { template static int call(lua_State* L, F&& f) { - typedef is_stack_based> is_stack; - if (clean_stack && !is_stack::value) { - lua_settop(L, 0); + if constexpr (is_index) { + constexpr bool is_stack = is_stack_based_v>; + if constexpr (clean_stack && !is_stack) { + lua_settop(L, 0); + } + return stack::push_reference(L, detail::unwrap(f.get_value())); } - return stack::push_reference(L, detail::unwrap(f.value)); - } - }; - - template - struct agnostic_lua_call_wrapper, false, is_variable, checked, boost, clean_stack, C> { - template - static int call_assign(std::true_type, lua_State* L, V&& f) { - detail::unwrap(f.value) = stack::unqualified_get>(L, boost + (is_variable ? 3 : 1)); - if (clean_stack) { - lua_settop(L, 0); + else { + if constexpr (std::is_const_v>) { + return luaL_error(L, "sol: cannot write to a readonly (const) variable"); + } + else { + using R = meta::unwrapped_t; + if constexpr (std::is_assignable_v>, R>) { + detail::unwrap(f.get_value()) = stack::unqualified_get>(L, boost + (is_variable ? 3 : 1)); + if (clean_stack) { + lua_settop(L, 0); + } + return 0; + } + else { + return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); + } + } } - return 0; - } - - template - static int call_assign(std::false_type, lua_State* L, Args&&...) { - return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); - } - - template - static int call_const(std::false_type, lua_State* L, Args&&... args) { - typedef meta::unwrapped_t R; - return call_assign(std::is_assignable>, R>(), L, std::forward(args)...); - } - - template - static int call_const(std::true_type, lua_State* L, Args&&...) { - return luaL_error(L, "sol: cannot write to a readonly (const) variable"); - } - - template - static int call(lua_State* L, V&& f) { - return call_const(std::is_const>(), L, f); } }; @@ -349,8 +419,8 @@ namespace sol { #endif // noexcept function types template - struct agnostic_lua_call_wrapper { - static int call(lua_State* L, const no_prop&) { + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, const detail::no_prop&) { return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property"); } }; @@ -373,119 +443,121 @@ namespace sol { template struct agnostic_lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack, C> { static int call(lua_State* L, std::reference_wrapper f) { - return agnostic_lua_call_wrapper {}.call(L, f.get()); + agnostic_lua_call_wrapper alcw{}; + return alcw.call(L, f.get()); } }; - template - struct lua_call_wrapper : agnostic_lua_call_wrapper {}; - - template - struct lua_call_wrapper::value>> { - typedef wrapper> wrap; - typedef typename wrap::object_type object_type; - - template - static int call(lua_State* L, Fx&& f, object_type& o) { - typedef typename wrap::returns_list returns_list; - typedef typename wrap::args_list args_list; - typedef typename wrap::caller caller; - return stack::call_into_lua(returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward(f), o); - } - - template - static int call(lua_State* L, Fx&& f) { - typedef std::conditional_t::value, object_type, T> Ta; + template + struct lua_call_wrapper { + template + static int call(lua_State* L, Fx&& fx, Args&&... args) { + if constexpr (std::is_member_function_pointer_v) { + using wrap = wrapper; + using object_type = typename wrap::object_type; + if constexpr (sizeof...(Args) < 1) { + using Ta = std::conditional_t, object_type, T>; #if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE - auto maybeo = stack::unqualified_check_get(L, 1); - if (!maybeo || maybeo.value() == nullptr) { - return luaL_error(L, "sol: received nil for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)"); - } - object_type* o = static_cast(maybeo.value()); - return call(L, std::forward(f), *o); + auto maybeo = stack::check_get(L, 1); + if (!maybeo || maybeo.value() == nullptr) { + return luaL_error(L, + "sol: received nil for 'self' argument (use ':' for accessing member functions, make sure member variables are " + "preceeded by the " + "actual object with '.' syntax)"); + } + object_type* o = static_cast(maybeo.value()); + return call(L, std::forward(fx), *o); #else - object_type& o = static_cast(*stack::unqualified_get>(L, 1)); - return call(L, std::forward(f), o); + object_type& o = static_cast(*stack::unqualified_get>(L, 1)); + return call(L, std::forward(fx), o); #endif // Safety - } - }; - - template - struct lua_call_wrapper::value>> { - typedef lua_bind_traits traits_type; - typedef wrapper> wrap; - typedef typename wrap::object_type object_type; - - template - static int call_assign(std::true_type, lua_State* L, V&& f, object_type& o) { - typedef typename wrap::args_list args_list; - typedef typename wrap::caller caller; - return stack::call_into_lua(types(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), f, o); - } - - template - static int call_assign(std::true_type, lua_State* L, V&& f) { - typedef std::conditional_t::value, object_type, T> Ta; -#if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE - auto maybeo = stack::check_get(L, 1); - if (!maybeo || maybeo.value() == 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)"); + else { + using returns_list = typename wrap::returns_list; + using args_list = typename wrap::args_list; + using caller = typename wrap::caller; + return stack::call_into_lua( + returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward(fx), std::forward(args)...); + } } - object_type* o = static_cast(maybeo.value()); - return call_assign(std::true_type(), L, f, *o); + else if constexpr (std::is_member_object_pointer_v) { + using traits_type = lua_bind_traits; + using wrap = wrapper; + using object_type = typename wrap::object_type; + using return_type = typename traits_type::return_type; + constexpr bool is_const = std::is_const_v>; + if constexpr (is_const) { + (void)fx; + (void)detail::swallow{ 0, (static_cast(args), 0)... }; + return luaL_error(L, "sol: cannot write to a readonly (const) variable"); + } + else { + using u_return_type = meta::unqualified_t; + constexpr bool is_assignable = std::is_copy_assignable_v || std::is_array_v; + if constexpr (!is_assignable) { + (void)fx; + (void)detail::swallow{ 0, ((void)args, 0)... }; + return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); + } + else { + using args_list = typename wrap::args_list; + using caller = typename wrap::caller; + if constexpr (sizeof...(Args) > 0) { + return stack::call_into_lua(types(), + args_list(), + L, + boost + (is_variable ? 3 : 2), + caller(), + std::forward(fx), + std::forward(args)...); + } + else { + using Ta = std::conditional_t, object_type, T>; +#if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE + auto maybeo = stack::check_get(L, 1); + if (!maybeo || maybeo.value() == 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)"); + } + object_type* po = static_cast(maybeo.value()); + object_type& o = *po; #else - object_type& o = static_cast(*stack::get>(L, 1)); - return call_assign(std::true_type(), L, f, o); + object_type& o = static_cast(*stack::get>(L, 1)); #endif // Safety - } - template - static int call_assign(std::false_type, lua_State* L, Args&&...) { - return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); - } - - template - static int call_const(std::false_type, lua_State* L, Args&&... args) { - typedef typename traits_type::return_type R; - return call_assign(std::is_copy_assignable>(), L, std::forward(args)...); - } - - template - static int call_const(std::true_type, lua_State* L, Args&&...) { - return luaL_error(L, "sol: cannot write to a readonly (const) variable"); - } - - template - static int call(lua_State* L, V&& f) { - return call_const(std::is_const(), L, std::forward(f)); - } - - template - static int call(lua_State* L, V&& f, object_type& o) { - return call_const(std::is_const(), L, std::forward(f), o); + return stack::call_into_lua( + types(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward(fx), o); + } + } + } + } + else { + agnostic_lua_call_wrapper alcw{}; + return alcw.call(L, std::forward(fx), std::forward(args)...); + } } }; template struct lua_call_wrapper::value>> { - typedef lua_bind_traits traits_type; - typedef wrapper> wrap; - typedef typename wrap::object_type object_type; + using traits_type = lua_bind_traits; + using wrap = wrapper; + using object_type = typename wrap::object_type; template static int call(lua_State* L, V&& v, object_type& o) { - typedef typename wrap::returns_list returns_list; - typedef typename wrap::caller caller; + using returns_list = typename wrap::returns_list; + using caller = typename wrap::caller; F f(std::forward(v)); return stack::call_into_lua(returns_list(), types<>(), L, boost + (is_variable ? 3 : 2), caller(), f, o); } template static int call(lua_State* L, V&& f) { - typedef std::conditional_t::value, object_type, T> Ta; + using Ta = std::conditional_t::value, object_type, T>; #if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE auto maybeo = stack::check_get(L, 1); if (!maybeo || maybeo.value() == nullptr) { @@ -505,23 +577,68 @@ namespace sol { template struct lua_call_wrapper, false, is_variable, checked, boost, clean_stack, C> { - typedef lua_bind_traits traits_type; - typedef wrapper> wrap; - typedef typename wrap::object_type object_type; + using traits_type = lua_bind_traits; + using wrap = wrapper; + using object_type = typename wrap::object_type; - template - static int call(lua_State* L, V&&) { + static int call(lua_State* L, const readonly_wrapper&) { return luaL_error(L, "sol: cannot write to a sol::readonly variable"); } - template - static int call(lua_State* L, V&&, object_type&) { - return luaL_error(L, "sol: cannot write to a sol::readonly variable"); + static int call(lua_State* L, const readonly_wrapper& rw, object_type&) { + return call(L, rw); } }; - template - struct lua_call_wrapper, true, is_variable, checked, boost, clean_stack, C> : lua_call_wrapper { + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack, C> { + using traits_type = lua_bind_traits; + using wrap = wrapper; + using object_type = typename wrap::object_type; + + static int call(lua_State* L, readonly_wrapper&& rw) { + if constexpr (!is_index) { + (void)rw; + return luaL_error(L, "sol: cannot write to a sol::readonly variable"); + } + else { + lua_call_wrapper lcw; + return lcw.call(L, std::move(rw.get_value()), o); + } + } + + static int call(lua_State* L, readonly_wrapper&& rw, object_type& o) { + if constexpr (!is_index) { + (void)o; + return call(L, std::move(rw)); + } + else { + lua_call_wrapper lcw; + return lcw.call(L, rw.get_value(), o); + } + } + + static int call(lua_State* L, const readonly_wrapper& rw) { + if constexpr (!is_index) { + (void)rw; + return luaL_error(L, "sol: cannot write to a sol::readonly variable"); + } + else { + lua_call_wrapper lcw; + return lcw.call(L, rw.get_value()); + } + } + + static int call(lua_State* L, const readonly_wrapper& rw, object_type& o) { + if constexpr (!is_index) { + (void)o; + return call(L, rw); + } + else { + lua_call_wrapper lcw; + return lcw.call(L, rw.get_value(), o); + } + } }; template @@ -577,37 +694,29 @@ namespace sol { } }; - template - struct lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack, std::enable_if_t::value>> { + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack, C> { typedef destructor_wrapper F; - static int call(lua_State* L, const F&) { - return detail::usertype_alloc_destruct(L); - } - }; - - template - struct lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack, std::enable_if_t::value>> { - typedef destructor_wrapper F; - - static int call_void(std::true_type, lua_State* L, const F& f) { - typedef meta::bind_traits> bt; - typedef typename bt::template arg_at<0> arg0; - typedef meta::unqualified_t O; - - O& obj = stack::get(L); - f.fx(detail::implicit_wrapper(obj)); - return 0; - } - - static int call_void(std::false_type, lua_State* L, const F& f) { - T& obj = stack::get(L); - f.fx(detail::implicit_wrapper(obj)); - return 0; - } - static int call(lua_State* L, const F& f) { - return call_void(std::is_void(), L, f); + if constexpr (std::is_void_v) { + return detail::usertype_alloc_destruct(L); + } + else { + if constexpr (std::is_void_v) { + using bt = meta::bind_traits>; + using arg0_t = typename bt::template arg_at<0>; + + decltype(auto) obj = stack::get(L, -1); + f.fx(detail::implicit_wrapper>(obj)); + return 0; + } + else { + T& obj = stack::get(L, -1); + f.fx(detail::implicit_wrapper(obj)); + return 0; + } + } } }; @@ -619,7 +728,7 @@ namespace sol { template int operator()(types, meta::index_value, types, types, lua_State* L, int, int, F& fx) { auto& f = std::get(fx.functions); - return lua_call_wrapper {}.call(L, f); + return lua_call_wrapper{}.call(L, f); } }; @@ -636,7 +745,7 @@ namespace sol { template int operator()(types, meta::index_value, types, types, lua_State* L, int, int, F& fx) { auto& f = std::get(fx.functions); - return lua_call_wrapper {}.call(L, f); + return lua_call_wrapper{}.call(L, f); } }; @@ -653,59 +762,75 @@ namespace sol { typedef lua_bind_traits traits_type; typedef meta::unqualified_t> object_type; - template - static int self_call(std::true_type, lua_State* L, F&& f) { - // The type being void means we don't have any arguments, so it might be a free functions? - typedef typename traits_type::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, boost + (is_variable ? 3 : 2), caller(), f); - } - - template - static int self_call(std::false_type, lua_State* L, F&& f) { - typedef meta::pop_front_type_t args_list; - typedef T Ta; - typedef std::remove_pointer_t Oa; -#if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE - auto maybeo = stack::check_get(L, 1); - if (!maybeo || maybeo.value() == nullptr) { - if (is_variable) { - return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)"); - } - return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)"); - } - Oa* o = static_cast(maybeo.value()); -#else - Oa* o = static_cast(stack::get>(L, 1)); -#endif // Safety - typedef typename wrap::returns_list returns_list; - typedef typename wrap::caller caller; - return stack::call_into_lua(returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), f, detail::implicit_wrapper(*o)); - } - - template - static int defer_call(std::false_type, lua_State* L, F&& f, Args&&... args) { - return self_call(meta::any, meta::boolean>::value != type::userdata>>(), L, pick(meta::boolean(), f), std::forward(args)...); - } - - template - static int defer_call(std::true_type, lua_State* L, F&& f, Args&&... args) { - auto& p = pick(meta::boolean(), std::forward(f)); - return lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack> {}.call(L, p, std::forward(args)...); - } - template static int call(lua_State* L, F&& f, Args&&... args) { - typedef meta::any< - std::is_void, - std::is_same, - meta::is_specialization_of, - meta::is_specialization_of, - meta::is_specialization_of, - std::is_member_pointer> - is_specialized; - return defer_call(is_specialized(), L, std::forward(f), std::forward(args)...); + constexpr bool is_specialized = meta::any< + std::is_same, + meta::is_specialization_of, + meta::is_specialization_of, + meta::is_specialization_of, + std::is_member_pointer>::value; + if constexpr (is_specialized) { + if constexpr (is_index) { + decltype(auto) p = f.read(); + lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack> lcw{}; + return lcw.call(L, p, std::forward(args)...); + } + else { + decltype(auto) p = f.write(); + lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack> lcw{}; + return lcw.call(L, p, std::forward(args)...); + } + } + else { + constexpr bool non_class_object_type = meta::any, + meta::boolean>::value != type::userdata>>::value; + if constexpr (non_class_object_type) { + // The type being void means we don't have any arguments, so it might be a free functions? + using args_list = typename traits_type::free_args_list; + using returns_list = typename wrap::returns_list; + using caller = typename wrap::caller; + if constexpr (is_index) { + decltype(auto) pf = f.read(); + return stack::call_into_lua( + returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf); + } + else { + decltype(auto) pf = f.write(); + return stack::call_into_lua( + returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf); + } + } + else { + using args_list = meta::pop_front_type_t; + using Ta = T; + using Oa = std::remove_pointer_t; +#if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE + auto maybeo = stack::check_get(L, 1); + if (!maybeo || maybeo.value() == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)"); + } + return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)"); + } + Oa* o = static_cast(maybeo.value()); +#else + Oa* o = static_cast(stack::get>(L, 1)); +#endif // Safety + using returns_list = typename wrap::returns_list; + using caller = typename wrap::caller; + if constexpr (is_index) { + decltype(auto) pf = f.read(); + return stack::call_into_lua( + returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf, detail::implicit_wrapper(*o)); + } + else { + decltype(auto) pf = f.write(); + return stack::call_into_lua( + returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf, detail::implicit_wrapper(*o)); + } + } + } } }; @@ -715,7 +840,7 @@ namespace sol { template static int call(lua_State* L, F& fx, Args&&... args) { - return lua_call_wrapper {}.call(L, fx.value, std::forward(args)...); + return lua_call_wrapper{}.call(L, fx.value, std::forward(args)...); } }; @@ -725,8 +850,8 @@ namespace sol { template static int call(std::index_sequence, lua_State* L, P& fx) { - int pushed = lua_call_wrapper {}.call(L, fx.value); - (void)detail::swallow { int(), (filter_detail::handle_filter(std::get(fx.filters), L, pushed), int())... }; + int pushed = lua_call_wrapper{}.call(L, fx.value); + (void)detail::swallow{ int(), (filter_detail::handle_filter(std::get(fx.filters), L, pushed), int())... }; return pushed; } @@ -746,24 +871,30 @@ namespace sol { template struct lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack, C> { - template - static int call(lua_State* L, F&& f) { - return lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack>{}.call(L, std::get<0>(f.arguments)); + static int call(lua_State* L, const function_arguments& f) { + lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack> lcw{}; + return lcw.call(L, std::get<0>(f.arguments)); + } + + static int call(lua_State* L, function_arguments&& f) { + lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack> lcw{}; + return lcw.call(L, std::get<0>(std::move(f.arguments))); } }; - template + template inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) { using uFx = meta::unqualified_t; - if constexpr(meta::is_specialization_of_v) { + if constexpr (meta::is_specialization_of_v) { using real_fx = meta::unqualified_t(fx).func)>; - int nr = lua_call_wrapper{}.call( - L, std::forward(fx).func, std::forward(args)...); + lua_call_wrapper lcw{}; + int nr = lcw.call(L, std::forward(fx).func, std::forward(args)...); return lua_yield(L, nr); } else { - return lua_call_wrapper{}.call( - L, std::forward(fx), std::forward(args)...); + lua_call_wrapper lcw{}; + return lcw.call(L, std::forward(fx), std::forward(args)...); } } @@ -783,7 +914,7 @@ namespace sol { struct is_var_bind::value>> : std::true_type {}; template <> - struct is_var_bind : std::true_type {}; + struct is_var_bind : std::true_type {}; template struct is_var_bind> : std::true_type {}; diff --git a/include/sol/ebco.hpp b/include/sol/ebco.hpp new file mode 100644 index 00000000..478d3137 --- /dev/null +++ b/include/sol/ebco.hpp @@ -0,0 +1,94 @@ +// sol3 + +// The MIT License (MIT) + +// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors + +// 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_EBCO_HPP +#define SOL_EBCO_HPP + +#include + +namespace sol { + + template + struct ebco { + T value; + + ebco() = default; + ebco(const ebco&) = default; + ebco(ebco&&) = default; + ebco& operator=(const ebco&) = default; + ebco& operator=(ebco&&) = default; + ebco(const T& v) : value(v){}; + ebco(T&& v) : value(std::move(v)){}; + ebco& operator=(const T& v) { + value = v; + } + ebco& operator=(T&& v) { + value = std::move(v); + }; + template >, + ebco> && !std::is_same_v>, T>>> + ebco(Arg&& arg, Args&&... args) : T(std::forward(arg), std::forward(args)...){}; + + T& get_value() { + return value; + } + + T const& get_value() const { + return value; + } + }; + + template + struct ebco && !std::is_final_v>> : T { + ebco() = default; + ebco(const ebco&) = default; + ebco(ebco&&) = default; + ebco(const T& v) : T(v){}; + ebco(T&& v) : T(std::move(v)){}; + template >, + ebco> && !std::is_same_v>, T>>> + ebco(Arg&& arg, Args&&... args) : T(std::forward(arg), std::forward(args)...){}; + + ebco& operator=(const ebco&) = default; + ebco& operator=(ebco&&) = default; + ebco& operator=(const T& v) { + static_cast(*this) = v; + } + ebco& operator=(T&& v) { + static_cast(*this) = std::move(v); + }; + + T& get_value() { + return static_cast(*this); + } + + T const& get_value() const { + return static_cast(*this); + } + }; + +} // namespace sol + +#endif // SOL_EBCO_HPP diff --git a/include/sol/function_types.hpp b/include/sol/function_types.hpp index a6ce9537..2c099599 100644 --- a/include/sol/function_types.hpp +++ b/include/sol/function_types.hpp @@ -156,6 +156,7 @@ namespace sol { using dFx = std::decay_t; using Tu = meta::unqualified_t; if constexpr (meta::is_specialization_of_v) { + (void)obj; using C = typename Tu::type; lua_CFunction freefunc = &function_detail::upvalue_this_member_function::call; @@ -178,7 +179,7 @@ namespace sol { } else { using F = function_detail::member_function; - select_set_fx(L, std::forward(fx), std::forward(args)...); + select_set_fx(L, std::forward(fx), std::forward(obj), std::forward(args)...); } } } diff --git a/include/sol/function_types_templated.hpp b/include/sol/function_types_templated.hpp index ad2cb846..46a8ef92 100644 --- a/include/sol/function_types_templated.hpp +++ b/include/sol/function_types_templated.hpp @@ -140,8 +140,9 @@ namespace sol { template inline int c_call(lua_State* L) { - if (sizeof...(Fxs) < 2) { - return meta::at_in_pack_t<0, Fxs...>::call(L); + if constexpr (sizeof...(Fxs) < 2) { + using target = meta::at_in_pack_t<0, Fxs...>; + return target::call(L); } else { return call_detail::overload_match_arity(function_detail::c_call_matcher(), L, lua_gettop(L), 1); diff --git a/include/sol/property.hpp b/include/sol/property.hpp index 4534e54b..8b536bab 100644 --- a/include/sol/property.hpp +++ b/include/sol/property.hpp @@ -25,83 +25,84 @@ #define SOL_PROPERTY_HPP #include "types.hpp" +#include "ebco.hpp" #include #include namespace sol { - - struct no_prop {}; + namespace detail { + struct no_prop {}; + } template - struct property_wrapper { - typedef std::integral_constant::value> can_read; - typedef std::integral_constant::value> can_write; - typedef std::conditional_t Read; - typedef std::conditional_t Write; - Read read; - Write write; - + struct property_wrapper : ebco, ebco { template property_wrapper(Rx&& r, Wx&& w) - : read(std::forward(r)), write(std::forward(w)) { + : ebco(std::forward(r)), ebco(std::forward(w)) { + } + + W& write() { + return ebco::get_value(); + } + + const W& write() const { + return ebco::get_value(); + } + + R& read() { + return ebco::get_value(); + } + + const R& read() const { + return ebco::get_value(); } }; - namespace property_detail { - template - inline decltype(auto) property(std::true_type, R&& read, W&& write) { - return property_wrapper, std::decay_t>(std::forward(read), std::forward(write)); - } - template - inline decltype(auto) property(std::false_type, W&& write, R&& read) { - return property_wrapper, std::decay_t>(std::forward(read), std::forward(write)); - } - template - inline decltype(auto) property(std::true_type, R&& read) { - return property_wrapper, void>(std::forward(read), no_prop()); - } - template - inline decltype(auto) property(std::false_type, W&& write) { - return property_wrapper>(no_prop(), std::forward(write)); - } - } // namespace property_detail - template inline decltype(auto) property(F&& f, G&& g) { typedef lua_bind_traits> left_traits; typedef lua_bind_traits> right_traits; - return property_detail::property(meta::boolean<(left_traits::free_arity < right_traits::free_arity)>(), std::forward(f), std::forward(g)); + if constexpr (left_traits::free_arity < right_traits::free_arity) { + return property_wrapper, std::decay_t>(std::forward(f), std::forward(g)); + } + else { + return property_wrapper, std::decay_t>(std::forward(g), std::forward(f)); + } } template inline decltype(auto) property(F&& f) { typedef lua_bind_traits> left_traits; - return property_detail::property(meta::boolean<(left_traits::free_arity < 2)>(), std::forward(f)); + if constexpr (left_traits::free_arity < 2) { + return property_wrapper, detail::no_prop>(std::forward(f), detail::no_prop()); + } + else { + return property_wrapper>(detail::no_prop(), std::forward(f)); + } } template inline decltype(auto) readonly_property(F&& f) { - return property_detail::property(std::true_type(), std::forward(f)); + return property_wrapper, detail::no_prop>(std::forward(f), detail::no_prop()); } template inline decltype(auto) writeonly_property(F&& f) { - return property_detail::property(std::false_type(), std::forward(f)); + return property_wrapper>(detail::no_prop(), std::forward(f)); } template - struct readonly_wrapper { - T v; - - readonly_wrapper(T v) - : v(std::move(v)) { - } + struct readonly_wrapper : ebco { + private: + using base_t = ebco; + public: + using base_t::base_t; operator T&() { - return v; + return base_t::get_value(); } operator const T&() const { - return v; + return base_t::get_value(); } }; @@ -112,16 +113,11 @@ namespace sol { } template - struct var_wrapper { - T value; - template - var_wrapper(Args&&... args) - : value(std::forward(args)...) { - } - var_wrapper(const var_wrapper&) = default; - var_wrapper(var_wrapper&&) = default; - var_wrapper& operator=(const var_wrapper&) = default; - var_wrapper& operator=(var_wrapper&&) = default; + struct var_wrapper : ebco { + private: + using base_t = ebco; + public: + using base_t::base_t; }; template diff --git a/include/sol/stack.hpp b/include/sol/stack.hpp index 3207b156..3ab32b67 100644 --- a/include/sol/stack.hpp +++ b/include/sol/stack.hpp @@ -127,26 +127,19 @@ namespace sol { return eval(types(), std::index_sequence(), L, start, tracking, std::forward(fx), std::forward(fxargs)..., stack_detail::unchecked_get(L, start + tracking.used, tracking)); } - template ::value >> + template inline decltype(auto) call(types, types ta, std::index_sequence tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { -#ifndef _MSC_VER static_assert(meta::all...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention."); -#endif // This compiler make me so sad argument_handler> handler{}; multi_check(L, start, handler); record tracking{}; - return eval(ta, tai, L, start, tracking, std::forward(fx), std::forward(args)...); - } - - template - inline void call(types, types ta, std::index_sequence tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { -#ifndef _MSC_VER - static_assert(meta::all...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention."); -#endif // This compiler make me so fucking sad - argument_handler> handler{}; - multi_check(L, start, handler); - record tracking{}; - eval(ta, tai, L, start, tracking, std::forward(fx), std::forward(args)...); + if constexpr (std::is_void_v) { + eval(ta, tai, L, start, tracking, std::forward(fx), std::forward(args)...); + } + + else { + return eval(ta, tai, L, start, tracking, std::forward(fx), std::forward(args)...); + } } } // namespace stack_detail @@ -156,65 +149,74 @@ namespace sol { return luaL_ref(L, tableindex); } - template ::value>> + template inline decltype(auto) call(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { - typedef std::make_index_sequence args_indices; - return stack_detail::call(tr, ta, args_indices(), L, start, std::forward(fx), std::forward(args)...); + using args_indices = std::make_index_sequence; + if constexpr (std::is_void_v) { + stack_detail::call(tr, ta, args_indices(), L, start, std::forward(fx), std::forward(args)...); + } + else { + return stack_detail::call(tr, ta, args_indices(), L, start, std::forward(fx), std::forward(args)...); + } } - template ::value>> + template inline decltype(auto) call(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - return call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); + if constexpr(std::is_void_v) { + call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); + } + else { + return call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); + } } - template - inline void call(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { - typedef std::make_index_sequence args_indices; - stack_detail::call(tr, ta, args_indices(), L, start, std::forward(fx), std::forward(args)...); - } - - template - inline void call(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); - } - - template ::value>> + template inline decltype(auto) call_from_top(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - typedef meta::count_for_pack expected_count; - return call(tr, ta, L, (std::max)(static_cast(lua_gettop(L) - expected_count::value), static_cast(0)), std::forward(fx), std::forward(args)...); - } - - template - inline void call_from_top(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - typedef meta::count_for_pack expected_count; - call(tr, ta, L, (std::max)(static_cast(lua_gettop(L) - expected_count::value), static_cast(0)), std::forward(fx), std::forward(args)...); - } - - template - inline int call_into_lua(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { - call(tr, ta, L, start, std::forward(fx), std::forward(fxargs)...); - if (clean_stack) { - lua_settop(L, 0); + using expected_count_t = meta::count_for_pack; + if constexpr (std::is_void_v) { + call(tr, + ta, + L, + (std::max)(static_cast(lua_gettop(L) - expected_count::value), static_cast(0)), + std::forward(fx), + std::forward(args)...); + } + else { + return call(tr, + ta, + L, + (std::max)(static_cast(lua_gettop(L) - expected_count_t::value), static_cast(0)), + std::forward(fx), + std::forward(args)...); } - return 0; } - template >::value>> - inline int call_into_lua(types, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { - decltype(auto) r = call(types>(), ta, L, start, std::forward(fx), std::forward(fxargs)...); - using R = meta::unqualified_t; - using is_stack = meta::any, std::is_same, std::is_same, std::is_same>; - if constexpr (clean_stack && !is_stack::value) { - lua_settop(L, 0); + template + inline int call_into_lua(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { + if constexpr (std::is_void_v) { + call(tr, ta, L, start, std::forward(fx), std::forward(fxargs)...); + if constexpr (clean_stack) { + lua_settop(L, 0); + } + return 0; + } + else { + (void)tr; + decltype(auto) r = call(types>(), ta, L, start, std::forward(fx), std::forward(fxargs)...); + using R = meta::unqualified_t; + using is_stack = meta::any, std::is_same, std::is_same, std::is_same>; + if constexpr (clean_stack && !is_stack::value) { + lua_settop(L, 0); + } + return push_reference(L, std::forward(r)); } - return push_reference(L, std::forward(r)); } template inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { - typedef lua_bind_traits> traits_type; - typedef typename traits_type::args_list args_list; - typedef typename traits_type::returns_list returns_list; + using traits_type = lua_bind_traits>; + using args_list = typename traits_type::args_list; + using returns_list = typename traits_type::returns_list; return call_into_lua(returns_list(), args_list(), L, start, std::forward(fx), std::forward(fxargs)...); } diff --git a/include/sol/stack_check_unqualified.hpp b/include/sol/stack_check_unqualified.hpp index 3d5b7689..f830f602 100644 --- a/include/sol/stack_check_unqualified.hpp +++ b/include/sol/stack_check_unqualified.hpp @@ -646,8 +646,10 @@ namespace sol { namespace stack { template static bool is_one(std::integral_constant, lua_State* L, int index, Handler&& handler, record& tracking) { - if (V_is_empty::value && lua_isnone(L, index)) { - return true; + if constexpr (V_is_empty::value) { + if (lua_isnone(L, index)) { + return true; + } } tracking.use(1); handler(L, index, type::poly, type_of(L, index), "value does not fit any type present in the variant"); diff --git a/include/sol/stack_get_qualified.hpp b/include/sol/stack_get_qualified.hpp index 829ca10e..57b1f947 100644 --- a/include/sol/stack_get_qualified.hpp +++ b/include/sol/stack_get_qualified.hpp @@ -56,29 +56,31 @@ namespace stack { // TODO: abort / terminate, maybe only in debug modes? return r; } - memory = detail::align_usertype_unique_tag(memory); - detail::unique_tag& ic = *reinterpret_cast(memory); - memory = detail::align_usertype_unique(memory); - string_view ti = usertype_traits::qualified_name(); - string_view rebind_ti = usertype_traits::qualified_name(); - int cast_operation = ic(memory, &r, ti, rebind_ti); - switch (cast_operation) { - case 1: { - // it's a perfect match, - // alias memory directly - Real* mem = static_cast(memory); - return *mem; + else { + memory = detail::align_usertype_unique_tag(memory); + detail::unique_tag& ic = *reinterpret_cast(memory); + memory = detail::align_usertype_unique(memory); + string_view ti = usertype_traits::qualified_name(); + string_view rebind_ti = usertype_traits::qualified_name(); + int cast_operation = ic(memory, &r, ti, rebind_ti); + switch (cast_operation) { + case 1: { + // it's a perfect match, + // alias memory directly + Real* mem = static_cast(memory); + return *mem; + } + case 2: + // it's a base match, return the + // aliased creation + return std::move(r); + default: + // uh oh.. + break; + } + // TODO: abort / terminate, maybe only in debug modes? + return r; } - case 2: - // it's a base match, return the - // aliased creation - return std::move(r); - default: - // uh oh.. - break; - } - // TODO: abort / terminate, maybe only in debug modes? - return r; } }; diff --git a/include/sol/stack_get_unqualified.hpp b/include/sol/stack_get_unqualified.hpp index 71ef025a..ca291e28 100644 --- a/include/sol/stack_get_unqualified.hpp +++ b/include/sol/stack_get_unqualified.hpp @@ -404,7 +404,7 @@ namespace sol { namespace stack { // This method is HIGHLY performant over regular table iteration thanks to the Lua API changes in 5.3 for (lua_Integer i = 0;; i += lua_size::value, lua_pop(L, lua_size::value)) { if (idx >= arr.max_size()) { - return arr; + goto done; } bool isnil = false; for (int vi = 0; vi < lua_size::value; ++vi) { @@ -415,7 +415,7 @@ namespace sol { namespace stack { break; } lua_pop(L, (vi + 1)); - return arr; + goto done; } } if (isnil) @@ -427,7 +427,7 @@ namespace sol { namespace stack { // Zzzz slower but necessary thanks to the lower version API and missing functions qq for (lua_Integer i = 0;; i += lua_size::value, lua_pop(L, lua_size::value)) { if (idx >= arr.max_size()) { - return arr; + goto done; } bool isnil = false; for (int vi = 0; vi < lua_size::value; ++vi) { @@ -440,7 +440,7 @@ namespace sol { namespace stack { break; } lua_pop(L, (vi + 1)); - return arr; + goto done; } } if (isnil) @@ -449,6 +449,7 @@ namespace sol { namespace stack { ++idx; } #endif + done: return arr; } @@ -939,24 +940,20 @@ namespace sol { namespace stack { #if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT template struct unqualified_getter> { - typedef std::variant V; - typedef std::variant_size V_size; - typedef std::integral_constant V_is_empty; - - static V get_empty(std::true_type, lua_State*, int, record&) { - return V(); - } - - static V get_empty(std::false_type, lua_State* L, int index, record& tracking) { - typedef std::variant_alternative_t<0, V> T; - // This should never be reached... - // please check your code and understand what you did to bring yourself here - std::abort(); - return V(std::in_place_index<0>, stack::get(L, index, tracking)); - } - + using V = std::variant; + static V get_one(std::integral_constant, lua_State* L, int index, record& tracking) { - return get_empty(V_is_empty(), L, index, tracking); + (void)L; + (void)index; + (void)tracking; + if constexpr (std::variant_size_v == 0) { + return V(); + } + else { + using T = std::variant_alternative_t<0, V>; + std::abort(); + /*return V(std::in_place_index<0>, stack::get(L, index, tracking));*/ + } } template @@ -971,7 +968,7 @@ namespace sol { namespace stack { } static V get(lua_State* L, int index, record& tracking) { - return get_one(std::integral_constant(), L, index, tracking); + return get_one(std::integral_constant>(), L, index, tracking); } }; #endif // SOL_STD_VARIANT diff --git a/include/sol/stack_probe.hpp b/include/sol/stack_probe.hpp index a5a3ce24..c270f7ed 100644 --- a/include/sol/stack_probe.hpp +++ b/include/sol/stack_probe.hpp @@ -64,7 +64,7 @@ namespace stack { struct probe_field_getter, P, b, raw, C> { template probe apply(std::index_sequence, int sofar, lua_State* L, Keys&& keys, int tableindex) { - get_field < I<1 && b, raw>(L, std::get(keys), tableindex); + get_field<(I<1) && b, raw>(L, std::get(keys), tableindex); return probe(check

(L), sofar); } @@ -79,10 +79,15 @@ namespace stack { template probe get(lua_State* L, Keys&& keys, int tableindex = -2) { - if (!b && !maybe_indexable(L, tableindex)) { - return probe(false, 0); + if constexpr (!b) { + if (!maybe_indexable(L, tableindex)) { + return probe(false, 0); + } + return apply(std::index_sequence_for(), 1, L, std::forward(keys), tableindex); + } + else { + return apply(std::index_sequence_for(), 1, L, std::forward(keys), tableindex); } - return apply(std::index_sequence_for(), 1, L, std::forward(keys), tableindex); } }; } diff --git a/include/sol/stack_push.hpp b/include/sol/stack_push.hpp index 11d0c1ef..a22a18c7 100644 --- a/include/sol/stack_push.hpp +++ b/include/sol/stack_push.hpp @@ -825,9 +825,11 @@ namespace sol { const char16_t* se = reinterpret_cast(stre); return stack::push(L, sb, se); } - const char32_t* sb = reinterpret_cast(strb); - const char32_t* se = reinterpret_cast(stre); - return stack::push(L, sb, se); + else { + const char32_t* sb = reinterpret_cast(strb); + const char32_t* se = reinterpret_cast(stre); + return stack::push(L, sb, se); + } } }; diff --git a/include/sol/state_view.hpp b/include/sol/state_view.hpp index 04f5c0ea..a7ad768c 100644 --- a/include/sol/state_view.hpp +++ b/include/sol/state_view.hpp @@ -115,85 +115,86 @@ namespace sol { luaL_openlibs(L); return; } + else { + lib libraries[1 + sizeof...(args)] = { lib::count, std::forward(args)... }; - lib libraries[1 + sizeof...(args)] = { lib::count, std::forward(args)... }; - - for (auto&& library : libraries) { - switch (library) { -#if SOL_LUA_VERSION <= 501 && defined(SOL_LUAJIT) - case lib::coroutine: -#endif // luajit opens coroutine base stuff - case lib::base: - luaL_requiref(L, "base", luaopen_base, 1); - lua_pop(L, 1); - break; - case lib::package: - luaL_requiref(L, "package", luaopen_package, 1); - lua_pop(L, 1); - break; -#if !defined(SOL_LUAJIT) - case lib::coroutine: -#if SOL_LUA_VERSION > 501 - luaL_requiref(L, "coroutine", luaopen_coroutine, 1); - lua_pop(L, 1); -#endif // Lua 5.2+ only - break; -#endif // Not LuaJIT - comes builtin - case lib::string: - luaL_requiref(L, "string", luaopen_string, 1); - lua_pop(L, 1); - break; - case lib::table: - luaL_requiref(L, "table", luaopen_table, 1); - lua_pop(L, 1); - break; - case lib::math: - luaL_requiref(L, "math", luaopen_math, 1); - lua_pop(L, 1); - break; - case lib::bit32: -#ifdef SOL_LUAJIT - luaL_requiref(L, "bit32", luaopen_bit, 1); - lua_pop(L, 1); -#elif (SOL_LUA_VERSION == 502) || defined(LUA_COMPAT_BITLIB) || defined(LUA_COMPAT_5_2) - luaL_requiref(L, "bit32", luaopen_bit32, 1); - lua_pop(L, 1); -#else -#endif // Lua 5.2 only (deprecated in 5.3 (503)) (Can be turned on with Compat flags) - break; - case lib::io: - luaL_requiref(L, "io", luaopen_io, 1); - lua_pop(L, 1); - break; - case lib::os: - luaL_requiref(L, "os", luaopen_os, 1); - lua_pop(L, 1); - break; - case lib::debug: - luaL_requiref(L, "debug", luaopen_debug, 1); - lua_pop(L, 1); - break; - case lib::utf8: -#if SOL_LUA_VERSION > 502 && !defined(SOL_LUAJIT) - luaL_requiref(L, "utf8", luaopen_utf8, 1); - lua_pop(L, 1); -#endif // Lua 5.3+ only - break; - case lib::ffi: -#ifdef SOL_LUAJIT - luaL_requiref(L, "ffi", luaopen_ffi, 1); - lua_pop(L, 1); -#endif // LuaJIT only - break; - case lib::jit: -#ifdef SOL_LUAJIT - luaL_requiref(L, "jit", luaopen_jit, 0); - lua_pop(L, 1); -#endif // LuaJIT Only - break; - case lib::count: - default: - break; + for (auto&& library : libraries) { + switch (library) { + #if SOL_LUA_VERSION <= 501 && defined(SOL_LUAJIT) + case lib::coroutine: + #endif // luajit opens coroutine base stuff + case lib::base: + luaL_requiref(L, "base", luaopen_base, 1); + lua_pop(L, 1); + break; + case lib::package: + luaL_requiref(L, "package", luaopen_package, 1); + lua_pop(L, 1); + break; + #if !defined(SOL_LUAJIT) + case lib::coroutine: + #if SOL_LUA_VERSION > 501 + luaL_requiref(L, "coroutine", luaopen_coroutine, 1); + lua_pop(L, 1); + #endif // Lua 5.2+ only + break; + #endif // Not LuaJIT - comes builtin + case lib::string: + luaL_requiref(L, "string", luaopen_string, 1); + lua_pop(L, 1); + break; + case lib::table: + luaL_requiref(L, "table", luaopen_table, 1); + lua_pop(L, 1); + break; + case lib::math: + luaL_requiref(L, "math", luaopen_math, 1); + lua_pop(L, 1); + break; + case lib::bit32: + #ifdef SOL_LUAJIT + luaL_requiref(L, "bit32", luaopen_bit, 1); + lua_pop(L, 1); + #elif (SOL_LUA_VERSION == 502) || defined(LUA_COMPAT_BITLIB) || defined(LUA_COMPAT_5_2) + luaL_requiref(L, "bit32", luaopen_bit32, 1); + lua_pop(L, 1); + #else + #endif // Lua 5.2 only (deprecated in 5.3 (503)) (Can be turned on with Compat flags) + break; + case lib::io: + luaL_requiref(L, "io", luaopen_io, 1); + lua_pop(L, 1); + break; + case lib::os: + luaL_requiref(L, "os", luaopen_os, 1); + lua_pop(L, 1); + break; + case lib::debug: + luaL_requiref(L, "debug", luaopen_debug, 1); + lua_pop(L, 1); + break; + case lib::utf8: + #if SOL_LUA_VERSION > 502 && !defined(SOL_LUAJIT) + luaL_requiref(L, "utf8", luaopen_utf8, 1); + lua_pop(L, 1); + #endif // Lua 5.3+ only + break; + case lib::ffi: + #ifdef SOL_LUAJIT + luaL_requiref(L, "ffi", luaopen_ffi, 1); + lua_pop(L, 1); + #endif // LuaJIT only + break; + case lib::jit: + #ifdef SOL_LUAJIT + luaL_requiref(L, "jit", luaopen_jit, 0); + lua_pop(L, 1); + #endif // LuaJIT Only + break; + case lib::count: + default: + break; + } } } } diff --git a/include/sol/types.hpp b/include/sol/types.hpp index 08370699..78632f82 100644 --- a/include/sol/types.hpp +++ b/include/sol/types.hpp @@ -1174,6 +1174,9 @@ namespace sol { template <> struct is_stack_based : std::true_type {}; + template + constexpr inline bool is_stack_based_v = is_stack_based::value; + template struct is_lua_primitive : std::true_type {}; template <> diff --git a/include/sol/wrapper.hpp b/include/sol/wrapper.hpp index c3f1164d..f34e07a6 100644 --- a/include/sol/wrapper.hpp +++ b/include/sol/wrapper.hpp @@ -112,7 +112,19 @@ namespace sol { template static void call(Fx&& fx, object_type& mem, Arg&& arg, Args&&...) { - (mem.*fx) = std::forward(arg); + using actual_type = meta::unqualified_t>; + if constexpr (std::is_array_v) { + using std::cend; + using std::cbegin; + auto first = cbegin(arg); + auto last = cend(arg); + for (std::size_t i = 0; first != last; ++i, ++first) { + (mem.*fx)[i] = *first; + } + } + else { + (mem.*fx) = std::forward(arg); + } } struct caller { diff --git a/single/include/sol/forward.hpp b/single/include/sol/forward.hpp index e64384ae..17d7122a 100644 --- a/single/include/sol/forward.hpp +++ b/single/include/sol/forward.hpp @@ -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 2019-01-28 17:33:06.880854 UTC -// This header was generated with sol v2.20.6 (revision e1f3e5f) +// Generated 2019-02-10 18:04:01.576518 UTC +// This header was generated with sol v2.20.6 (revision fbf5b48) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP diff --git a/single/include/sol/sol.hpp b/single/include/sol/sol.hpp index 113ca574..ad47d205 100644 --- a/single/include/sol/sol.hpp +++ b/single/include/sol/sol.hpp @@ -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 2019-01-28 17:33:06.587638 UTC -// This header was generated with sol v2.20.6 (revision e1f3e5f) +// Generated 2019-02-10 18:04:01.131525 UTC +// This header was generated with sol v2.20.6 (revision fbf5b48) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -1035,7 +1035,7 @@ namespace meta { template struct callable_traits { - typedef std::conditional_t::value, std::add_lvalue_reference_t, R> return_type; + typedef std::conditional_t, std::add_lvalue_reference_t, R> return_type; typedef return_type Arg; typedef T object_type; using signature_type = R(T::*); @@ -6959,6 +6959,9 @@ namespace sol { template <> struct is_stack_based : std::true_type {}; + template + constexpr inline bool is_stack_based_v = is_stack_based::value; + template struct is_lua_primitive : std::true_type {}; template <> @@ -10600,8 +10603,10 @@ namespace sol { namespace stack { template static bool is_one(std::integral_constant, lua_State* L, int index, Handler&& handler, record& tracking) { - if (V_is_empty::value && lua_isnone(L, index)) { - return true; + if constexpr (V_is_empty::value) { + if (lua_isnone(L, index)) { + return true; + } } tracking.use(1); handler(L, index, type::poly, type_of(L, index), "value does not fit any type present in the variant"); @@ -11407,7 +11412,7 @@ namespace sol { namespace stack { // This method is HIGHLY performant over regular table iteration thanks to the Lua API changes in 5.3 for (lua_Integer i = 0;; i += lua_size::value, lua_pop(L, lua_size::value)) { if (idx >= arr.max_size()) { - return arr; + goto done; } bool isnil = false; for (int vi = 0; vi < lua_size::value; ++vi) { @@ -11418,7 +11423,7 @@ namespace sol { namespace stack { break; } lua_pop(L, (vi + 1)); - return arr; + goto done; } } if (isnil) @@ -11430,7 +11435,7 @@ namespace sol { namespace stack { // Zzzz slower but necessary thanks to the lower version API and missing functions qq for (lua_Integer i = 0;; i += lua_size::value, lua_pop(L, lua_size::value)) { if (idx >= arr.max_size()) { - return arr; + goto done; } bool isnil = false; for (int vi = 0; vi < lua_size::value; ++vi) { @@ -11443,7 +11448,7 @@ namespace sol { namespace stack { break; } lua_pop(L, (vi + 1)); - return arr; + goto done; } } if (isnil) @@ -11452,6 +11457,7 @@ namespace sol { namespace stack { ++idx; } #endif + done: return arr; } @@ -11941,24 +11947,20 @@ namespace sol { namespace stack { #if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT template struct unqualified_getter> { - typedef std::variant V; - typedef std::variant_size V_size; - typedef std::integral_constant V_is_empty; - - static V get_empty(std::true_type, lua_State*, int, record&) { - return V(); - } - - static V get_empty(std::false_type, lua_State* L, int index, record& tracking) { - typedef std::variant_alternative_t<0, V> T; - // This should never be reached... - // please check your code and understand what you did to bring yourself here - std::abort(); - return V(std::in_place_index<0>, stack::get(L, index, tracking)); - } - + using V = std::variant; + static V get_one(std::integral_constant, lua_State* L, int index, record& tracking) { - return get_empty(V_is_empty(), L, index, tracking); + (void)L; + (void)index; + (void)tracking; + if constexpr (std::variant_size_v == 0) { + return V(); + } + else { + using T = std::variant_alternative_t<0, V>; + std::abort(); + /*return V(std::in_place_index<0>, stack::get(L, index, tracking));*/ + } } template @@ -11973,7 +11975,7 @@ namespace sol { namespace stack { } static V get(lua_State* L, int index, record& tracking) { - return get_one(std::integral_constant(), L, index, tracking); + return get_one(std::integral_constant>(), L, index, tracking); } }; #endif // SOL_STD_VARIANT @@ -12014,29 +12016,31 @@ namespace stack { // TODO: abort / terminate, maybe only in debug modes? return r; } - memory = detail::align_usertype_unique_tag(memory); - detail::unique_tag& ic = *reinterpret_cast(memory); - memory = detail::align_usertype_unique(memory); - string_view ti = usertype_traits::qualified_name(); - string_view rebind_ti = usertype_traits::qualified_name(); - int cast_operation = ic(memory, &r, ti, rebind_ti); - switch (cast_operation) { - case 1: { - // it's a perfect match, - // alias memory directly - Real* mem = static_cast(memory); - return *mem; + else { + memory = detail::align_usertype_unique_tag(memory); + detail::unique_tag& ic = *reinterpret_cast(memory); + memory = detail::align_usertype_unique(memory); + string_view ti = usertype_traits::qualified_name(); + string_view rebind_ti = usertype_traits::qualified_name(); + int cast_operation = ic(memory, &r, ti, rebind_ti); + switch (cast_operation) { + case 1: { + // it's a perfect match, + // alias memory directly + Real* mem = static_cast(memory); + return *mem; + } + case 2: + // it's a base match, return the + // aliased creation + return std::move(r); + default: + // uh oh.. + break; + } + // TODO: abort / terminate, maybe only in debug modes? + return r; } - case 2: - // it's a base match, return the - // aliased creation - return std::move(r); - default: - // uh oh.. - break; - } - // TODO: abort / terminate, maybe only in debug modes? - return r; } }; @@ -13085,9 +13089,11 @@ namespace sol { const char16_t* se = reinterpret_cast(stre); return stack::push(L, sb, se); } - const char32_t* sb = reinterpret_cast(strb); - const char32_t* se = reinterpret_cast(stre); - return stack::push(L, sb, se); + else { + const char32_t* sb = reinterpret_cast(strb); + const char32_t* se = reinterpret_cast(stre); + return stack::push(L, sb, se); + } } }; @@ -13771,7 +13777,7 @@ namespace stack { struct probe_field_getter, P, b, raw, C> { template probe apply(std::index_sequence, int sofar, lua_State* L, Keys&& keys, int tableindex) { - get_field < I<1 && b, raw>(L, std::get(keys), tableindex); + get_field<(I<1) && b, raw>(L, std::get(keys), tableindex); return probe(check

(L), sofar); } @@ -13786,10 +13792,15 @@ namespace stack { template probe get(lua_State* L, Keys&& keys, int tableindex = -2) { - if (!b && !maybe_indexable(L, tableindex)) { - return probe(false, 0); + if constexpr (!b) { + if (!maybe_indexable(L, tableindex)) { + return probe(false, 0); + } + return apply(std::index_sequence_for(), 1, L, std::forward(keys), tableindex); + } + else { + return apply(std::index_sequence_for(), 1, L, std::forward(keys), tableindex); } - return apply(std::index_sequence_for(), 1, L, std::forward(keys), tableindex); } }; } @@ -13886,26 +13897,19 @@ namespace sol { return eval(types(), std::index_sequence(), L, start, tracking, std::forward(fx), std::forward(fxargs)..., stack_detail::unchecked_get(L, start + tracking.used, tracking)); } - template ::value >> + template inline decltype(auto) call(types, types ta, std::index_sequence tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { -#ifndef _MSC_VER static_assert(meta::all...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention."); -#endif // This compiler make me so sad argument_handler> handler{}; multi_check(L, start, handler); record tracking{}; - return eval(ta, tai, L, start, tracking, std::forward(fx), std::forward(args)...); - } - - template - inline void call(types, types ta, std::index_sequence tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { -#ifndef _MSC_VER - static_assert(meta::all...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention."); -#endif // This compiler make me so fucking sad - argument_handler> handler{}; - multi_check(L, start, handler); - record tracking{}; - eval(ta, tai, L, start, tracking, std::forward(fx), std::forward(args)...); + if constexpr (std::is_void_v) { + eval(ta, tai, L, start, tracking, std::forward(fx), std::forward(args)...); + } + + else { + return eval(ta, tai, L, start, tracking, std::forward(fx), std::forward(args)...); + } } } // namespace stack_detail @@ -13915,65 +13919,74 @@ namespace sol { return luaL_ref(L, tableindex); } - template ::value>> + template inline decltype(auto) call(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { - typedef std::make_index_sequence args_indices; - return stack_detail::call(tr, ta, args_indices(), L, start, std::forward(fx), std::forward(args)...); + using args_indices = std::make_index_sequence; + if constexpr (std::is_void_v) { + stack_detail::call(tr, ta, args_indices(), L, start, std::forward(fx), std::forward(args)...); + } + else { + return stack_detail::call(tr, ta, args_indices(), L, start, std::forward(fx), std::forward(args)...); + } } - template ::value>> + template inline decltype(auto) call(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - return call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); + if constexpr(std::is_void_v) { + call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); + } + else { + return call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); + } } - template - inline void call(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { - typedef std::make_index_sequence args_indices; - stack_detail::call(tr, ta, args_indices(), L, start, std::forward(fx), std::forward(args)...); - } - - template - inline void call(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); - } - - template ::value>> + template inline decltype(auto) call_from_top(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - typedef meta::count_for_pack expected_count; - return call(tr, ta, L, (std::max)(static_cast(lua_gettop(L) - expected_count::value), static_cast(0)), std::forward(fx), std::forward(args)...); - } - - template - inline void call_from_top(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - typedef meta::count_for_pack expected_count; - call(tr, ta, L, (std::max)(static_cast(lua_gettop(L) - expected_count::value), static_cast(0)), std::forward(fx), std::forward(args)...); - } - - template - inline int call_into_lua(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { - call(tr, ta, L, start, std::forward(fx), std::forward(fxargs)...); - if (clean_stack) { - lua_settop(L, 0); + using expected_count_t = meta::count_for_pack; + if constexpr (std::is_void_v) { + call(tr, + ta, + L, + (std::max)(static_cast(lua_gettop(L) - expected_count::value), static_cast(0)), + std::forward(fx), + std::forward(args)...); + } + else { + return call(tr, + ta, + L, + (std::max)(static_cast(lua_gettop(L) - expected_count_t::value), static_cast(0)), + std::forward(fx), + std::forward(args)...); } - return 0; } - template >::value>> - inline int call_into_lua(types, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { - decltype(auto) r = call(types>(), ta, L, start, std::forward(fx), std::forward(fxargs)...); - using R = meta::unqualified_t; - using is_stack = meta::any, std::is_same, std::is_same, std::is_same>; - if constexpr (clean_stack && !is_stack::value) { - lua_settop(L, 0); + template + inline int call_into_lua(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { + if constexpr (std::is_void_v) { + call(tr, ta, L, start, std::forward(fx), std::forward(fxargs)...); + if constexpr (clean_stack) { + lua_settop(L, 0); + } + return 0; + } + else { + (void)tr; + decltype(auto) r = call(types>(), ta, L, start, std::forward(fx), std::forward(fxargs)...); + using R = meta::unqualified_t; + using is_stack = meta::any, std::is_same, std::is_same, std::is_same>; + if constexpr (clean_stack && !is_stack::value) { + lua_settop(L, 0); + } + return push_reference(L, std::forward(r)); } - return push_reference(L, std::forward(r)); } template inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { - typedef lua_bind_traits> traits_type; - typedef typename traits_type::args_list args_list; - typedef typename traits_type::returns_list returns_list; + using traits_type = lua_bind_traits>; + using args_list = typename traits_type::args_list; + using returns_list = typename traits_type::returns_list; return call_into_lua(returns_list(), args_list(), L, start, std::forward(fx), std::forward(fxargs)...); } @@ -15015,7 +15028,19 @@ namespace sol { template static void call(Fx&& fx, object_type& mem, Arg&& arg, Args&&...) { - (mem.*fx) = std::forward(arg); + using actual_type = meta::unqualified_t>; + if constexpr (std::is_array_v) { + using std::cend; + using std::cbegin; + auto first = cbegin(arg); + auto last = cend(arg); + for (std::size_t i = 0; first != last; ++i, ++first) { + (mem.*fx)[i] = *first; + } + } + else { + (mem.*fx) = std::forward(arg); + } } struct caller { @@ -15219,6 +15244,189 @@ namespace function_detail { // beginning of sol/call.hpp +// beginning of sol/property.hpp + +// beginning of sol/ebco.hpp + +namespace sol { + + template + struct ebco { + T value; + + ebco() = default; + ebco(const ebco&) = default; + ebco(ebco&&) = default; + ebco& operator=(const ebco&) = default; + ebco& operator=(ebco&&) = default; + ebco(const T& v) : value(v){}; + ebco(T&& v) : value(std::move(v)){}; + ebco& operator=(const T& v) { + value = v; + } + ebco& operator=(T&& v) { + value = std::move(v); + }; + template >, + ebco> && !std::is_same_v>, T>>> + ebco(Arg&& arg, Args&&... args) : T(std::forward(arg), std::forward(args)...){}; + + T& get_value() { + return value; + } + + T const& get_value() const { + return value; + } + }; + + template + struct ebco && !std::is_final_v>> : T { + ebco() = default; + ebco(const ebco&) = default; + ebco(ebco&&) = default; + ebco(const T& v) : T(v){}; + ebco(T&& v) : T(std::move(v)){}; + template >, + ebco> && !std::is_same_v>, T>>> + ebco(Arg&& arg, Args&&... args) : T(std::forward(arg), std::forward(args)...){}; + + ebco& operator=(const ebco&) = default; + ebco& operator=(ebco&&) = default; + ebco& operator=(const T& v) { + static_cast(*this) = v; + } + ebco& operator=(T&& v) { + static_cast(*this) = std::move(v); + }; + + T& get_value() { + return static_cast(*this); + } + + T const& get_value() const { + return static_cast(*this); + } + }; + +} // namespace sol + +// end of sol/ebco.hpp + +namespace sol { + namespace detail { + struct no_prop {}; + } + + template + struct property_wrapper : ebco, ebco { + template + property_wrapper(Rx&& r, Wx&& w) + : ebco(std::forward(r)), ebco(std::forward(w)) { + } + + W& write() { + return ebco::get_value(); + } + + const W& write() const { + return ebco::get_value(); + } + + R& read() { + return ebco::get_value(); + } + + const R& read() const { + return ebco::get_value(); + } + }; + + template + inline decltype(auto) property(F&& f, G&& g) { + typedef lua_bind_traits> left_traits; + typedef lua_bind_traits> right_traits; + if constexpr (left_traits::free_arity < right_traits::free_arity) { + return property_wrapper, std::decay_t>(std::forward(f), std::forward(g)); + } + else { + return property_wrapper, std::decay_t>(std::forward(g), std::forward(f)); + } + } + + template + inline decltype(auto) property(F&& f) { + typedef lua_bind_traits> left_traits; + if constexpr (left_traits::free_arity < 2) { + return property_wrapper, detail::no_prop>(std::forward(f), detail::no_prop()); + } + else { + return property_wrapper>(detail::no_prop(), std::forward(f)); + } + } + + template + inline decltype(auto) readonly_property(F&& f) { + return property_wrapper, detail::no_prop>(std::forward(f), detail::no_prop()); + } + + template + inline decltype(auto) writeonly_property(F&& f) { + return property_wrapper>(detail::no_prop(), std::forward(f)); + } + + template + struct readonly_wrapper : ebco { + private: + using base_t = ebco; + public: + using base_t::base_t; + + operator T&() { + return base_t::get_value(); + } + operator const T&() const { + return base_t::get_value(); + } + }; + + // Allow someone to make a member variable readonly (const) + template + inline auto readonly(R T::*v) { + return readonly_wrapper>(v); + } + + template + struct var_wrapper : ebco { + private: + using base_t = ebco; + public: + using base_t::base_t; + }; + + template + inline auto var(V&& v) { + typedef meta::unqualified_t T; + return var_wrapper(std::forward(v)); + } + + namespace meta { + template + struct is_member_object : std::is_member_object_pointer {}; + + template + struct is_member_object> : std::true_type {}; + + template + inline constexpr bool is_member_object_v = is_member_object::value; + } // namespace meta + +} // namespace sol + +// end of sol/property.hpp + // beginning of sol/protect.hpp namespace sol { @@ -15247,125 +15455,6 @@ namespace sol { // end of sol/protect.hpp -// beginning of sol/property.hpp - -namespace sol { - - struct no_prop {}; - - template - struct property_wrapper { - typedef std::integral_constant::value> can_read; - typedef std::integral_constant::value> can_write; - typedef std::conditional_t Read; - typedef std::conditional_t Write; - Read read; - Write write; - - template - property_wrapper(Rx&& r, Wx&& w) - : read(std::forward(r)), write(std::forward(w)) { - } - }; - - namespace property_detail { - template - inline decltype(auto) property(std::true_type, R&& read, W&& write) { - return property_wrapper, std::decay_t>(std::forward(read), std::forward(write)); - } - template - inline decltype(auto) property(std::false_type, W&& write, R&& read) { - return property_wrapper, std::decay_t>(std::forward(read), std::forward(write)); - } - template - inline decltype(auto) property(std::true_type, R&& read) { - return property_wrapper, void>(std::forward(read), no_prop()); - } - template - inline decltype(auto) property(std::false_type, W&& write) { - return property_wrapper>(no_prop(), std::forward(write)); - } - } // namespace property_detail - - template - inline decltype(auto) property(F&& f, G&& g) { - typedef lua_bind_traits> left_traits; - typedef lua_bind_traits> right_traits; - return property_detail::property(meta::boolean<(left_traits::free_arity < right_traits::free_arity)>(), std::forward(f), std::forward(g)); - } - - template - inline decltype(auto) property(F&& f) { - typedef lua_bind_traits> left_traits; - return property_detail::property(meta::boolean<(left_traits::free_arity < 2)>(), std::forward(f)); - } - - template - inline decltype(auto) readonly_property(F&& f) { - return property_detail::property(std::true_type(), std::forward(f)); - } - - template - inline decltype(auto) writeonly_property(F&& f) { - return property_detail::property(std::false_type(), std::forward(f)); - } - - template - struct readonly_wrapper { - T v; - - readonly_wrapper(T v) - : v(std::move(v)) { - } - - operator T&() { - return v; - } - operator const T&() const { - return v; - } - }; - - // Allow someone to make a member variable readonly (const) - template - inline auto readonly(R T::*v) { - return readonly_wrapper>(v); - } - - template - struct var_wrapper { - T value; - template - var_wrapper(Args&&... args) - : value(std::forward(args)...) { - } - var_wrapper(const var_wrapper&) = default; - var_wrapper(var_wrapper&&) = default; - var_wrapper& operator=(const var_wrapper&) = default; - var_wrapper& operator=(var_wrapper&&) = default; - }; - - template - inline auto var(V&& v) { - typedef meta::unqualified_t T; - return var_wrapper(std::forward(v)); - } - - namespace meta { - template - struct is_member_object : std::is_member_object_pointer {}; - - template - struct is_member_object> : std::true_type {}; - - template - inline constexpr bool is_member_object_v = is_member_object::value; - } // namespace meta - -} // namespace sol - -// end of sol/property.hpp - namespace sol { namespace u_detail { @@ -15374,31 +15463,34 @@ namespace sol { namespace filter_detail { template inline void handle_filter(static_stack_dependencies, lua_State* L, int&) { - if (sizeof...(In) == 0) { + if constexpr (sizeof...(In) == 0) { + (void)L; return; } - absolute_index ai(L, I); - if (type_of(L, ai) != type::userdata) { - return; - } - lua_createtable(L, static_cast(sizeof...(In)), 0); - stack_reference deps(L, -1); - auto per_dep = [&L, &deps](int i) { + else { + absolute_index ai(L, I); + if (type_of(L, ai) != type::userdata) { + return; + } + lua_createtable(L, static_cast(sizeof...(In)), 0); + stack_reference deps(L, -1); + auto per_dep = [&L, &deps](int i) { #if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK - luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); #endif // make sure stack doesn't overflow - lua_pushvalue(L, i); - luaL_ref(L, deps.stack_index()); - }; - (void)per_dep; - (void)detail::swallow { int(), (per_dep(In), int())... }; - lua_setuservalue(L, ai); + lua_pushvalue(L, i); + luaL_ref(L, deps.stack_index()); + }; + (void)per_dep; + (void)detail::swallow{ int(), (per_dep(In), int())... }; + lua_setuservalue(L, ai); + } } template inline void handle_filter(returns_self_with, lua_State* L, int& pushed) { pushed = stack::push(L, raw_index(1)); - handle_filter(static_stack_dependencies< -1, In...>(), L, pushed); + handle_filter(static_stack_dependencies<-1, In...>(), L, pushed); } inline void handle_filter(const stack_dependencies& sdeps, lua_State* L, int&) { @@ -15434,12 +15526,12 @@ namespace sol { template inline auto& pick(std::true_type, property_wrapper& f) { - return f.read; + return f.read(); } template inline auto& pick(std::false_type, property_wrapper& f) { - return f.write; + return f.write(); } template @@ -15455,13 +15547,12 @@ namespace sol { struct constructor_match { T* obj_; - constructor_match(T* o) - : obj_(o) { + constructor_match(T* o) : obj_(o) { } template int operator()(types, meta::index_value, types r, types a, lua_State* L, int, int start) const { - detail::default_construct func {}; + detail::default_construct func{}; return stack::call_into_lua(r, a, L, start, func, obj_); } }; @@ -15473,67 +15564,153 @@ namespace sol { } template - inline int overload_match_arity(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits> traits; - typedef meta::tuple_types 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 (!traits::runtime_variadics_t::value && meta::find_in_pack_v, meta::index_value...>::value) { - return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); - } - if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { - return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); - } - stack::record tracking {}; - if (!stack::stack_detail::check_types {}.check(args_list(), L, start, no_panic, tracking)) { - return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); - } - return matchfx(types(), meta::index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); - } - - template - inline int overload_match_arity_single(types<>, std::index_sequence<>, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); - } - - template - inline int overload_match_arity_single(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + inline int overload_match_arity(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, + int fxarity, int start, Args&&... args) { typedef lua_bind_traits> traits; typedef meta::tuple_types 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 constexpr (!traits::runtime_variadics_t::value && meta::find_in_pack_v, meta::index_value...>::value) { - return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + return overload_match_arity(types(), + std::index_sequence(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); } - if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { - return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + else { + if constexpr (!traits::runtime_variadics_t::value) { + if (traits::free_arity != fxarity) { + return overload_match_arity(types(), + std::index_sequence(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); + } + } + stack::record tracking{}; + stack::stack_detail::check_types ct{}; + if (!ct.check(args_list(), L, start, no_panic, tracking)) { + return overload_match_arity(types(), + std::index_sequence(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); + } + return matchfx(types(), meta::index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); } - return matchfx(types(), meta::index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); } - template - inline int overload_match_arity_single(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + template + inline int overload_match_arity_single( + types<>, std::index_sequence<>, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + return overload_match_arity(types<>(), + std::index_sequence<>(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); + } + + template + inline int overload_match_arity_single( + types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { typedef lua_bind_traits> traits; typedef meta::tuple_types 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 (!traits::runtime_variadics_t::value && meta::find_in_pack_v, meta::index_value...>::value) { - return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + if constexpr (!traits::runtime_variadics_t::value + && meta::find_in_pack_v, meta::index_value...>::value) { + return overload_match_arity(types<>(), + std::index_sequence<>(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); } if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { - return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); - } - stack::record tracking {}; - if (!stack::stack_detail::check_types {}.check(args_list(), L, start, no_panic, tracking)) { - return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + return overload_match_arity(types<>(), + std::index_sequence<>(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); } return matchfx(types(), meta::index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); } + + template + inline int overload_match_arity_single(types, std::index_sequence, std::index_sequence, Match&& matchfx, + lua_State* L, int fxarity, int start, Args&&... args) { + typedef lua_bind_traits> traits; + typedef meta::tuple_types 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 constexpr (!traits::runtime_variadics_t::value && meta::find_in_pack_v, meta::index_value...>::value) { + return overload_match_arity(types(), + std::index_sequence(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); + } + else { + if constexpr (!traits::runtime_variadics_t::value) { + if (traits::free_arity != fxarity) { + return overload_match_arity(types(), + std::index_sequence(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); + } + } + stack::record tracking{}; + stack::stack_detail::check_types ct{}; + if (!ct.check(args_list(), L, start, no_panic, tracking)) { + return overload_match_arity(types(), + std::index_sequence(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); + } + return matchfx(types(), meta::index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); + } + } } // namespace overload_detail template inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - return overload_detail::overload_match_arity_single(types(), std::make_index_sequence(), std::index_sequence<>(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + return overload_detail::overload_match_arity_single(types(), + std::make_index_sequence(), + std::index_sequence<>(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); } template @@ -15545,7 +15722,8 @@ namespace sol { template inline int construct_match(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::call)...>(std::forward(matchfx), L, fxarity, start, std::forward(args)...); + return overload_match_arity::call)...>( + std::forward(matchfx), L, fxarity, start, std::forward(args)...); } template @@ -15565,7 +15743,7 @@ namespace sol { stack::stack_detail::undefined_metatable umf(L, &meta[0]); umf(); - return 1; + return 1; } template @@ -15575,88 +15753,69 @@ namespace sol { template struct agnostic_lua_call_wrapper { - typedef wrapper> wrap; - - template - 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 {}.call(L, fx, std::forward(args)...); - } - - template - 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(returns_list(), args_list(), L, boost + 1, caller(), std::forward(f), std::forward(args)...); - } + using wrap = wrapper>; template 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>::value, std::is_convertible, fp_t>, std::false_type>(), L, std::forward(f), std::forward(args)...); - } - }; - - template - struct agnostic_lua_call_wrapper::value>> { - template - static int call(lua_State* L, Fx&& f, Args&&... args) { - if constexpr(is_index) { - return stack::push(L, std::forward(f), std::forward(args)...); + if constexpr(is_lua_reference_v>) { + if constexpr (is_index) { + return stack::push(L, std::forward(f), std::forward(args)...); + } + else { + std::forward(f) = stack::unqualified_get(L, boost + (is_variable ? 3 : 1)); + return 0; + } } else { - std::forward(f) = stack::unqualified_get(L, boost + (is_variable ? 3 : 1)); - return 0; + using traits_type = typename wrap::traits_type; + using fp_t = typename traits_type::function_pointer_type; + constexpr bool is_function_pointer_convertible + = std::is_class_v> && std::is_convertible_v, fp_t>; + if constexpr (is_function_pointer_convertible) { + fp_t fx = f; + return agnostic_lua_call_wrapper{}.call( + L, fx, std::forward(args)...); + } + else { + using returns_list = typename wrap::returns_list; + using args_list = typename wrap::free_args_list; + using caller = typename wrap::caller; + return stack::call_into_lua( + returns_list(), args_list(), L, boost + 1, caller(), std::forward(f), std::forward(args)...); + } } } }; - template - struct agnostic_lua_call_wrapper, true, is_variable, checked, boost, clean_stack, C> { + template + struct agnostic_lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack, C> { template static int call(lua_State* L, F&& f) { - typedef is_stack_based> is_stack; - if (clean_stack && !is_stack::value) { - lua_settop(L, 0); + if constexpr (is_index) { + constexpr bool is_stack = is_stack_based_v>; + if constexpr (clean_stack && !is_stack) { + lua_settop(L, 0); + } + return stack::push_reference(L, detail::unwrap(f.get_value())); } - return stack::push_reference(L, detail::unwrap(f.value)); - } - }; - - template - struct agnostic_lua_call_wrapper, false, is_variable, checked, boost, clean_stack, C> { - template - static int call_assign(std::true_type, lua_State* L, V&& f) { - detail::unwrap(f.value) = stack::unqualified_get>(L, boost + (is_variable ? 3 : 1)); - if (clean_stack) { - lua_settop(L, 0); + else { + if constexpr (std::is_const_v>) { + return luaL_error(L, "sol: cannot write to a readonly (const) variable"); + } + else { + using R = meta::unwrapped_t; + if constexpr (std::is_assignable_v>, R>) { + detail::unwrap(f.get_value()) = stack::unqualified_get>(L, boost + (is_variable ? 3 : 1)); + if (clean_stack) { + lua_settop(L, 0); + } + return 0; + } + else { + return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); + } + } } - return 0; - } - - template - static int call_assign(std::false_type, lua_State* L, Args&&...) { - return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); - } - - template - static int call_const(std::false_type, lua_State* L, Args&&... args) { - typedef meta::unwrapped_t R; - return call_assign(std::is_assignable>, R>(), L, std::forward(args)...); - } - - template - static int call_const(std::true_type, lua_State* L, Args&&...) { - return luaL_error(L, "sol: cannot write to a readonly (const) variable"); - } - - template - static int call(lua_State* L, V&& f) { - return call_const(std::is_const>(), L, f); } }; @@ -15684,8 +15843,8 @@ namespace sol { #endif // noexcept function types template - struct agnostic_lua_call_wrapper { - static int call(lua_State* L, const no_prop&) { + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, const detail::no_prop&) { return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property"); } }; @@ -15708,119 +15867,121 @@ namespace sol { template struct agnostic_lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack, C> { static int call(lua_State* L, std::reference_wrapper f) { - return agnostic_lua_call_wrapper {}.call(L, f.get()); + agnostic_lua_call_wrapper alcw{}; + return alcw.call(L, f.get()); } }; - template - struct lua_call_wrapper : agnostic_lua_call_wrapper {}; - - template - struct lua_call_wrapper::value>> { - typedef wrapper> wrap; - typedef typename wrap::object_type object_type; - - template - static int call(lua_State* L, Fx&& f, object_type& o) { - typedef typename wrap::returns_list returns_list; - typedef typename wrap::args_list args_list; - typedef typename wrap::caller caller; - return stack::call_into_lua(returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward(f), o); - } - - template - static int call(lua_State* L, Fx&& f) { - typedef std::conditional_t::value, object_type, T> Ta; + template + struct lua_call_wrapper { + template + static int call(lua_State* L, Fx&& fx, Args&&... args) { + if constexpr (std::is_member_function_pointer_v) { + using wrap = wrapper; + using object_type = typename wrap::object_type; + if constexpr (sizeof...(Args) < 1) { + using Ta = std::conditional_t, object_type, T>; #if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE - auto maybeo = stack::unqualified_check_get(L, 1); - if (!maybeo || maybeo.value() == nullptr) { - return luaL_error(L, "sol: received nil for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)"); - } - object_type* o = static_cast(maybeo.value()); - return call(L, std::forward(f), *o); + auto maybeo = stack::check_get(L, 1); + if (!maybeo || maybeo.value() == nullptr) { + return luaL_error(L, + "sol: received nil for 'self' argument (use ':' for accessing member functions, make sure member variables are " + "preceeded by the " + "actual object with '.' syntax)"); + } + object_type* o = static_cast(maybeo.value()); + return call(L, std::forward(fx), *o); #else - object_type& o = static_cast(*stack::unqualified_get>(L, 1)); - return call(L, std::forward(f), o); + object_type& o = static_cast(*stack::unqualified_get>(L, 1)); + return call(L, std::forward(fx), o); #endif // Safety - } - }; - - template - struct lua_call_wrapper::value>> { - typedef lua_bind_traits traits_type; - typedef wrapper> wrap; - typedef typename wrap::object_type object_type; - - template - static int call_assign(std::true_type, lua_State* L, V&& f, object_type& o) { - typedef typename wrap::args_list args_list; - typedef typename wrap::caller caller; - return stack::call_into_lua(types(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), f, o); - } - - template - static int call_assign(std::true_type, lua_State* L, V&& f) { - typedef std::conditional_t::value, object_type, T> Ta; -#if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE - auto maybeo = stack::check_get(L, 1); - if (!maybeo || maybeo.value() == 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)"); + else { + using returns_list = typename wrap::returns_list; + using args_list = typename wrap::args_list; + using caller = typename wrap::caller; + return stack::call_into_lua( + returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward(fx), std::forward(args)...); + } } - object_type* o = static_cast(maybeo.value()); - return call_assign(std::true_type(), L, f, *o); + else if constexpr (std::is_member_object_pointer_v) { + using traits_type = lua_bind_traits; + using wrap = wrapper; + using object_type = typename wrap::object_type; + using return_type = typename traits_type::return_type; + constexpr bool is_const = std::is_const_v>; + if constexpr (is_const) { + (void)fx; + (void)detail::swallow{ 0, (static_cast(args), 0)... }; + return luaL_error(L, "sol: cannot write to a readonly (const) variable"); + } + else { + using u_return_type = meta::unqualified_t; + constexpr bool is_assignable = std::is_copy_assignable_v || std::is_array_v; + if constexpr (!is_assignable) { + (void)fx; + (void)detail::swallow{ 0, ((void)args, 0)... }; + return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); + } + else { + using args_list = typename wrap::args_list; + using caller = typename wrap::caller; + if constexpr (sizeof...(Args) > 0) { + return stack::call_into_lua(types(), + args_list(), + L, + boost + (is_variable ? 3 : 2), + caller(), + std::forward(fx), + std::forward(args)...); + } + else { + using Ta = std::conditional_t, object_type, T>; +#if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE + auto maybeo = stack::check_get(L, 1); + if (!maybeo || maybeo.value() == 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)"); + } + object_type* po = static_cast(maybeo.value()); + object_type& o = *po; #else - object_type& o = static_cast(*stack::get>(L, 1)); - return call_assign(std::true_type(), L, f, o); + object_type& o = static_cast(*stack::get>(L, 1)); #endif // Safety - } - template - static int call_assign(std::false_type, lua_State* L, Args&&...) { - return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); - } - - template - static int call_const(std::false_type, lua_State* L, Args&&... args) { - typedef typename traits_type::return_type R; - return call_assign(std::is_copy_assignable>(), L, std::forward(args)...); - } - - template - static int call_const(std::true_type, lua_State* L, Args&&...) { - return luaL_error(L, "sol: cannot write to a readonly (const) variable"); - } - - template - static int call(lua_State* L, V&& f) { - return call_const(std::is_const(), L, std::forward(f)); - } - - template - static int call(lua_State* L, V&& f, object_type& o) { - return call_const(std::is_const(), L, std::forward(f), o); + return stack::call_into_lua( + types(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward(fx), o); + } + } + } + } + else { + agnostic_lua_call_wrapper alcw{}; + return alcw.call(L, std::forward(fx), std::forward(args)...); + } } }; template struct lua_call_wrapper::value>> { - typedef lua_bind_traits traits_type; - typedef wrapper> wrap; - typedef typename wrap::object_type object_type; + using traits_type = lua_bind_traits; + using wrap = wrapper; + using object_type = typename wrap::object_type; template static int call(lua_State* L, V&& v, object_type& o) { - typedef typename wrap::returns_list returns_list; - typedef typename wrap::caller caller; + using returns_list = typename wrap::returns_list; + using caller = typename wrap::caller; F f(std::forward(v)); return stack::call_into_lua(returns_list(), types<>(), L, boost + (is_variable ? 3 : 2), caller(), f, o); } template static int call(lua_State* L, V&& f) { - typedef std::conditional_t::value, object_type, T> Ta; + using Ta = std::conditional_t::value, object_type, T>; #if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE auto maybeo = stack::check_get(L, 1); if (!maybeo || maybeo.value() == nullptr) { @@ -15840,23 +16001,68 @@ namespace sol { template struct lua_call_wrapper, false, is_variable, checked, boost, clean_stack, C> { - typedef lua_bind_traits traits_type; - typedef wrapper> wrap; - typedef typename wrap::object_type object_type; + using traits_type = lua_bind_traits; + using wrap = wrapper; + using object_type = typename wrap::object_type; - template - static int call(lua_State* L, V&&) { + static int call(lua_State* L, const readonly_wrapper&) { return luaL_error(L, "sol: cannot write to a sol::readonly variable"); } - template - static int call(lua_State* L, V&&, object_type&) { - return luaL_error(L, "sol: cannot write to a sol::readonly variable"); + static int call(lua_State* L, const readonly_wrapper& rw, object_type&) { + return call(L, rw); } }; - template - struct lua_call_wrapper, true, is_variable, checked, boost, clean_stack, C> : lua_call_wrapper { + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack, C> { + using traits_type = lua_bind_traits; + using wrap = wrapper; + using object_type = typename wrap::object_type; + + static int call(lua_State* L, readonly_wrapper&& rw) { + if constexpr (!is_index) { + (void)rw; + return luaL_error(L, "sol: cannot write to a sol::readonly variable"); + } + else { + lua_call_wrapper lcw; + return lcw.call(L, std::move(rw.get_value()), o); + } + } + + static int call(lua_State* L, readonly_wrapper&& rw, object_type& o) { + if constexpr (!is_index) { + (void)o; + return call(L, std::move(rw)); + } + else { + lua_call_wrapper lcw; + return lcw.call(L, rw.get_value(), o); + } + } + + static int call(lua_State* L, const readonly_wrapper& rw) { + if constexpr (!is_index) { + (void)rw; + return luaL_error(L, "sol: cannot write to a sol::readonly variable"); + } + else { + lua_call_wrapper lcw; + return lcw.call(L, rw.get_value()); + } + } + + static int call(lua_State* L, const readonly_wrapper& rw, object_type& o) { + if constexpr (!is_index) { + (void)o; + return call(L, rw); + } + else { + lua_call_wrapper lcw; + return lcw.call(L, rw.get_value(), o); + } + } }; template @@ -15912,37 +16118,29 @@ namespace sol { } }; - template - struct lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack, std::enable_if_t::value>> { + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack, C> { typedef destructor_wrapper F; - static int call(lua_State* L, const F&) { - return detail::usertype_alloc_destruct(L); - } - }; - - template - struct lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack, std::enable_if_t::value>> { - typedef destructor_wrapper F; - - static int call_void(std::true_type, lua_State* L, const F& f) { - typedef meta::bind_traits> bt; - typedef typename bt::template arg_at<0> arg0; - typedef meta::unqualified_t O; - - O& obj = stack::get(L); - f.fx(detail::implicit_wrapper(obj)); - return 0; - } - - static int call_void(std::false_type, lua_State* L, const F& f) { - T& obj = stack::get(L); - f.fx(detail::implicit_wrapper(obj)); - return 0; - } - static int call(lua_State* L, const F& f) { - return call_void(std::is_void(), L, f); + if constexpr (std::is_void_v) { + return detail::usertype_alloc_destruct(L); + } + else { + if constexpr (std::is_void_v) { + using bt = meta::bind_traits>; + using arg0_t = typename bt::template arg_at<0>; + + decltype(auto) obj = stack::get(L, -1); + f.fx(detail::implicit_wrapper>(obj)); + return 0; + } + else { + T& obj = stack::get(L, -1); + f.fx(detail::implicit_wrapper(obj)); + return 0; + } + } } }; @@ -15954,7 +16152,7 @@ namespace sol { template int operator()(types, meta::index_value, types, types, lua_State* L, int, int, F& fx) { auto& f = std::get(fx.functions); - return lua_call_wrapper {}.call(L, f); + return lua_call_wrapper{}.call(L, f); } }; @@ -15971,7 +16169,7 @@ namespace sol { template int operator()(types, meta::index_value, types, types, lua_State* L, int, int, F& fx) { auto& f = std::get(fx.functions); - return lua_call_wrapper {}.call(L, f); + return lua_call_wrapper{}.call(L, f); } }; @@ -15988,59 +16186,75 @@ namespace sol { typedef lua_bind_traits traits_type; typedef meta::unqualified_t> object_type; - template - static int self_call(std::true_type, lua_State* L, F&& f) { - // The type being void means we don't have any arguments, so it might be a free functions? - typedef typename traits_type::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, boost + (is_variable ? 3 : 2), caller(), f); - } - - template - static int self_call(std::false_type, lua_State* L, F&& f) { - typedef meta::pop_front_type_t args_list; - typedef T Ta; - typedef std::remove_pointer_t Oa; -#if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE - auto maybeo = stack::check_get(L, 1); - if (!maybeo || maybeo.value() == nullptr) { - if (is_variable) { - return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)"); - } - return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)"); - } - Oa* o = static_cast(maybeo.value()); -#else - Oa* o = static_cast(stack::get>(L, 1)); -#endif // Safety - typedef typename wrap::returns_list returns_list; - typedef typename wrap::caller caller; - return stack::call_into_lua(returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), f, detail::implicit_wrapper(*o)); - } - - template - static int defer_call(std::false_type, lua_State* L, F&& f, Args&&... args) { - return self_call(meta::any, meta::boolean>::value != type::userdata>>(), L, pick(meta::boolean(), f), std::forward(args)...); - } - - template - static int defer_call(std::true_type, lua_State* L, F&& f, Args&&... args) { - auto& p = pick(meta::boolean(), std::forward(f)); - return lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack> {}.call(L, p, std::forward(args)...); - } - template static int call(lua_State* L, F&& f, Args&&... args) { - typedef meta::any< - std::is_void, - std::is_same, - meta::is_specialization_of, - meta::is_specialization_of, - meta::is_specialization_of, - std::is_member_pointer> - is_specialized; - return defer_call(is_specialized(), L, std::forward(f), std::forward(args)...); + constexpr bool is_specialized = meta::any< + std::is_same, + meta::is_specialization_of, + meta::is_specialization_of, + meta::is_specialization_of, + std::is_member_pointer>::value; + if constexpr (is_specialized) { + if constexpr (is_index) { + decltype(auto) p = f.read(); + lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack> lcw{}; + return lcw.call(L, p, std::forward(args)...); + } + else { + decltype(auto) p = f.write(); + lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack> lcw{}; + return lcw.call(L, p, std::forward(args)...); + } + } + else { + constexpr bool non_class_object_type = meta::any, + meta::boolean>::value != type::userdata>>::value; + if constexpr (non_class_object_type) { + // The type being void means we don't have any arguments, so it might be a free functions? + using args_list = typename traits_type::free_args_list; + using returns_list = typename wrap::returns_list; + using caller = typename wrap::caller; + if constexpr (is_index) { + decltype(auto) pf = f.read(); + return stack::call_into_lua( + returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf); + } + else { + decltype(auto) pf = f.write(); + return stack::call_into_lua( + returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf); + } + } + else { + using args_list = meta::pop_front_type_t; + using Ta = T; + using Oa = std::remove_pointer_t; +#if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE + auto maybeo = stack::check_get(L, 1); + if (!maybeo || maybeo.value() == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)"); + } + return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)"); + } + Oa* o = static_cast(maybeo.value()); +#else + Oa* o = static_cast(stack::get>(L, 1)); +#endif // Safety + using returns_list = typename wrap::returns_list; + using caller = typename wrap::caller; + if constexpr (is_index) { + decltype(auto) pf = f.read(); + return stack::call_into_lua( + returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf, detail::implicit_wrapper(*o)); + } + else { + decltype(auto) pf = f.write(); + return stack::call_into_lua( + returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf, detail::implicit_wrapper(*o)); + } + } + } } }; @@ -16050,7 +16264,7 @@ namespace sol { template static int call(lua_State* L, F& fx, Args&&... args) { - return lua_call_wrapper {}.call(L, fx.value, std::forward(args)...); + return lua_call_wrapper{}.call(L, fx.value, std::forward(args)...); } }; @@ -16060,8 +16274,8 @@ namespace sol { template static int call(std::index_sequence, lua_State* L, P& fx) { - int pushed = lua_call_wrapper {}.call(L, fx.value); - (void)detail::swallow { int(), (filter_detail::handle_filter(std::get(fx.filters), L, pushed), int())... }; + int pushed = lua_call_wrapper{}.call(L, fx.value); + (void)detail::swallow{ int(), (filter_detail::handle_filter(std::get(fx.filters), L, pushed), int())... }; return pushed; } @@ -16081,24 +16295,30 @@ namespace sol { template struct lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack, C> { - template - static int call(lua_State* L, F&& f) { - return lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack>{}.call(L, std::get<0>(f.arguments)); + static int call(lua_State* L, const function_arguments& f) { + lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack> lcw{}; + return lcw.call(L, std::get<0>(f.arguments)); + } + + static int call(lua_State* L, function_arguments&& f) { + lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack> lcw{}; + return lcw.call(L, std::get<0>(std::move(f.arguments))); } }; - template + template inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) { using uFx = meta::unqualified_t; - if constexpr(meta::is_specialization_of_v) { + if constexpr (meta::is_specialization_of_v) { using real_fx = meta::unqualified_t(fx).func)>; - int nr = lua_call_wrapper{}.call( - L, std::forward(fx).func, std::forward(args)...); + lua_call_wrapper lcw{}; + int nr = lcw.call(L, std::forward(fx).func, std::forward(args)...); return lua_yield(L, nr); } else { - return lua_call_wrapper{}.call( - L, std::forward(fx), std::forward(args)...); + lua_call_wrapper lcw{}; + return lcw.call(L, std::forward(fx), std::forward(args)...); } } @@ -16118,7 +16338,7 @@ namespace sol { struct is_var_bind::value>> : std::true_type {}; template <> - struct is_var_bind : std::true_type {}; + struct is_var_bind : std::true_type {}; template struct is_var_bind> : std::true_type {}; @@ -16260,8 +16480,9 @@ namespace sol { template inline int c_call(lua_State* L) { - if (sizeof...(Fxs) < 2) { - return meta::at_in_pack_t<0, Fxs...>::call(L); + if constexpr (sizeof...(Fxs) < 2) { + using target = meta::at_in_pack_t<0, Fxs...>; + return target::call(L); } else { return call_detail::overload_match_arity(function_detail::c_call_matcher(), L, lua_gettop(L), 1); @@ -16929,6 +17150,7 @@ namespace sol { using dFx = std::decay_t; using Tu = meta::unqualified_t; if constexpr (meta::is_specialization_of_v) { + (void)obj; using C = typename Tu::type; lua_CFunction freefunc = &function_detail::upvalue_this_member_function::call; @@ -16951,7 +17173,7 @@ namespace sol { } else { using F = function_detail::member_function; - select_set_fx(L, std::forward(fx), std::forward(args)...); + select_set_fx(L, std::forward(fx), std::forward(obj), std::forward(args)...); } } } @@ -22658,85 +22880,86 @@ namespace sol { luaL_openlibs(L); return; } + else { + lib libraries[1 + sizeof...(args)] = { lib::count, std::forward(args)... }; - lib libraries[1 + sizeof...(args)] = { lib::count, std::forward(args)... }; - - for (auto&& library : libraries) { - switch (library) { -#if SOL_LUA_VERSION <= 501 && defined(SOL_LUAJIT) - case lib::coroutine: -#endif // luajit opens coroutine base stuff - case lib::base: - luaL_requiref(L, "base", luaopen_base, 1); - lua_pop(L, 1); - break; - case lib::package: - luaL_requiref(L, "package", luaopen_package, 1); - lua_pop(L, 1); - break; -#if !defined(SOL_LUAJIT) - case lib::coroutine: -#if SOL_LUA_VERSION > 501 - luaL_requiref(L, "coroutine", luaopen_coroutine, 1); - lua_pop(L, 1); -#endif // Lua 5.2+ only - break; -#endif // Not LuaJIT - comes builtin - case lib::string: - luaL_requiref(L, "string", luaopen_string, 1); - lua_pop(L, 1); - break; - case lib::table: - luaL_requiref(L, "table", luaopen_table, 1); - lua_pop(L, 1); - break; - case lib::math: - luaL_requiref(L, "math", luaopen_math, 1); - lua_pop(L, 1); - break; - case lib::bit32: -#ifdef SOL_LUAJIT - luaL_requiref(L, "bit32", luaopen_bit, 1); - lua_pop(L, 1); -#elif (SOL_LUA_VERSION == 502) || defined(LUA_COMPAT_BITLIB) || defined(LUA_COMPAT_5_2) - luaL_requiref(L, "bit32", luaopen_bit32, 1); - lua_pop(L, 1); -#else -#endif // Lua 5.2 only (deprecated in 5.3 (503)) (Can be turned on with Compat flags) - break; - case lib::io: - luaL_requiref(L, "io", luaopen_io, 1); - lua_pop(L, 1); - break; - case lib::os: - luaL_requiref(L, "os", luaopen_os, 1); - lua_pop(L, 1); - break; - case lib::debug: - luaL_requiref(L, "debug", luaopen_debug, 1); - lua_pop(L, 1); - break; - case lib::utf8: -#if SOL_LUA_VERSION > 502 && !defined(SOL_LUAJIT) - luaL_requiref(L, "utf8", luaopen_utf8, 1); - lua_pop(L, 1); -#endif // Lua 5.3+ only - break; - case lib::ffi: -#ifdef SOL_LUAJIT - luaL_requiref(L, "ffi", luaopen_ffi, 1); - lua_pop(L, 1); -#endif // LuaJIT only - break; - case lib::jit: -#ifdef SOL_LUAJIT - luaL_requiref(L, "jit", luaopen_jit, 0); - lua_pop(L, 1); -#endif // LuaJIT Only - break; - case lib::count: - default: - break; + for (auto&& library : libraries) { + switch (library) { + #if SOL_LUA_VERSION <= 501 && defined(SOL_LUAJIT) + case lib::coroutine: + #endif // luajit opens coroutine base stuff + case lib::base: + luaL_requiref(L, "base", luaopen_base, 1); + lua_pop(L, 1); + break; + case lib::package: + luaL_requiref(L, "package", luaopen_package, 1); + lua_pop(L, 1); + break; + #if !defined(SOL_LUAJIT) + case lib::coroutine: + #if SOL_LUA_VERSION > 501 + luaL_requiref(L, "coroutine", luaopen_coroutine, 1); + lua_pop(L, 1); + #endif // Lua 5.2+ only + break; + #endif // Not LuaJIT - comes builtin + case lib::string: + luaL_requiref(L, "string", luaopen_string, 1); + lua_pop(L, 1); + break; + case lib::table: + luaL_requiref(L, "table", luaopen_table, 1); + lua_pop(L, 1); + break; + case lib::math: + luaL_requiref(L, "math", luaopen_math, 1); + lua_pop(L, 1); + break; + case lib::bit32: + #ifdef SOL_LUAJIT + luaL_requiref(L, "bit32", luaopen_bit, 1); + lua_pop(L, 1); + #elif (SOL_LUA_VERSION == 502) || defined(LUA_COMPAT_BITLIB) || defined(LUA_COMPAT_5_2) + luaL_requiref(L, "bit32", luaopen_bit32, 1); + lua_pop(L, 1); + #else + #endif // Lua 5.2 only (deprecated in 5.3 (503)) (Can be turned on with Compat flags) + break; + case lib::io: + luaL_requiref(L, "io", luaopen_io, 1); + lua_pop(L, 1); + break; + case lib::os: + luaL_requiref(L, "os", luaopen_os, 1); + lua_pop(L, 1); + break; + case lib::debug: + luaL_requiref(L, "debug", luaopen_debug, 1); + lua_pop(L, 1); + break; + case lib::utf8: + #if SOL_LUA_VERSION > 502 && !defined(SOL_LUAJIT) + luaL_requiref(L, "utf8", luaopen_utf8, 1); + lua_pop(L, 1); + #endif // Lua 5.3+ only + break; + case lib::ffi: + #ifdef SOL_LUAJIT + luaL_requiref(L, "ffi", luaopen_ffi, 1); + lua_pop(L, 1); + #endif // LuaJIT only + break; + case lib::jit: + #ifdef SOL_LUAJIT + luaL_requiref(L, "jit", luaopen_jit, 0); + lua_pop(L, 1); + #endif // LuaJIT Only + break; + case lib::count: + default: + break; + } } } } diff --git a/tests/compile_tests/CMakeLists.txt b/tests/compile_tests/CMakeLists.txt index 8efc3a2a..6feb8821 100644 --- a/tests/compile_tests/CMakeLists.txt +++ b/tests/compile_tests/CMakeLists.txt @@ -49,19 +49,18 @@ function(CREATE_TEST test_target_name test_name target_sol) _CRT_SECURE_NO_WARNINGS _CRT_SECURE_NO_DEPRECATE) else() target_compile_options(${test_target_name} - PRIVATE -std=c++1z -Wno-unknown-warning -Wno-unknown-warning-option - -Wall -Wextra -Wpedantic -pedantic -pedantic-errors) + PRIVATE -std=c++1z + -Wall -Wextra -Wpedantic -pedantic -pedantic-errors + -Wno-noexcept-type + -Wno-unknown-warning -Wno-unknown-warning-option) endif() if (MSVC) if (NOT CMAKE_COMPILER_ID MATCHES "Clang") target_compile_options(${test_target_name} - PRIVATE /bigobj) + PRIVATE /bigobj /W4) endif() else() - target_compile_options(${test_target_name} - PRIVATE -Wno-noexcept-type -pthread) - if (IS_X86) if(MINGW) set_target_properties(${test_target_name} diff --git a/tests/runtime_tests/CMakeLists.txt b/tests/runtime_tests/CMakeLists.txt index c6bbfc15..43f57c57 100644 --- a/tests/runtime_tests/CMakeLists.txt +++ b/tests/runtime_tests/CMakeLists.txt @@ -43,11 +43,14 @@ function(CREATE_TEST test_target_name test_name target_sol) if (MSVC) if (NOT CMAKE_COMPILER_ID MATCHES "Clang") target_compile_options(${test_target_name} - PRIVATE /bigobj) + PRIVATE /bigobj /W4) endif() else() target_compile_options(${test_target_name} - PRIVATE -Wno-noexcept-type -ftemplate-depth=1024 -pthread) + PRIVATE -std=c++1z + -Wall -Wpendatic -Werror -pedantic -pedantic-errors + -Wno-noexcept-type -pthread + -Wno-unknown-warning -Wno-unknown-warning-option) if (IS_X86) if(MINGW) diff --git a/tests/runtime_tests/source/common_classes.hpp b/tests/runtime_tests/source/common_classes.hpp index 0f6aae1b..653176ee 100644 --- a/tests/runtime_tests/source/common_classes.hpp +++ b/tests/runtime_tests/source/common_classes.hpp @@ -151,4 +151,15 @@ struct giver { } }; +struct lua_object { + +#define MAX_INFO_STRING 64 + + char info[MAX_INFO_STRING]; + const char stuck_info[MAX_INFO_STRING]; + + lua_object() : info("blah"), stuck_info("solid") { + } +}; + #endif // SOL_TESTS_COMMON_CLASSES_HPP \ No newline at end of file diff --git a/tests/runtime_tests/source/functions.cpp b/tests/runtime_tests/source/functions.cpp index 5c2f3414..7286a351 100644 --- a/tests/runtime_tests/source/functions.cpp +++ b/tests/runtime_tests/source/functions.cpp @@ -705,14 +705,14 @@ N = n(1, 2, 3) REQUIRE_FALSE(result.valid()); } { - auto result = lua.safe_script("t(2)", sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); - auto result2 = lua.safe_script("t2(2)", sol::script_pass_on_error); - REQUIRE_FALSE(result2.valid()); - auto result3 = lua.safe_script("t3(2)", sol::script_pass_on_error); - REQUIRE_FALSE(result3.valid()); - auto result4 = lua.safe_script("t4(2)", sol::script_pass_on_error); - REQUIRE_FALSE(result4.valid()); + auto tresult = lua.safe_script("t(2)", sol::script_pass_on_error); + REQUIRE_FALSE(tresult.valid()); + auto tresult2 = lua.safe_script("t2(2)", sol::script_pass_on_error); + REQUIRE_FALSE(tresult2.valid()); + auto tresult3 = lua.safe_script("t3(2)", sol::script_pass_on_error); + REQUIRE_FALSE(tresult3.valid()); + auto tresult4 = lua.safe_script("t4(2)", sol::script_pass_on_error); + REQUIRE_FALSE(tresult4.valid()); } { auto result = lua.safe_script("u(inner)", sol::script_pass_on_error); diff --git a/tests/runtime_tests/source/plain_types.cpp b/tests/runtime_tests/source/plain_types.cpp index 5f0927bb..9b50d01a 100644 --- a/tests/runtime_tests/source/plain_types.cpp +++ b/tests/runtime_tests/source/plain_types.cpp @@ -22,13 +22,15 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "sol_test.hpp" +#include "common_classes.hpp" #include #include + TEST_CASE("plain/alignment", "test that aligned classes in certain compilers don't trigger compiler errors") { #ifdef _MSC_VER - __declspec(align(16)) struct aligned_class { int var; }; + __declspec(align(16)) struct aligned_class { __declspec(align(16)) int var; }; struct A { aligned_class a; @@ -180,3 +182,17 @@ TEST_CASE("plain/constructors and destructors", REQUIRE(purely_constructed == 4); REQUIRE(purely_destructed == 4); } + +TEST_CASE("plain/arrays", "make sure c-style arrays don't ruin everything and compile fine as usertype variables") { + sol::state lua; + + lua.open_libraries(); + lua.new_usertype("lua_object", "info", &lua_object::info, "stuck_info", &lua_object::stuck_info); + + auto result0 = lua.safe_script("obj = lua_object.new()", sol::script_pass_on_error); + REQUIRE(result0.valid()); + auto result1 = lua.safe_script("print(obj.info)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("print(obj.stuck_info)", sol::script_pass_on_error); + REQUIRE(result2.valid()); +} diff --git a/tests/runtime_tests/source/usertype_properties.cpp b/tests/runtime_tests/source/usertype_properties.cpp index d9b0244f..a57ea449 100644 --- a/tests/runtime_tests/source/usertype_properties.cpp +++ b/tests/runtime_tests/source/usertype_properties.cpp @@ -77,7 +77,7 @@ void des(T& e) { template struct alignas(16) weird_aligned_wrapper { - template + template , std::nullptr_t> = nullptr> weird_aligned_wrapper(F&& f) : lambda(std::forward(f)) { } void operator()(SelfType& self, sol::object param) const {