27 #ifndef SOL_SINGLE_INCLUDE_HPP 28 #define SOL_SINGLE_INCLUDE_HPP 37 #define SOL_VERSION_MAJOR 3 38 #define SOL_VERSION_MINOR 2 39 #define SOL_VERSION_PATCH 3 40 #define SOL_VERSION_STRING "3.2.3" 41 #define SOL_VERSION ((SOL_VERSION_MAJOR * 100000) + (SOL_VERSION_MINOR * 100) + (SOL_VERSION_PATCH)) 43 #define SOL_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) #_TOKEN 44 #define SOL_TOKEN_TO_STRING_I_(_TOKEN) SOL_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) 46 #define SOL_CONCAT_TOKENS_POST_EXPANSION_I_(_LEFT, _RIGHT) _LEFT##_RIGHT 47 #define SOL_CONCAT_TOKENS_I_(_LEFT, _RIGHT) SOL_CONCAT_TOKENS_POST_EXPANSION_I_(_LEFT, _RIGHT) 49 #define SOL_RAW_IS_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) != 0) 50 #define SOL_RAW_IS_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3) == 0) 51 #define SOL_RAW_IS_DEFAULT_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) > 3) 52 #define SOL_RAW_IS_DEFAULT_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3 OP_SYMBOL 3) < 0) 54 #define SOL_IS_ON(OP_SYMBOL) SOL_RAW_IS_ON(OP_SYMBOL ## _I_) 55 #define SOL_IS_OFF(OP_SYMBOL) SOL_RAW_IS_OFF(OP_SYMBOL ## _I_) 56 #define SOL_IS_DEFAULT_ON(OP_SYMBOL) SOL_RAW_IS_DEFAULT_ON(OP_SYMBOL ## _I_) 57 #define SOL_IS_DEFAULT_OFF(OP_SYMBOL) SOL_RAW_IS_DEFAULT_OFF(OP_SYMBOL ## _I_) 61 #define SOL_DEFAULT_ON + 62 #define SOL_DEFAULT_OFF - 64 #if defined(SOL_BUILD_CXX_MODE) 65 #if (SOL_BUILD_CXX_MODE != 0) 66 #define SOL_BUILD_CXX_MODE_I_ SOL_ON 68 #define SOL_BUILD_CXX_MODE_I_ SOL_OFF 70 #elif defined(__cplusplus) 71 #define SOL_BUILD_CXX_MODE_I_ SOL_DEFAULT_ON 73 #define SOL_BUILD_CXX_MODE_I_ SOL_DEFAULT_OFF 76 #if defined(SOL_BUILD_C_MODE) 77 #if (SOL_BUILD_C_MODE != 0) 78 #define SOL_BUILD_C_MODE_I_ SOL_ON 80 #define SOL_BUILD_C_MODE_I_ SOL_OFF 82 #elif defined(__STDC__) 83 #define SOL_BUILD_C_MODE_I_ SOL_DEFAULT_ON 85 #define SOL_BUILD_C_MODE_I_ SOL_DEFAULT_OFF 88 #if SOL_IS_ON(SOL_BUILD_C_MODE) 98 #if defined(SOL_COMPILER_VCXX) 99 #if defined(SOL_COMPILER_VCXX != 0) 100 #define SOL_COMPILER_VCXX_I_ SOL_ON 102 #define SOL_COMPILER_VCXX_I_ SOL_OFF 104 #elif defined(_MSC_VER) 105 #define SOL_COMPILER_VCXX_I_ SOL_DEFAULT_ON 107 #define SOL_COMPILER_VCXX_I_ SOL_DEFAULT_OFF 110 #if defined(SOL_COMPILER_GCC) 111 #if defined(SOL_COMPILER_GCC != 0) 112 #define SOL_COMPILER_GCC_I_ SOL_ON 114 #define SOL_COMPILER_GCC_I_ SOL_OFF 116 #elif defined(__GNUC__) 117 #define SOL_COMPILER_GCC_I_ SOL_DEFAULT_ON 119 #define SOL_COMPILER_GCC_I_ SOL_DEFAULT_OFF 122 #if defined(SOL_COMPILER_CLANG) 123 #if defined(SOL_COMPILER_CLANG != 0) 124 #define SOL_COMPILER_CLANG_I_ SOL_ON 126 #define SOL_COMPILER_CLANG_I_ SOL_OFF 128 #elif defined(__clang__) 129 #define SOL_COMPILER_CLANG_I_ SOL_DEFAULT_ON 131 #define SOL_COMPILER_CLANG_I_ SOL_DEFAULT_OFF 134 #if defined(SOL_COMPILER_EDG) 135 #if defined(SOL_COMPILER_EDG != 0) 136 #define SOL_COMPILER_EDG_I_ SOL_ON 138 #define SOL_COMPILER_EDG_I_ SOL_OFF 141 #define SOL_COMPILER_EDG_I_ SOL_DEFAULT_OFF 144 #if defined(SOL_COMPILER_MINGW) 145 #if (SOL_COMPILER_MINGW != 0) 146 #define SOL_COMPILER_MINGW_I_ SOL_ON 148 #define SOL_COMPILER_MINGW_I_ SOL_OFF 150 #elif defined(__MINGW32__) 151 #define SOL_COMPILER_MINGW_I_ SOL_DEFAULT_ON 153 #define SOL_COMPILER_MINGW_I_ SOL_DEFAULT_OFF 156 #if SIZE_MAX <= 0xFFFFULL 157 #define SOL_PLATFORM_X16_I_ SOL_ON 158 #define SOL_PLATFORM_X86_I_ SOL_OFF 159 #define SOL_PLATFORM_X64_I_ SOL_OFF 160 #elif SIZE_MAX <= 0xFFFFFFFFULL 161 #define SOL_PLATFORM_X16_I_ SOL_OFF 162 #define SOL_PLATFORM_X86_I_ SOL_ON 163 #define SOL_PLATFORM_X64_I_ SOL_OFF 165 #define SOL_PLATFORM_X16_I_ SOL_OFF 166 #define SOL_PLATFORM_X86_I_ SOL_OFF 167 #define SOL_PLATFORM_X64_I_ SOL_ON 170 #define SOL_PLATFORM_ARM32_I_ SOL_OFF 171 #define SOL_PLATFORM_ARM64_I_ SOL_OFF 173 #if defined(SOL_PLATFORM_WINDOWS) 174 #if (SOL_PLATFORM_WINDOWS != 0) 175 #define SOL_PLATFORM_WINDOWS_I_ SOL_ON 177 #define SOL_PLATFORM_WINDOWS_I_ SOL_OFF 179 #elif defined(_WIN32) 180 #define SOL_PLATFORM_WINDOWS_I_ SOL_DEFAULT_ON 182 #define SOL_PLATFORM_WINDOWS_I_ SOL_DEFAULT_OFF 185 #if defined(SOL_PLATFORM_CYGWIN) 186 #if (SOL_PLATFORM_CYGWIN != 0) 187 #define SOL_PLATFORM_CYGWIN_I_ SOL_ON 189 #define SOL_PLATFORM_CYGWIN_I_ SOL_ON 191 #elif defined(__CYGWIN__) 192 #define SOL_PLATFORM_CYGWIN_I_ SOL_DEFAULT_ON 194 #define SOL_PLATFORM_CYGWIN_I_ SOL_DEFAULT_OFF 197 #if defined(SOL_PLATFORM_APPLE) 198 #if (SOL_PLATFORM_APPLE != 0) 199 #define SOL_PLATFORM_APPLE_I_ SOL_ON 201 #define SOL_PLATFORM_APPLE_I_ SOL_OFF 203 #elif defined(__APPLE__) 204 #define SOL_PLATFORM_APPLE_I_ SOL_DEFAULT_ON 206 #define SOL_PLATFORM_APPLE_I_ SOL_DEFAULT_OFF 209 #if defined(SOL_PLATFORM_UNIX) 210 #if (SOL_PLATFORM_UNIX != 0) 211 #define SOL_PLATFORM_UNIXLIKE_I_ SOL_ON 213 #define SOL_PLATFORM_UNIXLIKE_I_ SOL_OFF 215 #elif defined(__unix__) 216 #define SOL_PLATFORM_UNIXLIKE_I_ SOL_DEFAUKT_ON 218 #define SOL_PLATFORM_UNIXLIKE_I_ SOL_DEFAULT_OFF 221 #if defined(SOL_PLATFORM_LINUX) 222 #if (SOL_PLATFORM_LINUX != 0) 223 #define SOL_PLATFORM_LINUXLIKE_I_ SOL_ON 225 #define SOL_PLATFORM_LINUXLIKE_I_ SOL_OFF 227 #elif defined(__LINUX__) 228 #define SOL_PLATFORM_LINUXLIKE_I_ SOL_DEFAUKT_ON 230 #define SOL_PLATFORM_LINUXLIKE_I_ SOL_DEFAULT_OFF 233 #define SOL_PLATFORM_APPLE_IPHONE_I_ SOL_OFF 234 #define SOL_PLATFORM_BSDLIKE_I_ SOL_OFF 236 #if defined(SOL_IN_DEBUG_DETECTED) 237 #if SOL_IN_DEBUG_DETECTED != 0 238 #define SOL_DEBUG_BUILD_I_ SOL_ON 240 #define SOL_DEBUG_BUILD_I_ SOL_OFF 242 #elif !defined(NDEBUG) 243 #if SOL_IS_ON(SOL_COMPILER_VCXX) && defined(_DEBUG) 244 #define SOL_DEBUG_BUILD_I_ SOL_ON 245 #elif (SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC)) && !defined(__OPTIMIZE__) 246 #define SOL_DEBUG_BUILD_I_ SOL_ON 248 #define SOL_DEBUG_BUILD_I_ SOL_OFF 251 #define SOL_DEBUG_BUILD_I_ SOL_DEFAULT_OFF 252 #endif // We are in a debug mode of some sort 254 #if defined(SOL_NO_EXCEPTIONS) 255 #if (SOL_NO_EXCEPTIONS != 0) 256 #define SOL_EXCEPTIONS_I_ SOL_OFF 258 #define SOL_EXCEPTIONS_I_ SOL_ON 260 #elif SOL_IS_ON(SOL_COMPILER_VCXX) 261 #if !defined(_CPPUNWIND) 262 #define SOL_EXCEPTIONS_I_ SOL_OFF 264 #define SOL_EXCEPTIONS_I_ SOL_ON 266 #elif SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC) 267 #if !defined(__EXCEPTIONS) 268 #define SOL_EXCEPTIONS_I_ SOL_OFF 270 #define SOL_EXCEPTIONS_I_ SOL_ON 273 #define SOL_EXCEPTIONS_I_ SOL_DEFAULT_ON 276 #if defined(SOL_NO_RTTI) 277 #if (SOL_NO_RTTI != 0) 278 #define SOL_RTTI_I_ SOL_OFF 280 #define SOL_RTTI_I_ SOL_ON 282 #elif SOL_IS_ON(SOL_COMPILER_VCXX) 283 #if !defined(_CPPRTTI) 284 #define SOL_RTTI_I_ SOL_OFF 286 #define SOL_RTTI_I_ SOL_ON 288 #elif SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC) 289 #if !defined(__GXX_RTTI) 290 #define SOL_RTTI_I_ SOL_OFF 292 #define SOL_RTTI_I_ SOL_ON 295 #define SOL_RTTI_I_ SOL_DEFAULT_ON 298 #if defined(SOL_NO_THREAD_LOCAL) 299 #if SOL_NO_THREAD_LOCAL != 0 300 #define SOL_USE_THREAD_LOCAL_I_ SOL_OFF 302 #define SOL_USE_THREAD_LOCAL_I_ SOL_ON 305 #define SOL_USE_THREAD_LOCAL_I_ SOL_DEFAULT_ON 306 #endif // thread_local keyword is bjorked on some platforms 308 #if defined(SOL_ALL_SAFETIES_ON) 309 #if SOL_ALL_SAFETIES_ON != 0 310 #define SOL_ALL_SAFETIES_ON_I_ SOL_ON 312 #define SOL_ALL_SAFETIES_ON_I_ SOL_OFF 315 #define SOL_ALL_SAFETIES_ON_I_ SOL_DEFAULT_OFF 318 #if defined(SOL_SAFE_GETTER) 319 #if SOL_SAFE_GETTER != 0 320 #define SOL_SAFE_GETTER_I_ SOL_ON 322 #define SOL_SAFE_GETTER_I_ SOL_OFF 325 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) 326 #define SOL_SAFE_GETTER_I_ SOL_ON 327 #elif SOL_IS_ON(SOL_DEBUG_BUILD) 328 #define SOL_SAFE_GETTER_I_ SOL_DEFAULT_ON 330 #define SOL_SAFE_GETTER_I_ SOL_DEFAULT_OFF 334 #if defined(SOL_SAFE_USERTYPE) 335 #if SOL_SAFE_USERTYPE != 0 336 #define SOL_SAFE_USERTYPE_I_ SOL_ON 338 #define SOL_SAFE_USERTYPE_I_ SOL_OFF 341 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) 342 #define SOL_SAFE_USERTYPE_I_ SOL_ON 343 #elif SOL_IS_ON(SOL_DEBUG_BUILD) 344 #define SOL_SAFE_USERTYPE_I_ SOL_DEFAULT_ON 346 #define SOL_SAFE_USERTYPE_I_ SOL_DEFAULT_OFF 350 #if defined(SOL_SAFE_REFERENCES) 351 #if SOL_SAFE_REFERENCES != 0 352 #define SOL_SAFE_REFERENCES_I_ SOL_ON 354 #define SOL_SAFE_REFERENCES_I_ SOL_OFF 357 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) 358 #define SOL_SAFE_REFERENCES_I_ SOL_ON 359 #elif SOL_IS_ON(SOL_DEBUG_BUILD) 360 #define SOL_SAFE_REFERENCES_I_ SOL_DEFAULT_ON 362 #define SOL_SAFE_REFERENCES_I_ SOL_DEFAULT_OFF 366 #if defined(SOL_SAFE_FUNCTIONS) 367 #if SOL_SAFE_FUNCTIONS != 0 368 #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON 370 #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_OFF 372 #elif defined (SOL_SAFE_FUNCTION_OBJECTS) 373 #if SOL_SAFE_FUNCTION_OBJECTS != 0 374 #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON 376 #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_OFF 379 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) 380 #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON 381 #elif SOL_IS_ON(SOL_DEBUG_BUILD) 382 #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_DEFAULT_ON 384 #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_DEFAULT_OFF 388 #if defined(SOL_SAFE_FUNCTION_CALLS) 389 #if SOL_SAFE_FUNCTION_CALLS != 0 390 #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_ON 392 #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_OFF 395 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) 396 #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_ON 397 #elif SOL_IS_ON(SOL_DEBUG_BUILD) 398 #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_DEFAULT_ON 400 #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_DEFAULT_OFF 404 #if defined(SOL_SAFE_PROXIES) 405 #if SOL_SAFE_PROXIES != 0 406 #define SOL_SAFE_PROXIES_I_ SOL_ON 408 #define SOL_SAFE_PROXIES_I_ SOL_OFF 411 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) 412 #define SOL_SAFE_PROXIES_I_ SOL_ON 413 #elif SOL_IS_ON(SOL_DEBUG_BUILD) 414 #define SOL_SAFE_PROXIES_I_ SOL_DEFAULT_ON 416 #define SOL_SAFE_PROXIES_I_ SOL_DEFAULT_OFF 420 #if defined(SOL_SAFE_NUMERICS) 421 #if SOL_SAFE_NUMERICS != 0 422 #define SOL_SAFE_NUMERICS_I_ SOL_ON 424 #define SOL_SAFE_NUMERICS_I_ SOL_OFF 427 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) 428 #define SOL_SAFE_NUMERICS_I_ SOL_ON 429 #elif SOL_IS_ON(SOL_DEBUG_BUILD) 430 #define SOL_SAFE_NUMERICS_I_ SOL_DEFAULT_ON 432 #define SOL_SAFE_NUMERICS_I_ SOL_DEFAULT_OFF 436 #if defined(SOL_ALL_INTEGER_VALUES_FIT) 437 #if (SOL_ALL_INTEGER_VALUES_FIT != 0) 438 #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_ON 440 #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_OFF 442 #elif !SOL_IS_DEFAULT_OFF(SOL_SAFE_NUMERICS) && SOL_IS_OFF(SOL_SAFE_NUMERICS) 444 #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_DEFAULT_ON 447 #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_DEFAULT_OFF 450 #if defined(SOL_SAFE_STACK_CHECK) 451 #if SOL_SAFE_STACK_CHECK != 0 452 #define SOL_SAFE_STACK_CHECK_I_ SOL_ON 454 #define SOL_SAFE_STACK_CHECK_I_ SOL_OFF 457 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) 458 #define SOL_SAFE_STACK_CHECK_I_ SOL_ON 459 #elif SOL_IS_ON(SOL_DEBUG_BUILD) 460 #define SOL_SAFE_STACK_CHECK_I_ SOL_DEFAULT_ON 462 #define SOL_SAFE_STACK_CHECK_I_ SOL_DEFAULT_OFF 466 #if defined(SOL_NO_CHECK_NUMBER_PRECISION) 467 #if SOL_NO_CHECK_NUMBER_PRECISION != 0 468 #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_OFF 470 #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON 472 #elif defined(SOL_NO_CHECKING_NUMBER_PRECISION) 473 #if SOL_NO_CHECKING_NUMBER_PRECISION != 0 474 #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_OFF 476 #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON 479 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) 480 #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON 481 #elif SOL_IS_ON(SOL_SAFE_NUMERICS) 482 #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON 483 #elif SOL_IS_ON(SOL_DEBUG_BUILD) 484 #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_DEFAULT_ON 486 #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_DEFAULT_OFF 490 #if defined(SOL_STRINGS_ARE_NUMBERS) 491 #if (SOL_STRINGS_ARE_NUMBERS != 0) 492 #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_ON 494 #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_OFF 497 #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_DEFAULT_OFF 500 #if defined(SOL_ENABLE_INTEROP) 501 #if SOL_ENABLE_INTEROP != 0 502 #define SOL_USE_INTEROP_I_ SOL_ON 504 #define SOL_USE_INTEROP_I_ SOL_OFF 506 #elif defined(SOL_USE_INTEROP) 507 #if SOL_USE_INTEROP != 0 508 #define SOL_USE_INTEROP_I_ SOL_ON 510 #define SOL_USE_INTEROP_I_ SOL_OFF 513 #define SOL_USE_INTEROP_I_ SOL_DEFAULT_OFF 516 #if defined(SOL_NO_NIL) 517 #if (SOL_NO_NIL != 0) 518 #define SOL_NIL_I_ SOL_OFF 520 #define SOL_NIL_I_ SOL_ON 522 #elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) || defined(__OBJC__) || defined(nil) 523 #define SOL_NIL_I_ SOL_DEFAULT_OFF 525 #define SOL_NIL_I_ SOL_DEFAULT_ON 528 #if defined(SOL_USERTYPE_TYPE_BINDING_INFO) 529 #if (SOL_USERTYPE_TYPE_BINDING_INFO != 0) 530 #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_ON 532 #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_OFF 535 #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_DEFAULT_ON 536 #endif // We should generate a my_type.__type table with lots of class information for usertypes 538 #if defined(SOL_AUTOMAGICAL_TYPES_BY_DEFAULT) 539 #if (SOL_AUTOMAGICAL_TYPES_BY_DEFAULT != 0) 540 #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_ON 542 #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_OFF 544 #elif defined(SOL_DEFAULT_AUTOMAGICAL_USERTYPES) 545 #if (SOL_DEFAULT_AUTOMAGICAL_USERTYPES != 0) 546 #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_ON 548 #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_OFF 551 #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_DEFAULT_ON 552 #endif // make is_automagical on/off by default 554 #if defined(SOL_STD_VARIANT) 555 #if (SOL_STD_VARIANT != 0) 556 #define SOL_STD_VARIANT_I_ SOL_ON 558 #define SOL_STD_VARIANT_I_ SOL_OFF 561 #if SOL_IS_ON(SOL_COMPILER_CLANG) && SOL_IS_ON(SOL_PLATFORM_APPLE) 562 #if defined(__has_include) 563 #if __has_include(<variant>) 564 #define SOL_STD_VARIANT_I_ SOL_DEFAULT_ON 566 #define SOL_STD_VARIANT_I_ SOL_DEFAULT_OFF 569 #define SOL_STD_VARIANT_I_ SOL_DEFAULT_OFF 572 #define SOL_STD_VARIANT_I_ SOL_DEFAULT_ON 574 #endif // make is_automagical on/off by default 576 #if defined(SOL_NOEXCEPT_FUNCTION_TYPE) 577 #if (SOL_NOEXCEPT_FUNCTION_TYPE != 0) 578 #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_ON 580 #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_OFF 583 #if defined(__cpp_noexcept_function_type) 584 #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_ON 585 #elif SOL_IS_ON(SOL_COMPILER_VCXX) && (defined(_MSVC_LANG) && (_MSVC_LANG < 201403L)) 591 #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_OFF 593 #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_DEFAULT_ON 595 #endif // noexcept is part of a function's type 597 #if defined(SOL_STACK_STRING_OPTIMIZATION_SIZE) && SOL_STACK_STRING_OPTIMIZATION_SIZE > 0 598 #define SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_ SOL_STACK_STRING_OPTIMIZATION_SIZE 600 #define SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_ 1024 603 #if defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 604 #define SOL_ID_SIZE_I_ SOL_ID_SIZE 606 #define SOL_ID_SIZE_I_ 512 609 #if defined(LUA_IDSIZE) && LUA_IDSIZE > 0 610 #define SOL_FILE_ID_SIZE_I_ LUA_IDSIZE 611 #elif defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 612 #define SOL_FILE_ID_SIZE_I_ SOL_FILE_ID_SIZE 614 #define SOL_FILE_ID_SIZE_I_ 2048 617 #if defined(SOL_PRINT_ERRORS) 618 #if (SOL_PRINT_ERRORS != 0) 619 #define SOL_PRINT_ERRORS_I_ SOL_ON 621 #define SOL_PRINT_ERRORS_I_ SOL_OFF 624 #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) 625 #define SOL_PRINT_ERRORS_I_ SOL_ON 626 #elif SOL_IS_ON(SOL_DEBUG_BUILD) 627 #define SOL_PRINT_ERRORS_I_ SOL_DEFAULT_ON 629 #define SOL_PRINT_ERRORS_I_ SOL_OFF 633 #if defined(SOL_DEFAULT_PASS_ON_ERROR) 634 #if (SOL_DEFAULT_PASS_ON_ERROR != 0) 635 #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_ON 637 #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_OFF 640 #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_DEFAULT_OFF 643 #if defined(SOL_USING_CXX_LUA) 644 #if (SOL_USING_CXX_LUA != 0) 645 #define SOL_USE_CXX_LUA_I_ SOL_ON 647 #define SOL_USE_CXX_LUA_I_ SOL_OFF 649 #elif defined(SOL_USE_CXX_LUA) 650 #if (SOL_USE_CXX_LUA != 0) 651 #define SOL_USE_CXX_LUA_I_ SOL_ON 653 #define SOL_USE_CXX_LUA_I_ SOL_OFF 656 #define SOL_USE_CXX_LUA_I_ SOL_DEFAULT_OFF 659 #if defined(SOL_USING_CXX_LUAJIT) 660 #if (SOL_USING_CXX_LUA != 0) 661 #define SOL_USE_CXX_LUAJIT_I_ SOL_ON 663 #define SOL_USE_CXX_LUAJIT_I_ SOL_OFF 665 #elif defined(SOL_USE_CXX_LUAJIT) 666 #if (SOL_USE_CXX_LUA != 0) 667 #define SOL_USE_CXX_LUAJIT_I_ SOL_ON 669 #define SOL_USE_CXX_LUAJIT_I_ SOL_OFF 672 #define SOL_USE_CXX_LUAJIT_I_ SOL_DEFAULT_OFF 675 #if defined(SOL_NO_LUA_HPP) 676 #if (SOL_NO_LUA_HPP != 0) 677 #define SOL_USE_LUA_HPP_I_ SOL_OFF 679 #define SOL_USE_LUA_HPP_I_ SOL_ON 681 #elif defined(SOL_USING_CXX_LUA) 682 #define SOL_USE_LUA_HPP_I_ SOL_OFF 683 #elif defined(__has_include) 684 #if __has_include(<lua.hpp>) 685 #define SOL_USE_LUA_HPP_I_ SOL_ON 687 #define SOL_USE_LUA_HPP_I_ SOL_OFF 690 #define SOL_USE_LUA_HPP_I_ SOL_DEFAULT_ON 693 #if defined(SOL_CONTAINERS_START) 694 #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINERS_START 695 #elif defined(SOL_CONTAINERS_START_INDEX) 696 #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINERS_START_INDEX 697 #elif defined(SOL_CONTAINER_START_INDEX) 698 #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINER_START_INDEX 700 #define SOL_CONTAINER_START_INDEX_I_ 1 703 #if defined (SOL_NO_MEMORY_ALIGNMENT) 704 #if (SOL_NO_MEMORY_ALIGNMENT != 0) 705 #define SOL_ALIGN_MEMORY_I_ SOL_OFF 707 #define SOL_ALIGN_MEMORY_I_ SOL_ON 710 #define SOL_ALIGN_MEMORY_I_ SOL_DEFAULT_ON 713 #if defined(SOL_USE_BOOST) 714 #if (SOL_USE_BOOST != 0) 715 #define SOL_USE_BOOST_I_ SOL_ON 717 #define SOL_USE_BOOST_I_ SOL_OFF 720 #define SOL_USE_BOOST_I_ SOL_DEFAULT_OFF 723 #if defined(SOL_USE_UNSAFE_BASE_LOOKUP) 724 #if (SOL_USE_UNSAFE_BASE_LOOKUP != 0) 725 #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_ON 727 #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_OFF 730 #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_DEFAULT_OFF 733 #if defined(SOL_INSIDE_UNREAL) 734 #if (SOL_INSIDE_UNREAL != 0) 735 #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_ON 737 #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_OFF 740 #if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_SERVER) 741 #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_DEFAULT_ON 743 #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_DEFAULT_OFF 747 #if defined(SOL_NO_COMPAT) 748 #if (SOL_NO_COMPAT != 0) 749 #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_OFF 751 #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_ON 754 #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_DEFAULT_ON 757 #if defined(SOL_GET_FUNCTION_POINTER_UNSAFE) 758 #if (SOL_GET_FUNCTION_POINTER_UNSAFE != 0) 759 #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_ON 761 #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_OFF 764 #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_DEFAULT_OFF 767 #if defined(SOL_FUNCTION_CALL_VALUE_SEMANTICS) 768 #if (SOL_FUNCTION_CALL_VALUE_SEMANTICS != 0) 769 #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_ON 771 #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_OFF 774 #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_DEFAULT_OFF 777 #if defined(SOL_MINGW_CCTYPE_IS_POISONED) 778 #if (SOL_MINGW_CCTYPE_IS_POISONED != 0) 779 #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_ON 781 #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_OFF 783 #elif SOL_IS_ON(SOL_COMPILER_MINGW) && defined(__GNUC__) && (__GNUC__ < 6) 785 #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_DEFAULT_ON 787 #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_DEFAULT_OFF 790 #if defined(SOL_CHAR8_T) 791 #if (SOL_CHAR8_T != 0) 792 #define SOL_CHAR8_T_I_ SOL_ON 794 #define SOL_CHAR8_T_I_ SOL_OFF 797 #if defined(__cpp_char8_t) 798 #define SOL_CHAR8_T_I_ SOL_DEFAULT_ON 800 #define SOL_CHAR8_T_I_ SOL_DEFAULT_OFF 804 #if SOL_IS_ON(SOL_USE_BOOST) 805 #include <boost/version.hpp> 807 #if BOOST_VERSION >= 107500 // Since Boost 1.75.0 boost::none is constexpr 808 #define SOL_BOOST_NONE_CONSTEXPR_I_ constexpr 810 #define SOL_BOOST_NONE_CONSTEXPR_I_ const 811 #endif // BOOST_VERSION 814 #define SOL_BOOST_NONE_CONSTEXPR_I_ constexpr 819 #define SOL2_CI_I_ SOL_ON 821 #define SOL2_CI_I_ SOL_OFF 824 #define SOL2_CI_I_ SOL_DEFAULT_OFF 827 #if defined(SOL_C_ASSERT) 828 #define SOL_USER_C_ASSERT_I_ SOL_ON 830 #define SOL_USER_C_ASSERT_I_ SOL_DEFAULT_OFF 833 #if defined(SOL_M_ASSERT) 834 #define SOL_USER_M_ASSERT_I_ SOL_ON 836 #define SOL_USER_M_ASSERT_I_ SOL_DEFAULT_OFF 841 #if defined(SOL_PROLOGUE_I_) 842 #error "[sol2] Library Prologue was already included in translation unit and not properly ended with an epilogue." 845 #define SOL_PROLOGUE_I_ 1 847 #if SOL_IS_ON(SOL_BUILD_CXX_MODE) 848 #define _FWD(...) static_cast<decltype( __VA_ARGS__ )&&>( __VA_ARGS__ ) 850 #if SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) 851 #define _MOVE(...) static_cast<__typeof( __VA_ARGS__ )&&>( __VA_ARGS__ ) 853 #include <type_traits> 855 #define _MOVE(...) static_cast<::std::remove_reference_t<( __VA_ARGS__ )>&&>( __VA_OPT__(,) ) 863 #if !defined(SOL_PROLOGUE_I_) 864 #error "[sol2] Library Prologue is missing from this translation unit." 866 #undef SOL_PROLOGUE_I_ 869 #if SOL_IS_ON(SOL_BUILD_CXX_MODE) 880 #define SOL_DLL_I_ SOL_ON 882 #define SOL_DLL_I_ SOL_OFF 884 #elif SOL_IS_ON(SOL_COMPILER_VCXX) && (defined(DLL_) || defined(_DLL)) 885 #define SOL_DLL_I_ SOL_DEFAULT_ON 887 #define SOL_DLL_I_ SOL_DEFAULT_OFF 888 #endif // DLL definition 890 #if defined(SOL_HEADER_ONLY) 891 #if (SOL_HEADER_ONLY != 0) 892 #define SOL_HEADER_ONLY_I_ SOL_ON 894 #define SOL_HEADER_ONLY_I_ SOL_OFF 897 #define SOL_HEADER_ONLY_I_ SOL_DEFAULT_OFF 898 #endif // Header only library 900 #if defined(SOL_BUILD) 902 #define SOL_BUILD_I_ SOL_ON 904 #define SOL_BUILD_I_ SOL_OFF 906 #elif SOL_IS_ON(SOL_HEADER_ONLY) 907 #define SOL_BUILD_I_ SOL_DEFAULT_OFF 909 #define SOL_BUILD_I_ SOL_DEFAULT_ON 912 #if defined(SOL_UNITY_BUILD) 913 #if (SOL_UNITY_BUILD != 0) 914 #define SOL_UNITY_BUILD_I_ SOL_ON 916 #define SOL_UNITY_BUILD_I_ SOL_OFF 919 #define SOL_UNITY_BUILD_I_ SOL_DEFAULT_OFF 920 #endif // Header only library 922 #if defined(SOL_C_FUNCTION_LINKAGE) 923 #define SOL_C_FUNCTION_LINKAGE_I_ SOL_C_FUNCTION_LINKAGE 925 #if SOL_IS_ON(SOL_BUILD_CXX_MODE) 927 #define SOL_C_FUNCTION_LINKAGE_I_ extern "C" 930 #define SOL_C_FUNCTION_LINKAGE_I_ 932 #endif // Linkage specification for C functions 934 #if defined(SOL_API_LINKAGE) 935 #define SOL_API_LINKAGE_I_ SOL_API_LINKAGE 937 #if SOL_IS_ON(SOL_DLL) 938 #if SOL_IS_ON(SOL_COMPILER_VCXX) || SOL_IS_ON(SOL_PLATFORM_WINDOWS) || SOL_IS_ON(SOL_PLATFORM_CYGWIN) 940 #if SOL_IS_ON(SOL_BUILD) 942 #if SOL_IS_ON(SOL_COMPILER_GCC) 944 #define SOL_API_LINKAGE_I_ __attribute__((dllexport)) 947 #define SOL_API_LINKAGE_I_ __declspec(dllexport) 950 #if SOL_IS_ON(SOL_COMPILER_GCC) 951 #define SOL_API_LINKAGE_I_ __attribute__((dllimport)) 953 #define SOL_API_LINKAGE_I_ __declspec(dllimport) 958 #define SOL_API_LINKAGE_I_ extern 960 #elif SOL_IS_ON(SOL_UNITY_BUILD) 962 #if SOL_IS_ON(SOL_HEADER_ONLY) 964 #define SOL_API_LINKAGE_I_ inline 967 #define SOL_API_LINKAGE_I_ extern 971 #if SOL_IS_ON(SOL_BUILD_CXX_MODE) 972 #define SOL_API_LINKAGE_I_ 974 #define SOL_API_LINKAGE_I_ extern 977 #endif // Build definitions 979 #if defined(SOL_PUBLIC_FUNC_DECL) 980 #define SOL_PUBLIC_FUNC_DECL_I_ SOL_PUBLIC_FUNC_DECL 982 #define SOL_PUBLIC_FUNC_DECL_I_ SOL_API_LINKAGE_I_ 985 #if defined(SOL_INTERNAL_FUNC_DECL_) 986 #define SOL_INTERNAL_FUNC_DECL_I_ SOL_INTERNAL_FUNC_DECL_ 988 #define SOL_INTERNAL_FUNC_DECL_I_ SOL_API_LINKAGE_I_ 991 #if defined(SOL_PUBLIC_FUNC_DEF) 992 #define SOL_PUBLIC_FUNC_DEF_I_ SOL_PUBLIC_FUNC_DEF 994 #define SOL_PUBLIC_FUNC_DEF_I_ SOL_API_LINKAGE_I_ 997 #if defined(SOL_INTERNAL_FUNC_DEF) 998 #define SOL_INTERNAL_FUNC_DEF_I_ SOL_INTERNAL_FUNC_DEF 1000 #define SOL_INTERNAL_FUNC_DEF_I_ SOL_API_LINKAGE_I_ 1003 #if defined(SOL_FUNC_DECL) 1004 #define SOL_FUNC_DECL_I_ SOL_FUNC_DECL 1005 #elif SOL_IS_ON(SOL_HEADER_ONLY) 1006 #define SOL_FUNC_DECL_I_ 1007 #elif SOL_IS_ON(SOL_DLL) 1008 #if SOL_IS_ON(SOL_COMPILER_VCXX) 1009 #if SOL_IS_ON(SOL_BUILD) 1010 #define SOL_FUNC_DECL_I_ extern __declspec(dllexport) 1012 #define SOL_FUNC_DECL_I_ extern __declspec(dllimport) 1014 #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) 1015 #define SOL_FUNC_DECL_I_ extern __attribute__((visibility("default"))) 1017 #define SOL_FUNC_DECL_I_ extern 1021 #if defined(SOL_FUNC_DEFN) 1022 #define SOL_FUNC_DEFN_I_ SOL_FUNC_DEFN 1023 #elif SOL_IS_ON(SOL_HEADER_ONLY) 1024 #define SOL_FUNC_DEFN_I_ inline 1025 #elif SOL_IS_ON(SOL_DLL) 1026 #if SOL_IS_ON(SOL_COMPILER_VCXX) 1027 #if SOL_IS_ON(SOL_BUILD) 1028 #define SOL_FUNC_DEFN_I_ __declspec(dllexport) 1030 #define SOL_FUNC_DEFN_I_ __declspec(dllimport) 1032 #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) 1033 #define SOL_FUNC_DEFN_I_ __attribute__((visibility("default"))) 1035 #define SOL_FUNC_DEFN_I_ 1039 #if defined(SOL_HIDDEN_FUNC_DECL) 1040 #define SOL_HIDDEN_FUNC_DECL_I_ SOL_HIDDEN_FUNC_DECL 1041 #elif SOL_IS_ON(SOL_HEADER_ONLY) 1042 #define SOL_HIDDEN_FUNC_DECL_I_ 1043 #elif SOL_IS_ON(SOL_DLL) 1044 #if SOL_IS_ON(SOL_COMPILER_VCXX) 1045 #if SOL_IS_ON(SOL_BUILD) 1046 #define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllexport) 1048 #define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllimport) 1050 #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) 1051 #define SOL_HIDDEN_FUNC_DECL_I_ extern __attribute__((visibility("default"))) 1053 #define SOL_HIDDEN_FUNC_DECL_I_ extern 1057 #if defined(SOL_HIDDEN_FUNC_DEFN) 1058 #define SOL_HIDDEN_FUNC_DEFN_I_ SOL_HIDDEN_FUNC_DEFN 1059 #elif SOL_IS_ON(SOL_HEADER_ONLY) 1060 #define SOL_HIDDEN_FUNC_DEFN_I_ inline 1061 #elif SOL_IS_ON(SOL_DLL) 1062 #if SOL_IS_ON(SOL_COMPILER_VCXX) 1063 #if SOL_IS_ON(SOL_BUILD) 1064 #define SOL_HIDDEN_FUNC_DEFN_I_ 1066 #define SOL_HIDDEN_FUNC_DEFN_I_ 1068 #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) 1069 #define SOL_HIDDEN_FUNC_DEFN_I_ __attribute__((visibility("hidden"))) 1071 #define SOL_HIDDEN_FUNC_DEFN_I_ 1079 #if SOL_IS_ON(SOL_INSIDE_UNREAL_ENGINE) 1081 #pragma push_macro("check") 1084 #endif // Unreal Engine 4 Bullshit 1086 #if SOL_IS_ON(SOL_COMPILER_GCC) 1087 #pragma GCC diagnostic push 1088 #pragma GCC diagnostic ignored "-Wshadow" 1089 #pragma GCC diagnostic ignored "-Wconversion" 1091 #pragma GCC diagnostic ignored "-Wnoexcept-type" 1093 #elif SOL_IS_ON(SOL_COMPILER_CLANG) 1094 #elif SOL_IS_ON(SOL_COMPILER_VCXX) 1095 #pragma warning(push) 1096 #pragma warning(disable : 4505) // unreferenced local function has been removed GEE THANKS 1097 #endif // clang++ vs. g++ vs. VC++ 1101 #ifndef SOL_FORWARD_HPP 1102 #define SOL_FORWARD_HPP 1105 #include <type_traits> 1106 #include <string_view> 1108 #if SOL_IS_ON(SOL_USE_CXX_LUA) || SOL_IS_ON(SOL_USE_CXX_LUAJIT) 1114 #endif // C++ Mangling for Lua vs. Not 1120 class stateless_reference;
1128 template <
typename A>
1136 template <
typename,
typename>
1139 template <
bool,
typename>
1147 template <
typename base_type>
1161 template <
typename T,
typename base_type>
1163 template <
typename T>
1165 template <
typename T>
1168 template <
typename base_type>
1173 template <
typename base_t>
1179 template <
typename T,
bool>
1181 template <
typename T,
bool,
typename H>
1195 #if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS) 1211 #if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS) 1217 template <
typename base_t>
1219 template <
typename base_t>
1221 template <
typename base_t>
1223 template <
typename base_t>
1225 template <
typename base_t>
1227 template <
typename base_t>
1229 template <
typename base_t>
1260 template <
typename T>
1262 template <
typename T>
1264 template <
typename T>
1266 template <
typename T>
1268 template <
typename T>
1270 template <
typename T>
1272 template <
typename T>
1274 template <
typename F,
typename... Policies>
1277 template <
typename T>
1279 template <
typename T>
1282 template <
typename... Args>
1284 typedef std::make_index_sequence<
sizeof...(Args)> indices;
1285 static constexpr std::size_t size() {
1286 return sizeof...(Args);
1290 template <
typename T>
1295 template <
typename T>
1300 template <
typename T>
1305 template <
typename T>
1312 #if SOL_IS_OFF(SOL_USE_BOOST) 1320 using check_handler_type = int(
lua_State*,
int, type, type,
const char*);
1324 #define SOL_BASE_CLASSES(T, ...) \ 1327 struct base<T> : std::true_type { \ 1328 typedef ::sol::types<__VA_ARGS__> type; \ 1331 void a_sol3_detail_function_decl_please_no_collide() 1332 #define SOL_DERIVED_CLASSES(T, ...) \ 1335 struct derive<T> : std::true_type { \ 1336 typedef ::sol::types<__VA_ARGS__> type; \ 1339 void a_sol3_detail_function_decl_please_no_collide() 1341 #endif // SOL_FORWARD_HPP 1346 #ifndef SOL_FORWARD_DETAIL_HPP 1347 #define SOL_FORWARD_DETAIL_HPP 1355 #include <type_traits> 1364 using sfinae_yes_t = std::true_type;
1365 using sfinae_no_t = std::false_type;
1367 template <
typename...>
1368 using void_t = void;
1370 template <
typename T>
1371 using unqualified = std::remove_cv<std::remove_reference_t<T>>;
1373 template <
typename T>
1374 using unqualified_t =
typename unqualified<T>::type;
1376 namespace meta_detail {
1377 template <
typename T>
1380 template <
template <
class...>
class Test,
class,
class... Args>
1383 template <
template <
class...>
class Test,
class... Args>
1384 struct is_detected<Test, void_t<Test<Args...>>, Args...> : std::true_type { };
1387 template <
template <
class...>
class Trait,
class... Args>
1390 template <
template <
class...>
class Trait,
class... Args>
1391 constexpr
inline bool is_detected_v = is_detected<Trait, Args...>::value;
1393 template <std::
size_t I>
1394 using index_value = std::integral_constant<std::size_t, I>;
1398 template <
typename T,
typename U>
1404 template <
typename T,
typename U>
1408 template <
bool B,
typename T,
typename U>
1411 namespace meta_detail {
1412 template <
typename T,
template <
typename...>
class Templ>
1414 template <
typename... T,
template <
typename...>
class Templ>
1418 template <
typename T,
template <
typename...>
class Templ>
1421 template <
typename T,
template <
typename...>
class Templ>
1424 template <
typename T>
1429 template <
typename T>
1430 using identity_t =
typename identity<T>::type;
1432 template <
typename T>
1433 using is_builtin_type = std::integral_constant<bool, std::is_arithmetic<T>::value || std::is_pointer<T>::value || std::is_array<T>::value>;
1435 namespace meta_detail {
1436 template <
typename T,
typename =
void>
1438 template <
typename T>
1441 template <
typename T>
1444 template <
typename T>
1458 using swallow = std::initializer_list<int>;
1462 template <
typename T>
1465 template <
typename T>
1469 template <
typename... Args>
1474 template <
typename... Args>
1480 template <
typename... Args>
1483 template <
typename Arg>
1486 template <
typename Arg>
1489 template <
typename... Args>
1491 typedef void front_type;
1495 template <
typename Arg,
typename... Args>
1497 typedef Arg front_type;
1501 template <std::
size_t N,
typename Tuple>
1502 using tuple_element = std::tuple_element<N, std::remove_reference_t<Tuple>>;
1504 template <std::
size_t N,
typename Tuple>
1505 using tuple_element_t = std::tuple_element_t<N, std::remove_reference_t<Tuple>>;
1507 template <std::
size_t N,
typename Tuple>
1508 using unqualified_tuple_element = unqualified<tuple_element_t<N, Tuple>>;
1510 template <std::
size_t N,
typename Tuple>
1511 using unqualified_tuple_element_t = unqualified_t<tuple_element_t<N, Tuple>>;
1520 namespace sol {
namespace meta {
1521 namespace meta_detail {
1522 template <
typename F>
1523 using detect_deducible_signature = decltype(&F::operator());
1526 template <
typename F>
1527 using call_operator_deducible =
typename is_detected<meta_detail::detect_deducible_signature, F>::type;
1529 template <
typename F>
1530 constexpr
inline bool call_operator_deducible_v = call_operator_deducible<F>::value;
1532 namespace meta_detail {
1534 template <std::
size_t I,
typename T>
1537 template <std::
size_t I>
1542 template <std::
size_t I,
typename T>
1545 template <
bool it_is_noexcept,
bool has_c_variadic,
typename T,
typename R,
typename... Args>
1548 using first_type = meta::conditional_t<std::is_void<T>::value, int, T>&;
1551 inline static constexpr
const bool is_noexcept = it_is_noexcept;
1552 inline static constexpr
bool is_member_function = std::is_void<T>::value;
1553 inline static constexpr
bool has_c_var_arg = has_c_variadic;
1554 inline static constexpr std::size_t arity =
sizeof...(Args);
1555 inline static constexpr std::size_t free_arity =
sizeof...(Args) + static_cast<std::size_t>(!std::is_void<T>::value);
1557 typedef std::tuple<Args...> args_tuple;
1558 typedef T object_type;
1559 typedef R return_type;
1560 typedef tuple_types<R> returns_list;
1561 typedef R(function_type)(Args...);
1562 typedef meta::conditional_t<std::is_void<T>::value,
args_list,
types<first_type, Args...>> free_args_list;
1563 typedef meta::conditional_t<std::is_void<T>::value, R(Args...), R(first_type, Args...)> free_function_type;
1564 typedef meta::conditional_t<std::is_void<T>::value, R (*)(Args...), R (*)(first_type, Args...)> free_function_pointer_type;
1565 typedef std::remove_pointer_t<free_function_pointer_type> signature_type;
1566 template <std::
size_t i>
1567 using arg_at = void_tuple_element_t<i, args_tuple>;
1570 template <typename Signature, bool b = call_operator_deducible<Signature>::value>
1574 template <
typename R,
typename... Args>
1576 typedef R (*function_pointer_type)(Args...);
1579 template <
typename R,
typename... Args>
1581 typedef R (*function_pointer_type)(Args...);
1584 template <
typename R,
typename... Args>
1586 typedef R (*function_pointer_type)(Args..., ...);
1589 template <
typename R,
typename... Args>
1591 typedef R (*function_pointer_type)(Args..., ...);
1596 template <
typename T,
typename R,
typename... Args>
1598 typedef R (T::*function_pointer_type)(Args...);
1601 template <
typename T,
typename R,
typename... Args>
1603 typedef R (T::*function_pointer_type)(Args..., ...);
1607 template <
typename T,
typename R,
typename... Args>
1609 typedef R (T::*function_pointer_type)(Args...)
const;
1612 template <
typename T,
typename R,
typename... Args>
1614 typedef R (T::*function_pointer_type)(Args..., ...)
const;
1617 template <
typename T,
typename R,
typename... Args>
1619 typedef R (T::*function_pointer_type)(Args...)
const volatile;
1622 template <
typename T,
typename R,
typename... Args>
1624 typedef R (T::*function_pointer_type)(Args..., ...)
const volatile;
1628 template <
typename T,
typename R,
typename... Args>
1630 typedef R (T::*function_pointer_type)(Args...) &;
1633 template <
typename T,
typename R,
typename... Args>
1635 typedef R (T::*function_pointer_type)(Args..., ...) &;
1638 template <
typename T,
typename R,
typename... Args>
1640 typedef R (T::*function_pointer_type)(Args...)
const&;
1643 template <
typename T,
typename R,
typename... Args>
1645 typedef R (T::*function_pointer_type)(Args..., ...)
const&;
1648 template <
typename T,
typename R,
typename... Args>
1650 typedef R (T::*function_pointer_type)(Args...)
const volatile&;
1653 template <
typename T,
typename R,
typename... Args>
1655 typedef R (T::*function_pointer_type)(Args..., ...)
const volatile&;
1658 template <
typename T,
typename R,
typename... Args>
1660 typedef R (T::*function_pointer_type)(Args...) &&;
1663 template <
typename T,
typename R,
typename... Args>
1665 typedef R (T::*function_pointer_type)(Args..., ...) &&;
1668 template <
typename T,
typename R,
typename... Args>
1670 typedef R (T::*function_pointer_type)(Args...)
const&&;
1673 template <
typename T,
typename R,
typename... Args>
1675 typedef R (T::*function_pointer_type)(Args..., ...)
const&&;
1678 template <
typename T,
typename R,
typename... Args>
1680 typedef R (T::*function_pointer_type)(Args...)
const volatile&&;
1683 template <
typename T,
typename R,
typename... Args>
1685 typedef R (T::*function_pointer_type)(Args..., ...)
const volatile&&;
1688 #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) 1690 template <
typename R,
typename... Args>
1692 typedef R (*function_pointer_type)(Args...) noexcept;
1695 template <
typename R,
typename... Args>
1697 typedef R (*function_pointer_type)(Args...) noexcept;
1700 template <
typename R,
typename... Args>
1702 typedef R (*function_pointer_type)(Args..., ...) noexcept;
1705 template <
typename R,
typename... Args>
1707 typedef R (*function_pointer_type)(Args..., ...) noexcept;
1710 template <
typename T,
typename R,
typename... Args>
1712 typedef R (T::*function_pointer_type)(Args...) noexcept;
1715 template <
typename T,
typename R,
typename... Args>
1717 typedef R (T::*function_pointer_type)(Args..., ...) noexcept;
1721 template <
typename T,
typename R,
typename... Args>
1723 typedef R (T::*function_pointer_type)(Args...)
const noexcept;
1726 template <
typename T,
typename R,
typename... Args>
1728 typedef R (T::*function_pointer_type)(Args..., ...)
const noexcept;
1731 template <
typename T,
typename R,
typename... Args>
1733 typedef R (T::*function_pointer_type)(Args...)
const volatile noexcept;
1736 template <
typename T,
typename R,
typename... Args>
1737 struct fx_traits<R (T::*)(Args..., ...) const volatile noexcept, false> :
public basic_traits<true, true, T, R, Args...> {
1738 typedef R (T::*function_pointer_type)(Args..., ...)
const volatile noexcept;
1741 template <
typename T,
typename R,
typename... Args>
1743 typedef R (T::*function_pointer_type)(Args...) & noexcept;
1746 template <
typename T,
typename R,
typename... Args>
1748 typedef R (T::*function_pointer_type)(Args..., ...) & noexcept;
1751 template <
typename T,
typename R,
typename... Args>
1753 typedef R (T::*function_pointer_type)(Args...)
const& noexcept;
1756 template <
typename T,
typename R,
typename... Args>
1758 typedef R (T::*function_pointer_type)(Args..., ...)
const& noexcept;
1761 template <
typename T,
typename R,
typename... Args>
1763 typedef R (T::*function_pointer_type)(Args...)
const volatile& noexcept;
1766 template <
typename T,
typename R,
typename... Args>
1767 struct fx_traits<R (T::*)(Args..., ...) const volatile& noexcept, false> :
public basic_traits<true, true, T, R, Args...> {
1768 typedef R (T::*function_pointer_type)(Args..., ...)
const volatile& noexcept;
1771 template <
typename T,
typename R,
typename... Args>
1773 typedef R (T::*function_pointer_type)(Args...) && noexcept;
1776 template <
typename T,
typename R,
typename... Args>
1778 typedef R (T::*function_pointer_type)(Args..., ...) && noexcept;
1781 template <
typename T,
typename R,
typename... Args>
1783 typedef R (T::*function_pointer_type)(Args...)
const&& noexcept;
1786 template <
typename T,
typename R,
typename... Args>
1788 typedef R (T::*function_pointer_type)(Args..., ...)
const&& noexcept;
1791 template <
typename T,
typename R,
typename... Args>
1792 struct fx_traits<R (T::*)(Args...) const volatile&& noexcept, false> :
public basic_traits<true, false, T, R, Args...> {
1793 typedef R (T::*function_pointer_type)(Args...)
const volatile&& noexcept;
1796 template <
typename T,
typename R,
typename... Args>
1797 struct fx_traits<R (T::*)(Args..., ...) const volatile&& noexcept, false> :
public basic_traits<true, true, T, R, Args...> {
1798 typedef R (T::*function_pointer_type)(Args..., ...)
const volatile&& noexcept;
1801 #endif // noexcept is part of a function's type 1803 #if SOL_IS_ON(SOL_COMPILER_VCXX) && SOL_IS_ON(SOL_PLATFORM_X86) 1804 template <
typename R,
typename... Args>
1805 struct fx_traits<R __stdcall(Args...), false> :
public basic_traits<false, false, void, R, Args...> {
1806 typedef R(__stdcall* function_pointer_type)(Args...);
1809 template <
typename R,
typename... Args>
1810 struct fx_traits<R(__stdcall*)(Args...),
false> :
public basic_traits<
false,
false, void, R, Args...> {
1811 typedef R(__stdcall* function_pointer_type)(Args...);
1814 template <
typename T,
typename R,
typename... Args>
1815 struct fx_traits<R (__stdcall T::*)(Args...), false> :
public basic_traits<false, false, T, R, Args...> {
1816 typedef R (__stdcall T::*function_pointer_type)(Args...);
1820 template <
typename T,
typename R,
typename... Args>
1821 struct fx_traits<R (__stdcall T::*)(Args...) const, false> :
public basic_traits<false, false, T, R, Args...> {
1822 typedef R (__stdcall T::*function_pointer_type)(Args...)
const;
1825 template <
typename T,
typename R,
typename... Args>
1826 struct fx_traits<R (__stdcall T::*)(Args...) const volatile, false> :
public basic_traits<false, false, T, R, Args...> {
1827 typedef R (__stdcall T::*function_pointer_type)(Args...)
const volatile;
1831 template <
typename T,
typename R,
typename... Args>
1832 struct fx_traits<R (__stdcall T::*)(Args...)&, false> :
public basic_traits<false, false, T, R, Args...> {
1833 typedef R (__stdcall T::*function_pointer_type)(Args...) &;
1836 template <
typename T,
typename R,
typename... Args>
1837 struct fx_traits<R (__stdcall T::*)(Args...) const&, false> :
public basic_traits<false, false, T, R, Args...> {
1838 typedef R (__stdcall T::*function_pointer_type)(Args...)
const&;
1841 template <
typename T,
typename R,
typename... Args>
1842 struct fx_traits<R (__stdcall T::*)(Args...) const volatile&, false> :
public basic_traits<false, false, T, R, Args...> {
1843 typedef R (__stdcall T::*function_pointer_type)(Args...)
const volatile&;
1846 template <
typename T,
typename R,
typename... Args>
1847 struct fx_traits<R (__stdcall T::*)(Args...)&&, false> :
public basic_traits<false, false, T, R, Args...> {
1848 typedef R (__stdcall T::*function_pointer_type)(Args...) &&;
1851 template <
typename T,
typename R,
typename... Args>
1852 struct fx_traits<R (__stdcall T::*)(Args...) const&&, false> :
public basic_traits<false, false, T, R, Args...> {
1853 typedef R (__stdcall T::*function_pointer_type)(Args...)
const&&;
1856 template <
typename T,
typename R,
typename... Args>
1857 struct fx_traits<R (__stdcall T::*)(Args...) const volatile&&, false> :
public basic_traits<false, false, T, R, Args...> {
1858 typedef R (__stdcall T::*function_pointer_type)(Args...)
const volatile&&;
1861 #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) 1863 template <
typename R,
typename... Args>
1864 struct fx_traits<R __stdcall(Args...) noexcept, false> :
public basic_traits<true, false, void, R, Args...> {
1865 typedef R(__stdcall* function_pointer_type)(Args...) noexcept;
1868 template <
typename R,
typename... Args>
1869 struct fx_traits<R(__stdcall*)(Args...) noexcept,
false> :
public basic_traits<
true,
false, void, R, Args...> {
1870 typedef R(__stdcall* function_pointer_type)(Args...) noexcept;
1884 template <
typename T,
typename R,
typename... Args>
1885 struct fx_traits<R (__stdcall T::*)(Args...) noexcept, false> :
public basic_traits<true, false, T, R, Args...> {
1886 typedef R (__stdcall T::*function_pointer_type)(Args...) noexcept;
1896 template <
typename T,
typename R,
typename... Args>
1897 struct fx_traits<R (__stdcall T::*)(Args...) const noexcept, false> :
public basic_traits<true, false, T, R, Args...> {
1898 typedef R (__stdcall T::*function_pointer_type)(Args...)
const noexcept;
1907 template <
typename T,
typename R,
typename... Args>
1908 struct fx_traits<R (__stdcall T::*)(Args...) const volatile noexcept, false> :
public basic_traits<true, false, T, R, Args...> {
1909 typedef R (__stdcall T::*function_pointer_type)(Args...)
const volatile noexcept;
1918 template <
typename T,
typename R,
typename... Args>
1919 struct fx_traits<R (__stdcall T::*)(Args...)& noexcept, false> :
public basic_traits<true, false, T, R, Args...> {
1920 typedef R (__stdcall T::*function_pointer_type)(Args...) & noexcept;
1929 template <
typename T,
typename R,
typename... Args>
1930 struct fx_traits<R (__stdcall T::*)(Args...) const& noexcept, false> :
public basic_traits<true, false, T, R, Args...> {
1931 typedef R (__stdcall T::*function_pointer_type)(Args...)
const& noexcept;
1940 template <
typename T,
typename R,
typename... Args>
1941 struct fx_traits<R (__stdcall T::*)(Args...) const volatile& noexcept, false> :
public basic_traits<true, false, T, R, Args...> {
1942 typedef R (__stdcall T::*function_pointer_type)(Args...)
const volatile& noexcept;
1951 template <
typename T,
typename R,
typename... Args>
1952 struct fx_traits<R (__stdcall T::*)(Args...)&& noexcept, false> :
public basic_traits<true, false, T, R, Args...> {
1953 typedef R (__stdcall T::*function_pointer_type)(Args...) && noexcept;
1962 template <
typename T,
typename R,
typename... Args>
1963 struct fx_traits<R (__stdcall T::*)(Args...) const&& noexcept, false> :
public basic_traits<true, false, T, R, Args...> {
1964 typedef R (__stdcall T::*function_pointer_type)(Args...)
const&& noexcept;
1973 template <
typename T,
typename R,
typename... Args>
1974 struct fx_traits<R (__stdcall T::*)(Args...) const volatile&& noexcept, false> :
public basic_traits<true, false, T, R, Args...> {
1975 typedef R (__stdcall T::*function_pointer_type)(Args...)
const volatile&& noexcept;
1983 #endif // noexcept is part of a function's type 1984 #endif // __stdcall x86 VC++ bug 1986 template <
typename Signature>
1987 struct fx_traits<Signature, true> :
public fx_traits<typename fx_traits<decltype(&Signature::operator())>::function_type, false> { };
1989 template <typename Signature, bool b = std::is_member_object_pointer<Signature>::value>
1992 template <
typename R,
typename T>
1994 typedef meta::conditional_t<std::is_array_v<R>, std::add_lvalue_reference_t<R>, R> return_type;
1995 typedef return_type Arg;
1996 typedef T object_type;
1997 using signature_type = R(T::*);
1998 inline static constexpr
bool is_noexcept =
false;
1999 inline static constexpr
bool is_member_function =
false;
2000 inline static constexpr std::size_t arity = 1;
2001 inline static constexpr std::size_t free_arity = 2;
2002 typedef std::tuple<Arg> args_tuple;
2005 typedef meta::tuple_types<return_type> returns_list;
2006 typedef return_type(function_type)(T&, return_type);
2007 typedef return_type (*function_pointer_type)(T&, Arg);
2008 typedef return_type (*free_function_pointer_type)(T&, Arg);
2009 template <std::
size_t i>
2010 using arg_at = void_tuple_element_t<i, args_tuple>;
2015 template <
typename Signature>
2018 namespace meta_detail {
2019 template <
typename,
bool>
2022 template <
typename T>
2026 template <
typename T>
2029 template <
typename T>
2032 template <
typename Signature>
2035 template <
typename Signature>
2036 using function_signature_t =
typename bind_traits<Signature>::signature_type;
2038 template <
typename Signature>
2039 using function_return_t =
typename bind_traits<Signature>::return_type;
2047 #include <type_traits> 2053 namespace meta_detail {
2054 template <
typename T>
2055 using is_dereferenceable_test = decltype(*std::declval<T>());
2057 template <
typename T>
2058 using is_explicitly_dereferenceable_test = decltype(std::declval<T>().
operator*());
2061 template <
typename T>
2062 using is_pointer_like = std::integral_constant<bool,
2063 !std::is_array_v<T> && (std::is_pointer_v<T> || is_detected_v<meta_detail::is_explicitly_dereferenceable_test, T>)>;
2065 template <
typename T>
2066 constexpr
inline bool is_pointer_like_v = is_pointer_like<T>::value;
2071 template <
typename T>
2072 auto unwrap(T&& item) -> decltype(std::forward<T>(item)) {
2073 return std::forward<T>(item);
2076 template <
typename T>
2077 T& unwrap(std::reference_wrapper<T> arg) {
2081 template <
typename T>
2082 inline decltype(
auto) deref(T&& item) {
2083 using Tu = meta::unqualified_t<T>;
2084 if constexpr (meta::is_pointer_like_v<Tu>) {
2085 return *std::forward<T>(item);
2088 return std::forward<T>(item);
2092 template <
typename T>
2093 inline decltype(
auto) deref_move_only(T&& item) {
2094 using Tu = meta::unqualified_t<T>;
2095 if constexpr (meta::is_pointer_like_v<Tu> && !std::is_pointer_v<Tu> && !std::is_copy_constructible_v<Tu>) {
2096 return *std::forward<T>(item);
2099 return std::forward<T>(item);
2103 template <
typename T>
2104 inline T* ptr(T& val) {
2105 return std::addressof(val);
2108 template <
typename T>
2109 inline T* ptr(std::reference_wrapper<T> val) {
2110 return std::addressof(val.get());
2113 template <
typename T>
2114 inline T* ptr(T* val) {
2126 #include <string_view> 2127 #include <functional> 2130 template <
typename C,
typename T = std::
char_traits<C>>
2131 using basic_string_view = std::basic_string_view<C, T>;
2133 typedef std::string_view string_view;
2134 typedef std::wstring_view wstring_view;
2135 typedef std::u16string_view u16string_view;
2136 typedef std::u32string_view u32string_view;
2137 typedef std::hash<std::string_view> string_view_hash;
2142 #include <type_traits> 2145 #include <functional> 2149 #if SOL_IS_ON(SOL_STD_VARIANT) 2151 #endif // variant is weird on XCode, thanks XCode 2153 namespace sol {
namespace meta {
2154 template <
typename T>
2159 template <
typename T>
2164 template <
typename T>
2165 using unwrapped_t =
typename unwrapped<T>::type;
2167 template <
typename T>
2170 template <
typename T>
2171 using unwrap_unqualified_t =
typename unwrap_unqualified<T>::type;
2173 template <
typename T>
2176 template <
typename R,
typename T>
2181 template <
typename R,
typename T>
2186 template <
typename T>
2189 template <
typename T,
typename...>
2192 template <
typename T,
typename U,
typename... Args>
2193 struct all_same<T, U, Args...> : std::integral_constant<bool, std::is_same<T, U>::value && all_same<T, Args...>::value> { };
2195 template <
typename T,
typename...>
2198 template <
typename T,
typename U,
typename... Args>
2199 struct any_same<T, U, Args...> : std::integral_constant<bool, std::is_same<T, U>::value || any_same<T, Args...>::value> { };
2201 template <
typename T,
typename... Args>
2202 constexpr
inline bool any_same_v =
any_same<T, Args...>::value;
2205 using boolean = std::integral_constant<bool, B>;
2208 constexpr
inline bool boolean_v = boolean<B>::value;
2210 template <
typename T>
2211 using neg = boolean<!T::value>;
2213 template <
typename T>
2214 constexpr
inline bool neg_v = neg<T>::value;
2216 template <
typename... Args>
2217 struct all : boolean<true> { };
2219 template <
typename T,
typename... Args>
2220 struct all<T, Args...> : std::conditional_t<T::value, all<Args...>, boolean<false>> { };
2222 template <
typename... Args>
2223 struct any : boolean<false> { };
2225 template <
typename T,
typename... Args>
2226 struct any<T, Args...> : std::conditional_t<T::value, boolean<true>, any<Args...>> { };
2228 template <
typename... Args>
2229 constexpr
inline bool all_v =
all<Args...>::value;
2231 template <
typename... Args>
2232 constexpr
inline bool any_v =
any<Args...>::value;
2234 enum class enable_t { _ };
2236 constexpr
const auto enabler = enable_t::_;
2238 template <
bool value,
typename T =
void>
2239 using disable_if_t = std::enable_if_t<!value, T>;
2241 template <
typename... Args>
2242 using enable = std::enable_if_t<
all<Args...>::value, enable_t>;
2244 template <
typename... Args>
2245 using disable = std::enable_if_t<neg<
all<Args...>>::value, enable_t>;
2247 template <
typename... Args>
2248 using enable_any = std::enable_if_t<
any<Args...>::value, enable_t>;
2250 template <
typename... Args>
2251 using disable_any = std::enable_if_t<neg<
any<Args...>>::value, enable_t>;
2253 template <
typename V,
typename... Vs>
2256 template <
typename V,
typename Vs1,
typename... Vs>
2257 struct find_in_pack_v<V, Vs1, Vs...> :
any<boolean<(V::value == Vs1::value)>, find_in_pack_v<V, Vs...>> { };
2259 namespace meta_detail {
2260 template <std::size_t I,
typename T,
typename... Args>
2263 template <std::size_t I,
typename T,
typename T1,
typename... Args>
2265 : conditional_t<std::is_same<T, T1>::value, std::integral_constant<std::ptrdiff_t, I>, index_in_pack<I + 1, T, Args...>> { };
2268 template <
typename T,
typename... Args>
2271 template <
typename T,
typename List>
2274 template <
typename T,
typename... Args>
2277 template <std::size_t I,
typename... Args>
2280 template <std::size_t I,
typename... Args>
2281 using at_in_pack_t =
typename at_in_pack<I, Args...>::type;
2283 template <std::size_t I,
typename Arg,
typename... Args>
2284 struct at_in_pack<I, Arg, Args...> : std::conditional<I == 0, Arg, at_in_pack_t<I - 1, Args...>> { };
2286 template <
typename Arg,
typename... Args>
2291 namespace meta_detail {
2292 template <
typename,
typename TI>
2293 using on_even = meta::boolean<(TI::value % 2) == 0>;
2295 template <
typename,
typename TI>
2296 using on_odd = meta::boolean<(TI::value % 2) == 1>;
2298 template <
typename,
typename>
2299 using on_always = std::true_type;
2301 template <
template <
typename...>
class When, std::size_t Limit, std::size_t I,
template <
typename...>
class Pred,
typename... Ts>
2303 template <
template <
typename...>
class When, std::size_t Limit, std::size_t I,
template <
typename...>
class Pred,
typename T,
typename... Ts>
2304 struct count_when_for_pack<When, Limit, I, Pred, T, Ts...> : conditional_t < sizeof...(Ts)
2306 || Limit<2, std::integral_constant<std::size_t, I + static_cast<std::size_t>(Limit != 0 && Pred<T>::value)>,
2307 count_when_for_pack<When, Limit - static_cast<std::size_t>(When<T, std::integral_constant<std::size_t, I>>::value),
2308 I + static_cast<std::size_t>(When<T, std::integral_constant<std::size_t, I>>::value&& Pred<T>::value), Pred, Ts...>> { };
2311 template <template <typename...> class Pred, typename... Ts>
2312 struct count_for_pack : meta_detail::count_when_for_pack<meta_detail::on_always, sizeof...(Ts), 0, Pred, Ts...> { };
2314 template <template <typename...> class Pred, typename... Ts>
2315 inline constexpr std::size_t count_for_pack_v = count_for_pack<Pred, Ts...>::value;
2317 template <template <typename...> class Pred, typename List>
2320 template <template <typename...> class Pred, typename... Args>
2321 struct count_for<Pred, types<Args...>> : count_for_pack<Pred, Args...> { };
2323 template <std::size_t Limit, template <typename...> class Pred, typename... Ts>
2324 struct count_for_to_pack : meta_detail::count_when_for_pack<meta_detail::on_always, Limit, 0, Pred, Ts...> { };
2326 template <std::size_t Limit, template <typename...> class Pred, typename... Ts>
2327 inline constexpr std::size_t count_for_to_pack_v = count_for_to_pack<Limit, Pred, Ts...>::value;
2329 template <template <typename...> class When, std::size_t Limit, template <typename...> class Pred, typename... Ts>
2330 struct count_when_for_to_pack : meta_detail::count_when_for_pack<When, Limit, 0, Pred, Ts...> { };
2332 template <template <typename...> class When, std::size_t Limit, template <typename...> class Pred, typename... Ts>
2333 inline constexpr std::size_t count_when_for_to_pack_v = count_when_for_to_pack<When, Limit, Pred, Ts...>::value;
2335 template <template <typename...> class Pred, typename... Ts>
2336 using count_even_for_pack = count_when_for_to_pack<meta_detail::on_even, sizeof...(Ts), Pred, Ts...>;
2338 template <template <typename...> class Pred, typename... Ts>
2339 inline constexpr std::size_t count_even_for_pack_v = count_even_for_pack<Pred, Ts...>::value;
2341 template <template <typename...> class Pred, typename... Ts>
2342 using count_odd_for_pack = count_when_for_to_pack<meta_detail::on_odd, sizeof...(Ts), Pred, Ts...>;
2344 template <template <typename...> class Pred, typename... Ts>
2345 inline constexpr std::size_t count_odd_for_pack_v = count_odd_for_pack<Pred, Ts...>::value;
2347 template <typename... Args>
2348 struct return_type {
2349 typedef std::tuple<Args...> type;
2352 template <typename T>
2353 struct return_type<T> {
2358 struct return_type<> {
2362 template <typename... Args>
2363 using return_type_t = typename return_type<Args...>::type;
2365 namespace meta_detail {
2367 struct always_true : std::true_type { };
2368 struct is_invokable_tester {
2369 template <typename Fun, typename... Args>
2370 static always_true<decltype(std::declval<Fun>()(std::declval<Args>()...))> test(int);
2371 template <typename...>
2372 static std::false_type test(...);
2376 template <typename T>
2377 struct is_invokable;
2378 template <typename Fun, typename... Args>
2379 struct is_invokable<Fun(Args...)> : decltype(meta_detail::is_invokable_tester::test<Fun, Args...>(0)) { };
2381 namespace meta_detail {
2383 template <typename T, typename = void>
2384 struct is_invocable : std::is_function<std::remove_pointer_t<T>> { };
2386 template <typename T>
2387 struct is_invocable<T,
2388 std::enable_if_t<std::is_final<unqualified_t<T>>::value && std::is_class<unqualified_t<T>>::value
2389 && std::is_same<decltype(void(&T::operator())), void>::value>> { };
2391 template <typename T>
2392 struct is_invocable<T,
2393 std::enable_if_t<!std::is_final<unqualified_t<T>>::value && std::is_class<unqualified_t<T>>::value
2394 && std::is_destructible<unqualified_t<T>>::value>> {
2396 void operator()() {};
2398 struct Derived : T, F { };
2399 template <typename U, U>
2402 template <typename V>
2403 static sfinae_no_t test(Check<void (F::*)(), &V::operator()>*);
2406 static sfinae_yes_t test(...);
2408 static constexpr bool value = std::is_same_v<decltype(test<Derived>(0)), sfinae_yes_t>;
2411 template <typename T>
2412 struct is_invocable<T,
2413 std::enable_if_t<!std::is_final<unqualified_t<T>>::value && std::is_class<unqualified_t<T>>::value
2414 && !std::is_destructible<unqualified_t<T>>::value>> {
2416 void operator()() {};
2418 struct Derived : T, F {
2419 ~Derived() = delete;
2421 template <typename U, U>
2424 template <typename V>
2425 static sfinae_no_t test(Check<void (F::*)(), &V::operator()>*);
2428 static sfinae_yes_t test(...);
2430 static constexpr bool value = std::is_same_v<decltype(test<Derived>(0)), sfinae_yes_t>;
2433 struct has_begin_end_impl {
2434 template <typename T, typename U = unqualified_t<T>, typename B = decltype(std::declval<U&>().begin()),
2435 typename E = decltype(std::declval<U&>().end())>
2436 static std::true_type test(int);
2438 template <typename...>
2439 static std::false_type test(...);
2442 struct has_key_type_impl {
2443 template <typename T, typename U = unqualified_t<T>, typename V = typename U::key_type>
2444 static std::true_type test(int);
2446 template <typename...>
2447 static std::false_type test(...);
2450 struct has_key_comp_impl {
2451 template <typename T, typename V = decltype(std::declval<unqualified_t<T>>().key_comp())>
2452 static std::true_type test(int);
2454 template <typename...>
2455 static std::false_type test(...);
2458 struct has_load_factor_impl {
2459 template <typename T, typename V = decltype(std::declval<unqualified_t<T>>().load_factor())>
2460 static std::true_type test(int);
2462 template <typename...>
2463 static std::false_type test(...);
2466 struct has_mapped_type_impl {
2467 template <typename T, typename V = typename unqualified_t<T>::mapped_type>
2468 static std::true_type test(int);
2470 template <typename...>
2471 static std::false_type test(...);
2474 struct has_value_type_impl {
2475 template <typename T, typename V = typename unqualified_t<T>::value_type>
2476 static std::true_type test(int);
2478 template <typename...>
2479 static std::false_type test(...);
2482 struct has_iterator_impl {
2483 template <typename T, typename V = typename unqualified_t<T>::iterator>
2484 static std::true_type test(int);
2486 template <typename...>
2487 static std::false_type test(...);
2490 struct has_key_value_pair_impl {
2491 template <typename T, typename U = unqualified_t<T>, typename V = typename U::value_type, typename F = decltype(std::declval<V&>().first),
2492 typename S = decltype(std::declval<V&>().second)>
2493 static std::true_type test(int);
2495 template <typename...>
2496 static std::false_type test(...);
2499 template <typename T>
2500 struct has_push_back_test {
2502 template <typename C>
2503 static sfinae_yes_t test(decltype(std::declval<C>().push_back(std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*);
2504 template <typename C>
2505 static sfinae_no_t test(...);
2508 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>;
2511 template <typename T>
2512 struct has_insert_with_iterator_test {
2514 template <typename C>
2515 static sfinae_yes_t test(decltype(std::declval<C>().insert(
2516 std::declval<std::add_rvalue_reference_t<typename C::iterator>>(), std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*);
2517 template <typename C>
2518 static sfinae_no_t test(...);
2521 static constexpr bool value = !std::is_same_v<decltype(test<T>(0)), sfinae_no_t>;
2524 template <typename T>
2525 struct has_insert_test {
2527 template <typename C>
2528 static sfinae_yes_t test(decltype(std::declval<C>().insert(std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*);
2529 template <typename C>
2530 static sfinae_no_t test(...);
2533 static constexpr bool value = !std::is_same_v<decltype(test<T>(0)), sfinae_no_t>;
2536 template <typename T>
2537 struct has_insert_after_test {
2539 template <typename C>
2540 static sfinae_yes_t test(decltype(std::declval<C>().insert_after(std::declval<std::add_rvalue_reference_t<typename C::const_iterator>>(),
2541 std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*);
2542 template <typename C>
2543 static sfinae_no_t test(...);
2546 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>;
2549 template <typename T>
2550 struct has_size_test {
2552 template <typename C>
2553 static sfinae_yes_t test(decltype(std::declval<C>().size())*);
2554 template <typename C>
2555 static sfinae_no_t test(...);
2558 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>;
2561 template <typename T>
2562 struct has_max_size_test {
2564 template <typename C>
2565 static sfinae_yes_t test(decltype(std::declval<C>().max_size())*);
2566 template <typename C>
2567 static sfinae_no_t test(...);
2570 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>;
2573 template <typename T>
2574 struct has_to_string_test {
2576 template <typename C>
2577 static sfinae_yes_t test(decltype(std::declval<C>().to_string())*);
2578 template <typename C>
2579 static sfinae_no_t test(...);
2582 static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>;
2585 template <typename T, typename U, typename = void>
2586 class supports_op_less_test : public std::false_type { };
2587 template <typename T, typename U>
2588 class supports_op_less_test<T, U, void_t<decltype(std::declval<T&>() < std::declval<U&>())>>
2589 : public std::integral_constant<bool,
2590 #if SOL_IS_ON(SOL_STD_VARIANT)
2591 !is_specialization_of_v<unqualified_t<T>, std::variant> && !is_specialization_of_v<unqualified_t<U>, std::variant>
2598 template <typename T, typename U, typename = void>
2599 class supports_op_equal_test : public std::false_type { };
2600 template <typename T, typename U>
2601 class supports_op_equal_test<T, U, void_t<decltype(std::declval<T&>() == std::declval<U&>())>>
2602 : public std::integral_constant<bool,
2603 #if SOL_IS_ON(SOL_STD_VARIANT)
2604 !is_specialization_of_v<unqualified_t<T>, std::variant> && !is_specialization_of_v<unqualified_t<U>, std::variant>
2611 template <typename T, typename U, typename = void>
2612 class supports_op_less_equal_test : public std::false_type { };
2613 template <typename T, typename U>
2614 class supports_op_less_equal_test<T, U, void_t<decltype(std::declval<T&>() <= std::declval<U&>())>>
2615 : public std::integral_constant<bool,
2616 #if SOL_IS_ON(SOL_STD_VARIANT)
2617 !is_specialization_of_v<unqualified_t<T>, std::variant> && !is_specialization_of_v<unqualified_t<U>, std::variant>
2624 template <typename T, typename U, typename = void>
2625 class supports_op_left_shift_test : public std::false_type { };
2626 template <typename T, typename U>
2627 class supports_op_left_shift_test<T, U, void_t<decltype(std::declval<T&>() << std::declval<U&>())>> : public std::true_type { };
2629 template <typename T, typename = void>
2630 class supports_adl_to_string_test : public std::false_type { };
2631 template <typename T>
2632 class supports_adl_to_string_test<T, void_t<decltype(to_string(std::declval<const T&>()))>> : public std::true_type { };
2634 template <typename T, bool b>
2635 struct is_matched_lookup_impl : std::false_type { };
2636 template <typename T>
2637 struct is_matched_lookup_impl<T, true> : std::is_same<typename T::key_type, typename T::value_type> { };
2639 template <typename T>
2640 using non_void_t = meta::conditional_t<std::is_void_v<T>, ::sol::detail::unchecked_t, T>;
2643 template <typename T, typename U = T>
2644 class supports_op_less : public meta_detail::supports_op_less_test<T, U> { };
2646 template <typename T, typename U = T>
2647 class supports_op_equal : public meta_detail::supports_op_equal_test<T, U> { };
2649 template <typename T, typename U = T>
2650 class supports_op_less_equal : public meta_detail::supports_op_less_equal_test<T, U> { };
2652 template <typename T, typename U = T>
2653 class supports_op_left_shift : public meta_detail::supports_op_left_shift_test<T, U> { };
2655 template <typename T>
2656 class supports_adl_to_string : public meta_detail::supports_adl_to_string_test<T> { };
2658 template <typename T>
2659 class supports_to_string_member : public meta::boolean<meta_detail::has_to_string_test<meta_detail::non_void_t<T>>::value> { };
2661 template <typename T>
2662 using is_invocable = boolean<meta_detail::is_invocable<T>::value>;
2664 template <typename T>
2665 constexpr inline bool is_invocable_v = is_invocable<T>::value;
2667 template <typename T>
2668 struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test<T>(0)) { };
2670 template <typename T>
2671 constexpr inline bool has_begin_end_v = has_begin_end<T>::value;
2673 template <typename T>
2674 struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test<T>(0)) { };
2676 template <typename T>
2677 struct has_key_type : decltype(meta_detail::has_key_type_impl::test<T>(0)) { };
2679 template <typename T>
2680 struct has_key_comp : decltype(meta_detail::has_key_comp_impl::test<T>(0)) { };
2682 template <typename T>
2683 struct has_load_factor : decltype(meta_detail::has_load_factor_impl::test<T>(0)) { };
2685 template <typename T>
2686 struct has_mapped_type : decltype(meta_detail::has_mapped_type_impl::test<T>(0)) { };
2688 template <typename T>
2689 struct has_iterator : decltype(meta_detail::has_iterator_impl::test<T>(0)) { };
2691 template <typename T>
2692 struct has_value_type : decltype(meta_detail::has_value_type_impl::test<T>(0)) { };
2694 template <typename T>
2695 using has_push_back = meta::boolean<meta_detail::has_push_back_test<T>::value>;
2697 template <typename T>
2698 using has_max_size = meta::boolean<meta_detail::has_max_size_test<T>::value>;
2700 template <typename T>
2701 using has_insert = meta::boolean<meta_detail::has_insert_test<T>::value>;
2703 template <typename T>
2704 using has_insert_with_iterator = meta::boolean<meta_detail::has_insert_with_iterator_test<T>::value>;
2706 template <typename T>
2707 using has_insert_after = meta::boolean<meta_detail::has_insert_after_test<T>::value>;
2709 template <typename T>
2710 using has_size = meta::boolean<meta_detail::has_size_test<T>::value>;
2712 template <typename T>
2713 using is_associative = meta::all<has_key_type<T>, has_key_value_pair<T>, has_mapped_type<T>>;
2715 template <typename T>
2716 using is_lookup = meta::all<has_key_type<T>, has_value_type<T>>;
2718 template <typename T>
2719 using is_ordered = meta::all<has_key_comp<T>, meta::neg<has_load_factor<T>>>;
2721 template <typename T>
2722 using is_matched_lookup = meta_detail::is_matched_lookup_impl<T, is_lookup<T>::value>;
2724 template <typename T>
2725 using is_initializer_list = meta::is_specialization_of<T, std::initializer_list>;
2727 template <typename T>
2728 constexpr inline bool is_initializer_list_v = is_initializer_list<T>::value;
2730 template <typename T, typename CharT = char>
2731 using is_string_literal_array_of = boolean<std::is_array_v<T> && std::is_same_v<std::remove_all_extents_t<T>, CharT>>;
2733 template <typename T, typename CharT = char>
2734 constexpr inline bool is_string_literal_array_of_v = is_string_literal_array_of<T, CharT>::value;
2736 template <typename T>
2737 using is_string_literal_array = boolean<std::is_array_v<T> && any_same_v<std::remove_all_extents_t<T>, char,
2738 #if SOL_IS_ON(SOL_CHAR8_T)
2741 char16_t, char32_t, wchar_t>>;
2743 template <typename T>
2744 constexpr inline bool is_string_literal_array_v = is_string_literal_array<T>::value;
2746 template <typename T, typename CharT>
2747 struct is_string_of : std::false_type { };
2749 template <typename CharT, typename CharTargetT, typename TraitsT, typename AllocT>
2750 struct is_string_of<std::basic_string<CharT, TraitsT, AllocT>, CharTargetT> : std::is_same<CharT, CharTargetT> { };
2752 template <typename T, typename CharT>
2753 constexpr inline bool is_string_of_v = is_string_of<T, CharT>::value;
2755 template <typename T, typename CharT>
2756 struct is_string_view_of : std::false_type { };
2758 template <typename CharT, typename CharTargetT, typename TraitsT>
2759 struct is_string_view_of<std::basic_string_view<CharT, TraitsT>, CharTargetT> : std::is_same<CharT, CharTargetT> { };
2761 template <typename T, typename CharT>
2762 constexpr inline bool is_string_view_of_v = is_string_view_of<T, CharT>::value;
2764 template <typename T>
2765 using is_string_like
2766 = meta::boolean<is_specialization_of_v<T, std::basic_string> || is_specialization_of_v<T, std::basic_string_view> || is_string_literal_array_v<T>>;
2768 template <typename T>
2769 constexpr inline bool is_string_like_v = is_string_like<T>::value;
2771 template <typename T, typename CharT = char>
2772 using is_string_constructible = meta::boolean<
2773 is_string_literal_array_of_v<T,
2774 CharT> || std::is_same_v<T, const CharT*> || std::is_same_v<T, CharT> || is_string_of_v<T, CharT> || std::is_same_v<T, std::initializer_list<CharT>> || is_string_view_of_v<T, CharT> || std::is_null_pointer_v<T>>;
2776 template <typename T, typename CharT = char>
2777 constexpr inline bool is_string_constructible_v = is_string_constructible<T, CharT>::value;
2779 template <typename T>
2780 using is_string_like_or_constructible = meta::boolean<is_string_like_v<T> || is_string_constructible_v<T>>;
2782 template <typename T>
2783 struct is_pair : std::false_type { };
2785 template <typename T1, typename T2>
2786 struct is_pair<std::pair<T1, T2>> : std::true_type { };
2788 template <typename T, typename Char>
2789 using is_c_str_of = any<std::is_same<T, const Char*>, std::is_same<T, Char const* const>, std::is_same<T, Char*>, is_string_literal_array_of<T, Char>>;
2791 template <typename T, typename Char>
2792 constexpr inline bool is_c_str_of_v = is_c_str_of<T, Char>::value;
2794 template <typename T>
2795 using is_c_str = is_c_str_of<T, char>;
2797 template <typename T>
2798 constexpr inline bool is_c_str_v = is_c_str<T>::value;
2800 template <typename T, typename Char>
2801 using is_c_str_or_string_of = any<is_c_str_of<T, Char>, is_string_of<T, Char>>;
2803 template <typename T, typename Char>
2804 constexpr inline bool is_c_str_or_string_of_v = is_c_str_or_string_of<T, Char>::value;
2806 template <typename T>
2807 using is_c_str_or_string = is_c_str_or_string_of<T, char>;
2809 template <typename T>
2810 constexpr inline bool is_c_str_or_string_v = is_c_str_or_string<T>::value;
2812 template <typename T>
2813 struct is_move_only : all<neg<std::is_reference<T>>, neg<std::is_copy_constructible<unqualified_t<T>>>, std::is_move_constructible<unqualified_t<T>>> { };
2815 template <typename T>
2816 using is_not_move_only = neg<is_move_only<T>>;
2818 namespace meta_detail {
2819 template <typename T>
2820 decltype(auto) force_tuple(T&& x) {
2821 if constexpr (meta::is_specialization_of_v<meta::unqualified_t<T>, std::tuple>) {
2822 return std::forward<T>(x);
2825 return std::tuple<T>(std::forward<T>(x));
2830 template <typename... X>
2831 decltype(auto) tuplefy(X&&... x) {
2832 return std::tuple_cat(meta_detail::force_tuple(std::forward<X>(x))...);
2835 template <typename T, typename = void>
2836 struct iterator_tag {
2837 using type = std::input_iterator_tag;
2840 template <typename T>
2841 struct iterator_tag<T, conditional_t<false, typename std::iterator_traits<T>::iterator_category, void>> {
2842 using type = typename std::iterator_traits<T>::iterator_category;
2851 const bool default_safe_function_calls =
2852 #if SOL_IS_ON(SOL_SAFE_FUNCTION_CALLS)
2859 namespace meta { namespace meta_detail {
2862 namespace stack { namespace stack_detail {
2863 using undefined_method_func = void (*)(stack_reference);
2865 template <typename T>
2866 void set_undefined_methods_on(stack_reference);
2868 struct undefined_metatable;
2877 #if SOL_IS_ON(SOL2_CI)
2882 _set_abort_behavior(0, _WRITE_ABORT_MSG);
2885 } inline sol2_ci_dont_lock_ci_please = {};
2889 #if SOL_IS_ON(SOL_USER_C_ASSERT)
2890 #define sol_c_assert(...) SOL_C_ASSERT(__VA_ARGS__)
2892 #if SOL_IS_ON(SOL_DEBUG_BUILD)
2893 #include <exception>
2897 #define sol_c_assert(...) \
2899 if (!(__VA_ARGS__)) { \
2900 std::cerr << "Assertion `" #__VA_ARGS__ "` failed in " << __FILE__ << " line " << __LINE__ << std::endl; \
2905 #define sol_c_assert(...) \
2908 (void)(__VA_ARGS__); \
2914 #if SOL_IS_ON(SOL_USER_M_ASSERT)
2915 #define sol_m_assert(message, ...) SOL_M_ASSERT(message, __VA_ARGS__)
2917 #if SOL_IS_ON(SOL_DEBUG_BUILD)
2918 #include <exception>
2922 #define sol_m_assert(message, ...) \
2924 if (!(__VA_ARGS__)) { \
2925 std::cerr << "Assertion `" #__VA_ARGS__ "` failed in " << __FILE__ << " line " << __LINE__ << ": " << message << std::endl; \
2930 #define sol_m_assert(message, ...) \
2933 (void)(__VA_ARGS__); \
2934 (void)sizeof(message); \
2948 #if SOL_IS_ON(SOL_USE_CXX_LUA)
2951 #include <lauxlib.h>
2952 #elif SOL_IS_ON(SOL_USE_LUA_HPP)
2957 #include <lauxlib.h>
2962 #if defined(SOL_LUAJIT)
2963 #if (SOL_LUAJIT != 0)
2964 #define SOL_USE_LUAJIT_I_ SOL_ON
2966 #define SOL_USE_LUAJIT_I_ SOL_OFF
2968 #elif defined(LUAJIT_VERSION)
2969 #define SOL_USE_LUAJIT_I_ SOL_ON
2971 #define SOL_USE_LUAJIT_I_ SOL_DEFAULT_OFF
2974 #if SOL_IS_ON(SOL_USE_CXX_LUAJIT)
2976 #elif SOL_IS_ON(SOL_USE_LUAJIT)
2982 #if defined(SOL_LUAJIT_VERSION)
2983 #define SOL_LUAJIT_VERSION_I_ SOL_LUAJIT_VERSION
2984 #elif SOL_IS_ON(SOL_USE_LUAJIT)
2985 #define SOL_LUAJIT_VERSION_I_ LUAJIT_VERSION_NUM
2987 #define SOL_LUAJIT_VERSION_I_ 0
2990 #if defined(SOL_LUAJIT_FFI_DISABLED)
2991 #define SOL_LUAJIT_FFI_DISABLED_I_ SOL_ON
2992 #elif defined(LUAJIT_DISABLE_FFI)
2993 #define SOL_LUAJIT_FFI_DISABLED_I_ SOL_ON
2995 #define SOL_LUAJIT_FFI_DISABLED_I_ SOL_DEFAULT_OFF
2998 #if defined(MOONJIT_VERSION)
2999 #define SOL_USE_MOONJIT_I_ SOL_ON
3001 #define SOL_USE_MOONJIT_I_ SOL_OFF
3004 #if !defined(SOL_LUA_VERSION)
3005 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 502
3006 #define SOL_LUA_VERSION LUA_VERSION_NUM
3007 #elif defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
3008 #define SOL_LUA_VERSION LUA_VERSION_NUM
3009 #elif !defined(LUA_VERSION_NUM) || !(LUA_VERSION_NUM)
3011 #define SOL_LUA_VERSION 500
3014 #define SOL_LUA_VERSION 504
3018 #if defined(SOL_LUA_VERSION)
3019 #define SOL_LUA_VERSION_I_ SOL_LUA_VERSION
3021 #define SOL_LUA_VERSION_I_ 504
3024 #if defined(SOL_EXCEPTIONS_ALWAYS_UNSAFE)
3025 #if (SOL_EXCEPTIONS_ALWAYS_UNSAFE != 0)
3026 #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_OFF
3028 #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_ON
3030 #elif defined(SOL_EXCEPTIONS_SAFE_PROPAGATION)
3031 #if (SOL_EXCEPTIONS_SAFE_PROPAGATION != 0)
3032 #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_ON
3034 #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_OFF
3036 #elif SOL_LUAJIT_VERSION_I_ >= 20100
3038 #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_ON
3039 #elif SOL_LUAJIT_VERSION_I_ >= 20000
3041 #if SOL_IS_ON(SOL_PLATFORM_X64)
3042 #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_ON
3044 #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_OFF
3050 #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_OFF
3053 #if defined(SOL_EXCEPTIONS_CATCH_ALL)
3054 #if (SOL_EXCEPTIONS_CATCH_ALL != 0)
3055 #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_ON
3057 #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_OFF
3060 #if SOL_IS_ON(SOL_USE_LUAJIT)
3061 #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_OFF
3062 #elif SOL_IS_ON(SOL_USE_CXX_LUAJIT)
3063 #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_OFF
3064 #elif SOL_IS_ON(SOL_USE_CXX_LUA)
3065 #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_OFF
3067 #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_ON
3071 #if defined(SOL_LUAJIT_USE_EXCEPTION_TRAMPOLINE)
3072 #if (SOL_LUAJIT_USE_EXCEPTION_TRAMPOLINE != 0)
3073 #define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_ON
3075 #define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_OFF
3078 #if SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS) && SOL_IS_ON(SOL_USE_LUAJIT)
3079 #define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_ON
3081 #define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_DEFAULT_OFF
3085 #if defined(SOL_LUAL_STREAM_HAS_CLOSE_FUNCTION)
3086 #if (SOL_LUAL_STREAM_HAS_CLOSE_FUNCTION != 0)
3087 #define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_ON
3089 #define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_OFF
3092 #if SOL_IS_OFF(SOL_USE_LUAJIT) && (SOL_LUA_VERSION > 501)
3093 #define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_ON
3095 #define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_DEFAULT_OFF
3099 #if defined (SOL_LUA_BIT32_LIB)
3100 #if SOL_LUA_BIT32_LIB != 0
3101 #define SOL_LUA_BIT32_LIB_I_ SOL_ON
3103 #define SOL_LUA_BIT32_LIB_I_ SOL_OFF
3108 #if (SOL_LUA_VERSION_I_ == 502) || (defined(LUA_COMPAT_BITLIB) && (LUA_COMPAT_BITLIB != 0)) || (SOL_LUA_VERSION_I_ < 504 && (defined(LUA_COMPAT_5_2) && (LUA_COMPAT_5_2 != 0)))
3109 #define SOL_LUA_BIT32_LIB_I_ SOL_ON
3111 #define SOL_LUA_BIT32_LIB_I_ SOL_DEFAULT_OFF
3115 #if defined (SOL_LUA_NIL_IN_TABLES)
3116 #if SOL_LUA_NIL_IN_TABLES != 0
3117 #define SOL_LUA_NIL_IN_TABLES_I_ SOL_ON
3119 #define SOL_LUA_NIL_IN_TABLES_I_ SOL_OFF
3122 #if defined(LUA_NILINTABLE) && (LUA_NILINTABLE != 0)
3123 #define SOL_LUA_NIL_IN_TABLES_I_ SOL_DEFAULT_ON
3125 #define SOL_LUA_NIL_IN_TABLES_I_ SOL_DEFAULT_OFF
3131 #if SOL_IS_ON(SOL_USE_COMPATIBILITY_LAYER)
3133 #if SOL_IS_ON(SOL_USE_CXX_LUA) || SOL_IS_ON(SOL_USE_CXX_LUAJIT)
3134 #ifndef COMPAT53_LUA_CPP
3135 #define COMPAT53_LUA_CPP 1
3138 #ifndef COMPAT53_INCLUDE_SOURCE
3139 #define COMPAT53_INCLUDE_SOURCE 1
3144 #ifndef KEPLER_PROJECT_COMPAT53_H_
3145 #define KEPLER_PROJECT_COMPAT53_H_
3150 #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
3154 #include <lauxlib.h>
3156 #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
3160 #ifndef COMPAT53_PREFIX
3165 # define COMPAT53_PREFIX kp_compat53
3168 #ifndef COMPAT53_API
3169 # if defined(COMPAT53_INCLUDE_SOURCE) && COMPAT53_INCLUDE_SOURCE
3170 # if defined(__GNUC__) || defined(__clang__)
3171 # define COMPAT53_API __attribute__((__unused__)) static inline
3173 # define COMPAT53_API static inline
3177 # define COMPAT53_API extern
3181 #define COMPAT53_CONCAT_HELPER(a, b) a##b
3182 #define COMPAT53_CONCAT(a, b) COMPAT53_CONCAT_HELPER(a, b)
3185 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
3199 # define LUA_OPADD 0
3202 # define LUA_OPSUB 1
3205 # define LUA_OPMUL 2
3208 # define LUA_OPDIV 3
3211 # define LUA_OPMOD 4
3214 # define LUA_OPPOW 5
3217 # define LUA_OPUNM 6
3233 #if !defined(LUA_ERRGCMM)
3239 # define LUA_ERRGCMM (LUA_ERRERR + 2)
3242 #if !defined(MOONJIT_VERSION)
3243 typedef size_t lua_Unsigned;
3246 typedef struct luaL_Buffer_53 {
3253 #define luaL_Buffer luaL_Buffer_53
3259 typedef struct luaL_Stream {
3263 #define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex)
3264 COMPAT53_API int lua_absindex(lua_State *L, int i);
3266 #define lua_arith COMPAT53_CONCAT(COMPAT53_PREFIX, _arith)
3267 COMPAT53_API void lua_arith(lua_State *L, int op);
3269 #define lua_compare COMPAT53_CONCAT(COMPAT53_PREFIX, _compare)
3270 COMPAT53_API int lua_compare(lua_State *L, int idx1, int idx2, int op);
3272 #define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy)
3273 COMPAT53_API void lua_copy(lua_State *L, int from, int to);
3275 #define lua_getuservalue(L, i) \
3276 (lua_getfenv((L), (i)), lua_type((L), -1))
3277 #define lua_setuservalue(L, i) \
3278 (luaL_checktype((L), -1, LUA_TTABLE), lua_setfenv((L), (i)))
3280 #define lua_len COMPAT53_CONCAT(COMPAT53_PREFIX, _len)
3281 COMPAT53_API void lua_len(lua_State *L, int i);
3283 #define lua_pushstring(L, s) \
3284 (lua_pushstring((L), (s)), lua_tostring((L), -1))
3286 #define lua_pushlstring(L, s, len) \
3287 ((((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))), lua_tostring((L), -1))
3289 #ifndef luaL_newlibtable
3290 # define luaL_newlibtable(L, l) \
3291 (lua_createtable((L), 0, sizeof((l))/sizeof(*(l))-1))
3294 # define luaL_newlib(L, l) \
3295 (luaL_newlibtable((L), (l)), luaL_register((L), NULL, (l)))
3298 #ifndef lua_pushglobaltable
3299 # define lua_pushglobaltable(L) \
3300 lua_pushvalue((L), LUA_GLOBALSINDEX)
3302 #define lua_rawgetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawgetp)
3303 COMPAT53_API int lua_rawgetp(lua_State *L, int i, const void *p);
3305 #define lua_rawsetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawsetp)
3306 COMPAT53_API void lua_rawsetp(lua_State *L, int i, const void *p);
3308 #define lua_rawlen(L, i) lua_objlen((L), (i))
3310 #define lua_tointeger(L, i) lua_tointegerx((L), (i), NULL)
3312 #define lua_tonumberx COMPAT53_CONCAT(COMPAT53_PREFIX, _tonumberx)
3313 COMPAT53_API lua_Number lua_tonumberx(lua_State *L, int i, int *isnum);
3315 #define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion)
3316 COMPAT53_API void luaL_checkversion(lua_State *L);
3318 #define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53)
3319 COMPAT53_API int lua_load(lua_State *L, lua_Reader reader, void *data, const char* source, const char* mode);
3321 #define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex)
3322 COMPAT53_API int luaL_loadfilex(lua_State *L, const char *filename, const char *mode);
3324 #define luaL_loadbufferx COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadbufferx)
3325 COMPAT53_API int luaL_loadbufferx(lua_State *L, const char *buff, size_t sz, const char *name, const char *mode);
3327 #define luaL_checkstack COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkstack_53)
3328 COMPAT53_API void luaL_checkstack(lua_State *L, int sp, const char *msg);
3330 #define luaL_getsubtable COMPAT53_CONCAT(COMPAT53_PREFIX, L_getsubtable)
3331 COMPAT53_API int luaL_getsubtable(lua_State* L, int i, const char *name);
3333 #define luaL_len COMPAT53_CONCAT(COMPAT53_PREFIX, L_len)
3334 COMPAT53_API lua_Integer luaL_len(lua_State *L, int i);
3336 #define luaL_setfuncs COMPAT53_CONCAT(COMPAT53_PREFIX, L_setfuncs)
3337 COMPAT53_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup);
3339 #define luaL_setmetatable COMPAT53_CONCAT(COMPAT53_PREFIX, L_setmetatable)
3340 COMPAT53_API void luaL_setmetatable(lua_State *L, const char *tname);
3342 #define luaL_testudata COMPAT53_CONCAT(COMPAT53_PREFIX, L_testudata)
3343 COMPAT53_API void *luaL_testudata(lua_State *L, int i, const char *tname);
3345 #define luaL_traceback COMPAT53_CONCAT(COMPAT53_PREFIX, L_traceback)
3346 COMPAT53_API void luaL_traceback(lua_State *L, lua_State *L1, const char *msg, int level);
3348 #define luaL_fileresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_fileresult)
3349 COMPAT53_API int luaL_fileresult(lua_State *L, int stat, const char *fname);
3351 #define luaL_execresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_execresult)
3352 COMPAT53_API int luaL_execresult(lua_State *L, int stat);
3354 #define lua_callk(L, na, nr, ctx, cont) \
3355 ((void)(ctx), (void)(cont), lua_call((L), (na), (nr)))
3356 #define lua_pcallk(L, na, nr, err, ctx, cont) \
3357 ((void)(ctx), (void)(cont), lua_pcall((L), (na), (nr), (err)))
3359 #define lua_resume(L, from, nargs) \
3360 ((void)(from), lua_resume((L), (nargs)))
3362 #define luaL_buffinit COMPAT53_CONCAT(COMPAT53_PREFIX, _buffinit_53)
3363 COMPAT53_API void luaL_buffinit(lua_State *L, luaL_Buffer_53 *B);
3365 #define luaL_prepbuffsize COMPAT53_CONCAT(COMPAT53_PREFIX, _prepbufsize_53)
3366 COMPAT53_API char *luaL_prepbuffsize(luaL_Buffer_53 *B, size_t s);
3368 #define luaL_addlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _addlstring_53)
3369 COMPAT53_API void luaL_addlstring(luaL_Buffer_53 *B, const char *s, size_t l);
3371 #define luaL_addvalue COMPAT53_CONCAT(COMPAT53_PREFIX, _addvalue_53)
3372 COMPAT53_API void luaL_addvalue(luaL_Buffer_53 *B);
3374 #define luaL_pushresult COMPAT53_CONCAT(COMPAT53_PREFIX, _pushresult_53)
3375 COMPAT53_API void luaL_pushresult(luaL_Buffer_53 *B);
3377 #undef luaL_buffinitsize
3378 #define luaL_buffinitsize(L, B, s) \
3379 (luaL_buffinit((L), (B)), luaL_prepbuffsize((B), (s)))
3381 #undef luaL_prepbuffer
3382 #define luaL_prepbuffer(B) \
3383 luaL_prepbuffsize((B), LUAL_BUFFERSIZE)
3386 #define luaL_addchar(B, c) \
3387 ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize((B), 1)), \
3388 ((B)->ptr[(B)->nelems++] = (c)))
3391 #define luaL_addsize(B, s) \
3392 ((B)->nelems += (s))
3394 #undef luaL_addstring
3395 #define luaL_addstring(B, s) \
3396 luaL_addlstring((B), (s), strlen((s)))
3398 #undef luaL_pushresultsize
3399 #define luaL_pushresultsize(B, s) \
3400 (luaL_addsize((B), (s)), luaL_pushresult((B)))
3402 #if defined(LUA_COMPAT_APIINTCASTS)
3403 #define lua_pushunsigned(L, n) \
3404 lua_pushinteger((L), (lua_Integer)(n))
3405 #define lua_tounsignedx(L, i, is) \
3406 ((lua_Unsigned)lua_tointegerx((L), (i), (is)))
3407 #define lua_tounsigned(L, i) \
3408 lua_tounsignedx((L), (i), NULL)
3409 #define luaL_checkunsigned(L, a) \
3410 ((lua_Unsigned)luaL_checkinteger((L), (a)))
3411 #define luaL_optunsigned(L, a, d) \
3412 ((lua_Unsigned)luaL_optinteger((L), (a), (lua_Integer)(d)))
3418 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502
3420 typedef int lua_KContext;
3422 typedef int(*lua_KFunction)(lua_State *L, int status, lua_KContext ctx);
3424 #define lua_dump(L, w, d, s) \
3425 ((void)(s), lua_dump((L), (w), (d)))
3427 #define lua_getfield(L, i, k) \
3428 (lua_getfield((L), (i), (k)), lua_type((L), -1))
3430 #define lua_gettable(L, i) \
3431 (lua_gettable((L), (i)), lua_type((L), -1))
3433 #define lua_geti COMPAT53_CONCAT(COMPAT53_PREFIX, _geti)
3434 COMPAT53_API int lua_geti(lua_State *L, int index, lua_Integer i);
3436 #define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger)
3437 COMPAT53_API int lua_isinteger(lua_State *L, int index);
3439 #define lua_tointegerx COMPAT53_CONCAT(COMPAT53_PREFIX, _tointegerx_53)
3440 COMPAT53_API lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum);
3442 #define lua_numbertointeger(n, p) \
3443 ((*(p) = (lua_Integer)(n)), 1)
3445 #define lua_rawget(L, i) \
3446 (lua_rawget((L), (i)), lua_type((L), -1))
3448 #define lua_rawgeti(L, i, n) \
3449 (lua_rawgeti((L), (i), (n)), lua_type((L), -1))
3451 #define lua_rotate COMPAT53_CONCAT(COMPAT53_PREFIX, _rotate)
3452 COMPAT53_API void lua_rotate(lua_State *L, int idx, int n);
3454 #define lua_seti COMPAT53_CONCAT(COMPAT53_PREFIX, _seti)
3455 COMPAT53_API void lua_seti(lua_State *L, int index, lua_Integer i);
3457 #define lua_stringtonumber COMPAT53_CONCAT(COMPAT53_PREFIX, _stringtonumber)
3458 COMPAT53_API size_t lua_stringtonumber(lua_State *L, const char *s);
3460 #define luaL_tolstring COMPAT53_CONCAT(COMPAT53_PREFIX, L_tolstring)
3461 COMPAT53_API const char *luaL_tolstring(lua_State *L, int idx, size_t *len);
3463 #define luaL_getmetafield(L, o, e) \
3464 (luaL_getmetafield((L), (o), (e)) ? lua_type((L), -1) : LUA_TNIL)
3466 #define luaL_newmetatable(L, tn) \
3467 (luaL_newmetatable((L), (tn)) ? (lua_pushstring((L), (tn)), lua_setfield((L), -2, "__name"), 1) : 0)
3469 #define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_53)
3470 COMPAT53_API void luaL_requiref(lua_State *L, const char *modname,
3471 lua_CFunction openf, int glb);
3476 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 502
3485 #define lua_getglobal(L, n) \
3486 (lua_getglobal((L), (n)), lua_type((L), -1))
3488 #define lua_getuservalue(L, i) \
3489 (lua_getuservalue((L), (i)), lua_type((L), -1))
3491 #define lua_pushlstring(L, s, len) \
3492 (((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len)))
3494 #define lua_rawgetp(L, i, p) \
3495 (lua_rawgetp((L), (i), (p)), lua_type((L), -1))
3497 #define LUA_KFUNCTION(_name) \
3498 static int (_name)(lua_State *L, int status, lua_KContext ctx); \
3499 static int (_name ## _52)(lua_State *L) { \
3501 int status = lua_getctx(L, &ctx); \
3502 return (_name)(L, status, ctx); \
3504 static int (_name)(lua_State *L, int status, lua_KContext ctx)
3506 #define lua_pcallk(L, na, nr, err, ctx, cont) \
3507 lua_pcallk((L), (na), (nr), (err), (ctx), cont ## _52)
3509 #define lua_callk(L, na, nr, ctx, cont) \
3510 lua_callk((L), (na), (nr), (ctx), cont ## _52)
3512 #define lua_yieldk(L, nr, ctx, cont) \
3513 lua_yieldk((L), (nr), (ctx), cont ## _52)
3517 # define lua_call(L, na, nr) \
3518 (lua_callk)((L), (na), (nr), 0, NULL)
3523 # define lua_pcall(L, na, nr, err) \
3524 (lua_pcallk)((L), (na), (nr), (err), 0, NULL)
3529 # define lua_yield(L, nr) \
3530 (lua_yieldk)((L), (nr), 0, NULL)
3536 #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 504
3538 # error "unsupported Lua version (i.e. not Lua 5.1, 5.2, 5.3, or 5.4)"
3544 #ifndef LUA_KFUNCTION
3545 #define LUA_KFUNCTION(_name) \
3546 static int (_name)(lua_State *L, int status, lua_KContext ctx)
3549 #if defined(COMPAT53_INCLUDE_SOURCE) && COMPAT53_INCLUDE_SOURCE == 1
3560 #ifndef KEPLER_PROJECT_COMPAT53_C_
3561 #define KEPLER_PROJECT_COMPAT53_C_
3564 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
3566 #ifndef COMPAT53_FOPEN_NO_LOCK
3567 #if defined(_MSC_VER)
3568 #define COMPAT53_FOPEN_NO_LOCK 1
3570 #define COMPAT53_FOPEN_NO_LOCK 0
3574 #if defined(_MSC_VER) && COMPAT53_FOPEN_NO_LOCK
3578 #ifndef COMPAT53_HAVE_STRERROR_R
3579 #if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) || (!defined(__MINGW32__) && defined(__GNUC__) && (__GNUC__ < 6))
3580 #define COMPAT53_HAVE_STRERROR_R 1
3582 #define COMPAT53_HAVE_STRERROR_R 0
3586 #ifndef COMPAT53_HAVE_STRERROR_S
3587 #if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || (defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__)
3588 #define COMPAT53_HAVE_STRERROR_S 1
3590 #define COMPAT53_HAVE_STRERROR_S 0
3594 #ifndef COMPAT53_LUA_FILE_BUFFER_SIZE
3595 #define COMPAT53_LUA_FILE_BUFFER_SIZE 4096
3598 static char* compat53_strerror(int en, char* buff, size_t sz) {
3599 #if COMPAT53_HAVE_STRERROR_R
3604 if (strerror_r(en, buff, sz)) {
3608 if (buff[0] == '\0') {
3612 return strerror(en);
3616 #elif COMPAT53_HAVE_STRERROR_S
3619 strerror_s(buff, sz, en);
3628 return strerror(en);
3632 COMPAT53_API int lua_absindex(lua_State* L, int i) {
3633 if (i < 0 && i > LUA_REGISTRYINDEX)
3634 i += lua_gettop(L) + 1;
3638 static void compat53_call_lua(lua_State* L, char const code[], size_t len, int nargs, int nret) {
3639 lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code);
3640 if (lua_type(L, -1) != LUA_TFUNCTION) {
3642 if (luaL_loadbuffer(L, code, len, "=none"))
3644 lua_pushvalue(L, -1);
3645 lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code);
3647 lua_insert(L, -nargs - 1);
3648 lua_call(L, nargs, nret);
3651 COMPAT53_API void lua_arith(lua_State* L, int op) {
3652 static const char compat53_arith_code[]
3653 = "local op,a,b=...\n"
3654 "if op==0 then return a+b\n"
3655 "elseif op==1 then return a-b\n"
3656 "elseif op==2 then return a*b\n"
3657 "elseif op==3 then return a/b\n"
3658 "elseif op==4 then return a%b\n"
3659 "elseif op==5 then return a^b\n"
3660 "elseif op==6 then return -a\n"
3663 if (op < LUA_OPADD || op > LUA_OPUNM)
3664 luaL_error(L, "invalid 'op' argument for lua_arith");
3665 luaL_checkstack(L, 5, "not enough stack slots");
3666 if (op == LUA_OPUNM)
3667 lua_pushvalue(L, -1);
3668 lua_pushnumber(L, op);
3670 compat53_call_lua(L, compat53_arith_code, sizeof(compat53_arith_code) - 1, 3, 1);
3673 COMPAT53_API int lua_compare(lua_State* L, int idx1, int idx2, int op) {
3674 static const char compat53_compare_code[]
3681 return lua_equal(L, idx1, idx2);
3683 return lua_lessthan(L, idx1, idx2);
3685 luaL_checkstack(L, 5, "not enough stack slots");
3686 idx1 = lua_absindex(L, idx1);
3687 idx2 = lua_absindex(L, idx2);
3688 lua_pushvalue(L, idx1);
3689 lua_pushvalue(L, idx2);
3690 compat53_call_lua(L, compat53_compare_code, sizeof(compat53_compare_code) - 1, 2, 1);
3691 result = lua_toboolean(L, -1);
3695 luaL_error(L, "invalid 'op' argument for lua_compare");
3700 COMPAT53_API void lua_copy(lua_State* L, int from, int to) {
3701 int abs_to = lua_absindex(L, to);
3702 luaL_checkstack(L, 1, "not enough stack slots");
3703 lua_pushvalue(L, from);
3704 lua_replace(L, abs_to);
3707 COMPAT53_API void lua_len(lua_State* L, int i) {
3708 switch (lua_type(L, i)) {
3710 lua_pushnumber(L, (lua_Number)lua_objlen(L, i));
3713 if (!luaL_callmeta(L, i, "__len"))
3714 lua_pushnumber(L, (lua_Number)lua_objlen(L, i));
3717 if (luaL_callmeta(L, i, "__len"))
3721 luaL_error(L, "attempt to get length of a %s value", lua_typename(L, lua_type(L, i)));
3725 COMPAT53_API int lua_rawgetp(lua_State* L, int i, const void* p) {
3726 int abs_i = lua_absindex(L, i);
3727 lua_pushlightuserdata(L, (void*)p);
3728 lua_rawget(L, abs_i);
3729 return lua_type(L, -1);
3732 COMPAT53_API void lua_rawsetp(lua_State* L, int i, const void* p) {
3733 int abs_i = lua_absindex(L, i);
3734 luaL_checkstack(L, 1, "not enough stack slots");
3735 lua_pushlightuserdata(L, (void*)p);
3737 lua_rawset(L, abs_i);
3740 COMPAT53_API lua_Number lua_tonumberx(lua_State* L, int i, int* isnum) {
3741 lua_Number n = lua_tonumber(L, i);
3742 if (isnum != NULL) {
3743 *isnum = (n != 0 || lua_isnumber(L, i));
3748 COMPAT53_API void luaL_checkversion(lua_State* L) {
3752 COMPAT53_API void luaL_checkstack(lua_State* L, int sp, const char* msg) {
3753 if (!lua_checkstack(L, sp + LUA_MINSTACK)) {
3755 luaL_error(L, "stack overflow (%s)", msg);
3757 lua_pushliteral(L, "stack overflow");
3763 COMPAT53_API int luaL_getsubtable(lua_State* L, int i, const char* name) {
3764 int abs_i = lua_absindex(L, i);
3765 luaL_checkstack(L, 3, "not enough stack slots");
3766 lua_pushstring(L, name);
3767 lua_gettable(L, abs_i);
3768 if (lua_istable(L, -1))
3772 lua_pushstring(L, name);
3773 lua_pushvalue(L, -2);
3774 lua_settable(L, abs_i);
3778 COMPAT53_API lua_Integer luaL_len(lua_State* L, int i) {
3779 lua_Integer res = 0;
3781 luaL_checkstack(L, 1, "not enough stack slots");
3783 res = lua_tointegerx(L, -1, &isnum);
3786 luaL_error(L, "object length is not an integer");
3790 COMPAT53_API void luaL_setfuncs(lua_State* L, const luaL_Reg* l, int nup) {
3791 luaL_checkstack(L, nup + 1, "too many upvalues");
3792 for (; l->name != NULL; l++) {
3794 lua_pushstring(L, l->name);
3795 for (i = 0; i < nup; i++)
3796 lua_pushvalue(L, -(nup + 1));
3797 lua_pushcclosure(L, l->func, nup);
3798 lua_settable(L, -(nup + 3));
3803 COMPAT53_API void luaL_setmetatable(lua_State* L, const char* tname) {
3804 luaL_checkstack(L, 1, "not enough stack slots");
3805 luaL_getmetatable(L, tname);
3806 lua_setmetatable(L, -2);
3809 COMPAT53_API void* luaL_testudata(lua_State* L, int i, const char* tname) {
3810 void* p = lua_touserdata(L, i);
3811 luaL_checkstack(L, 2, "not enough stack slots");
3812 if (p == NULL || !lua_getmetatable(L, i))
3816 luaL_getmetatable(L, tname);
3817 res = lua_rawequal(L, -1, -2);
3825 static int compat53_countlevels(lua_State* L) {
3829 while (lua_getstack(L, le, &ar)) {
3835 int m = (li + le) / 2;
3836 if (lua_getstack(L, m, &ar))
3844 static int compat53_findfield(lua_State* L, int objidx, int level) {
3845 if (level == 0 || !lua_istable(L, -1))
3848 while (lua_next(L, -2)) {
3849 if (lua_type(L, -2) == LUA_TSTRING) {
3850 if (lua_rawequal(L, objidx, -1)) {
3854 else if (compat53_findfield(L, objidx, level - 1)) {
3856 lua_pushliteral(L, ".");
3867 static int compat53_pushglobalfuncname(lua_State* L, lua_Debug* ar) {
3868 int top = lua_gettop(L);
3869 lua_getinfo(L, "f", ar);
3870 lua_pushvalue(L, LUA_GLOBALSINDEX);
3871 if (compat53_findfield(L, top + 1, 2)) {
3872 lua_copy(L, -1, top + 1);
3882 static void compat53_pushfuncname(lua_State* L, lua_Debug* ar) {
3883 if (*ar->namewhat != '\0')
3884 lua_pushfstring(L, "function " LUA_QS, ar->name);
3885 else if (*ar->what == 'm')
3886 lua_pushliteral(L, "main chunk");
3887 else if (*ar->what == 'C') {
3888 if (compat53_pushglobalfuncname(L, ar)) {
3889 lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1));
3893 lua_pushliteral(L, "?");
3896 lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined);
3899 #define COMPAT53_LEVELS1 12
3900 #define COMPAT53_LEVELS2 10
3902 COMPAT53_API void luaL_traceback(lua_State* L, lua_State* L1, const char* msg, int level) {
3904 int top = lua_gettop(L);
3905 int numlevels = compat53_countlevels(L1);
3906 int mark = (numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2) ? COMPAT53_LEVELS1 : 0;
3908 lua_pushfstring(L, "%s\n", msg);
3909 lua_pushliteral(L, "stack traceback:");
3910 while (lua_getstack(L1, level++, &ar)) {
3911 if (level == mark) {
3912 lua_pushliteral(L, "\n\t...");
3913 level = numlevels - COMPAT53_LEVELS2;
3916 lua_getinfo(L1, "Slnt", &ar);
3917 lua_pushfstring(L, "\n\t%s:", ar.short_src);
3918 if (ar.currentline > 0)
3919 lua_pushfstring(L, "%d:", ar.currentline);
3920 lua_pushliteral(L, " in ");
3921 compat53_pushfuncname(L, &ar);
3922 lua_concat(L, lua_gettop(L) - top);
3925 lua_concat(L, lua_gettop(L) - top);
3928 COMPAT53_API int luaL_fileresult(lua_State* L, int stat, const char* fname) {
3929 const char* serr = NULL;
3931 char buf[512] = { 0 };
3933 lua_pushboolean(L, 1);
3938 serr = compat53_strerror(en, buf, sizeof(buf));
3940 lua_pushfstring(L, "%s: %s", fname, serr);
3942 lua_pushstring(L, serr);
3943 lua_pushnumber(L, (lua_Number)en);
3948 static int compat53_checkmode(lua_State* L, const char* mode, const char* modename, int err) {
3949 if (mode && strchr(mode, modename[0]) == NULL) {
3950 lua_pushfstring(L, "attempt to load a %s chunk (mode is '%s')", modename, mode);
3959 int has_peeked_data;
3960 const char* peeked_data;
3961 size_t peeked_data_size;
3962 } compat53_reader_data;
3964 static const char* compat53_reader(lua_State* L, void* ud, size_t* size) {
3965 compat53_reader_data* data = (compat53_reader_data*)ud;
3966 if (data->has_peeked_data) {
3967 data->has_peeked_data = 0;
3968 *size = data->peeked_data_size;
3969 return data->peeked_data;
3972 return data->reader(L, data->ud, size);
3975 COMPAT53_API int lua_load(lua_State* L, lua_Reader reader, void* data, const char* source, const char* mode) {
3976 int status = LUA_OK;
3977 compat53_reader_data compat53_data = { reader, data, 1, 0, 0 };
3978 compat53_data.peeked_data = reader(L, data, &(compat53_data.peeked_data_size));
3979 if (compat53_data.peeked_data && compat53_data.peeked_data_size && compat53_data.peeked_data[0] == LUA_SIGNATURE[0])
3980 status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX);
3982 status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX);
3983 if (status != LUA_OK)
3987 return lua_load(L, compat53_reader, &compat53_data, source);
3988 #define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53)
3994 char buff[COMPAT53_LUA_FILE_BUFFER_SIZE];
3997 static const char* compat53_getF(lua_State* L, void* ud, size_t* size) {
3998 compat53_LoadF* lf = (compat53_LoadF*)ud;
4010 *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);
4015 static int compat53_errfile(lua_State* L, const char* what, int fnameindex) {
4016 char buf[512] = { 0 };
4017 const char* serr = compat53_strerror(errno, buf,
sizeof(buf));
4018 const char* filename = lua_tostring(L, fnameindex) + 1;
4019 lua_pushfstring(L,
"cannot %s %s: %s", what, filename, serr);
4020 lua_remove(L, fnameindex);
4024 static int compat53_skipBOM(compat53_LoadF* lf) {
4025 const char* p =
"\xEF\xBB\xBF";
4030 if (c == EOF || c != *(
const unsigned char*)p++)
4032 lf->buff[lf->n++] = (char)c;
4033 }
while (*p !=
'\0');
4045 static int compat53_skipcomment(compat53_LoadF* lf,
int* cp) {
4046 int c = *cp = compat53_skipBOM(lf);
4050 }
while (c != EOF && c !=
'\n');
4058 COMPAT53_API
int luaL_loadfilex(
lua_State* L,
const char* filename,
const char* mode) {
4060 int status, readstatus;
4062 int fnameindex = lua_gettop(L) + 1;
4063 if (filename == NULL) {
4064 lua_pushliteral(L,
"=stdin");
4068 lua_pushfstring(L,
"@%s", filename);
4069 #if defined(_MSC_VER) 4080 #if COMPAT53_FOPEN_NO_LOCK 4081 lf.f = _fsopen(filename,
"r", _SH_DENYNO);
4083 return compat53_errfile(L,
"open", fnameindex);
4085 if (fopen_s(&lf.f, filename,
"r") != 0)
4086 return compat53_errfile(L,
"open", fnameindex);
4089 lf.f = fopen(filename,
"r");
4091 return compat53_errfile(L,
"open", fnameindex);
4094 if (compat53_skipcomment(&lf, &c))
4095 lf.buff[lf.n++] =
'\n';
4096 if (c == LUA_SIGNATURE[0] && filename) {
4097 #if defined(_MSC_VER) 4098 if (freopen_s(&lf.f, filename,
"rb", lf.f) != 0)
4099 return compat53_errfile(L,
"reopen", fnameindex);
4101 lf.f = freopen(filename,
"rb", lf.f);
4103 return compat53_errfile(L,
"reopen", fnameindex);
4105 compat53_skipcomment(&lf, &c);
4108 lf.buff[lf.n++] = (char)c;
4109 status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1), mode);
4110 readstatus = ferror(lf.f);
4114 lua_settop(L, fnameindex);
4115 return compat53_errfile(L,
"read", fnameindex);
4117 lua_remove(L, fnameindex);
4121 COMPAT53_API
int luaL_loadbufferx(
lua_State* L,
const char* buff,
size_t sz,
const char* name,
const char* mode) {
4122 int status = LUA_OK;
4123 if (sz > 0 && buff[0] == LUA_SIGNATURE[0]) {
4124 status = compat53_checkmode(L, mode,
"binary", LUA_ERRSYNTAX);
4127 status = compat53_checkmode(L, mode,
"text", LUA_ERRSYNTAX);
4129 if (status != LUA_OK)
4131 return luaL_loadbuffer(L, buff, sz, name);
4134 #if !defined(l_inspectstat) \ 4135 && (defined(unix) || defined(__unix) || defined(__unix__) || defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || (defined(__APPLE__) && defined(__MACH__))) 4140 #if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L 4141 #include <sys/wait.h> 4142 #define l_inspectstat(stat, what) \ 4143 if (WIFEXITED(stat)) { \ 4144 stat = WEXITSTATUS(stat); \ 4146 else if (WIFSIGNALED(stat)) { \ 4147 stat = WTERMSIG(stat); \ 4154 #if !defined(l_inspectstat) 4155 #define l_inspectstat(stat, what) ((void)0) 4158 COMPAT53_API
int luaL_execresult(
lua_State* L,
int stat) {
4159 const char* what =
"exit";
4161 return luaL_fileresult(L, 0, NULL);
4163 l_inspectstat(stat, what);
4164 if (*what ==
'e' && stat == 0)
4165 lua_pushboolean(L, 1);
4168 lua_pushstring(L, what);
4169 lua_pushinteger(L, stat);
4174 COMPAT53_API
void luaL_buffinit(
lua_State* L, luaL_Buffer_53* B) {
4180 B->ptr = B->b.buffer;
4181 B->capacity = LUAL_BUFFERSIZE;
4186 COMPAT53_API
char* luaL_prepbuffsize(luaL_Buffer_53* B,
size_t s) {
4187 if (B->capacity - B->nelems < s) {
4188 char* newptr = NULL;
4189 size_t newcap = B->capacity * 2;
4190 if (newcap - B->nelems < s)
4191 newcap = B->nelems + s;
4192 if (newcap < B->capacity)
4193 luaL_error(B->L2,
"buffer too large");
4194 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 504 4195 newptr = (
char*)lua_newuserdatauv(B->L2, newcap, 0);
4197 newptr = (
char*)lua_newuserdata(B->L2, newcap);
4199 memcpy(newptr, B->ptr, B->nelems);
4200 if (B->ptr != B->b.buffer)
4201 lua_replace(B->L2, -2);
4203 B->capacity = newcap;
4205 return B->ptr + B->nelems;
4208 COMPAT53_API
void luaL_addlstring(luaL_Buffer_53* B,
const char* s,
size_t l) {
4209 memcpy(luaL_prepbuffsize(B, l), s, l);
4213 COMPAT53_API
void luaL_addvalue(luaL_Buffer_53* B) {
4215 const char* s = lua_tolstring(B->L2, -1, &len);
4217 luaL_error(B->L2,
"cannot convert value to string");
4218 if (B->ptr != B->b.buffer)
4219 lua_insert(B->L2, -2);
4220 luaL_addlstring(B, s, len);
4221 lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1);
4224 void luaL_pushresult(luaL_Buffer_53* B) {
4225 lua_pushlstring(B->L2, B->ptr, B->nelems);
4226 if (B->ptr != B->b.buffer)
4227 lua_replace(B->L2, -2);
4233 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502 4235 COMPAT53_API
int lua_geti(
lua_State* L,
int index, lua_Integer i) {
4236 index = lua_absindex(L, index);
4237 lua_pushinteger(L, i);
4238 lua_gettable(L, index);
4239 return lua_type(L, -1);
4242 COMPAT53_API
int lua_isinteger(
lua_State* L,
int index) {
4243 if (lua_type(L, index) == LUA_TNUMBER) {
4244 lua_Number n = lua_tonumber(L, index);
4245 lua_Integer i = lua_tointeger(L, index);
4252 COMPAT53_API lua_Integer lua_tointegerx(
lua_State* L,
int i,
int* isnum) {
4254 lua_Number n = lua_tonumberx(L, i, &ok);
4256 if (n == (lua_Integer)n) {
4259 return (lua_Integer)n;
4267 static void compat53_reverse(
lua_State* L,
int a,
int b) {
4268 for (; a < b; ++a, --b) {
4269 lua_pushvalue(L, a);
4270 lua_pushvalue(L, b);
4276 COMPAT53_API
void lua_rotate(
lua_State* L,
int idx,
int n) {
4278 idx = lua_absindex(L, idx);
4279 n_elems = lua_gettop(L) - idx + 1;
4282 if (n > 0 && n < n_elems) {
4283 luaL_checkstack(L, 2,
"not enough stack slots available");
4285 compat53_reverse(L, idx, idx + n - 1);
4286 compat53_reverse(L, idx + n, idx + n_elems - 1);
4287 compat53_reverse(L, idx, idx + n_elems - 1);
4291 COMPAT53_API
void lua_seti(
lua_State* L,
int index, lua_Integer i) {
4292 luaL_checkstack(L, 1,
"not enough stack slots available");
4293 index = lua_absindex(L, index);
4294 lua_pushinteger(L, i);
4296 lua_settable(L, index);
4299 #if !defined(lua_str2number) 4300 #define lua_str2number(s, p) strtod((s), (p)) 4303 COMPAT53_API
size_t lua_stringtonumber(
lua_State* L,
const char* s) {
4305 lua_Number n = lua_str2number(s, &endptr);
4307 while (*endptr !=
'\0' && isspace((
unsigned char)*endptr))
4309 if (*endptr ==
'\0') {
4310 lua_pushnumber(L, n);
4311 return endptr - s + 1;
4317 COMPAT53_API
const char* luaL_tolstring(
lua_State* L,
int idx,
size_t* len) {
4318 if (!luaL_callmeta(L, idx,
"__tostring")) {
4319 int t = lua_type(L, idx), tt = 0;
4320 char const* name = NULL;
4323 lua_pushliteral(L,
"nil");
4327 lua_pushvalue(L, idx);
4330 if (lua_toboolean(L, idx))
4331 lua_pushliteral(L,
"true");
4333 lua_pushliteral(L,
"false");
4336 tt = luaL_getmetafield(L, idx,
"__name");
4337 name = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : lua_typename(L, t);
4338 lua_pushfstring(L,
"%s: %p", name, lua_topointer(L, idx));
4345 if (!lua_isstring(L, -1))
4346 luaL_error(L,
"'__tostring' must return a string");
4348 return lua_tolstring(L, -1, len);
4351 COMPAT53_API
void luaL_requiref(
lua_State* L,
const char* modname, lua_CFunction openf,
int glb) {
4352 luaL_checkstack(L, 3,
"not enough stack slots available");
4353 luaL_getsubtable(L, LUA_REGISTRYINDEX,
"_LOADED");
4354 if (lua_getfield(L, -1, modname) == LUA_TNIL) {
4356 lua_pushcfunction(L, openf);
4357 lua_pushstring(L, modname);
4359 lua_pushvalue(L, -1);
4360 lua_setfield(L, -3, modname);
4363 lua_pushvalue(L, -1);
4364 lua_setglobal(L, modname);
4407 #ifndef NOT_KEPLER_PROJECT_COMPAT54_H_ 4408 #define NOT_KEPLER_PROJECT_COMPAT54_H_ 4410 #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) 4414 #include <lauxlib.h> 4416 #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) 4420 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 504 4422 #if !defined(LUA_ERRGCMM) 4426 # define LUA_ERRGCMM (LUA_ERRERR + 2) 4429 #endif // Lua 5.4 only 4431 #endif // NOT_KEPLER_PROJECT_COMPAT54_H_// end of sol/compatibility/compat-5.4.h 4443 template <
typename Allocator = std::allocator<std::byte>>
4444 class basic_bytecode :
private std::vector<std::byte, Allocator> {
4446 using base_t = std::vector<std::byte, Allocator>;
4449 using typename base_t::allocator_type;
4450 using typename base_t::const_iterator;
4451 using typename base_t::const_pointer;
4452 using typename base_t::const_reference;
4453 using typename base_t::const_reverse_iterator;
4454 using typename base_t::difference_type;
4455 using typename base_t::iterator;
4456 using typename base_t::pointer;
4457 using typename base_t::reference;
4458 using typename base_t::reverse_iterator;
4459 using typename base_t::size_type;
4460 using typename base_t::value_type;
4462 using base_t::base_t;
4463 using base_t::operator=;
4466 using base_t::empty;
4467 using base_t::max_size;
4471 using base_t::operator[];
4473 using base_t::front;
4475 using base_t::begin;
4476 using base_t::cbegin;
4480 using base_t::crbegin;
4481 using base_t::crend;
4482 using base_t::rbegin;
4485 using base_t::get_allocator;
4488 using base_t::clear;
4489 using base_t::emplace;
4490 using base_t::emplace_back;
4491 using base_t::erase;
4492 using base_t::insert;
4493 using base_t::pop_back;
4494 using base_t::push_back;
4495 using base_t::reserve;
4496 using base_t::resize;
4497 using base_t::shrink_to_fit;
4499 string_view as_string_view()
const {
4500 return string_view(reinterpret_cast<const char*>(this->data()), this->size());
4504 template <
typename Container>
4505 inline int basic_insert_dump_writer(
lua_State*,
const void* memory,
size_t memory_size,
void* userdata_pointer) {
4506 using storage_t = Container;
4507 const std::byte* p_code =
static_cast<const std::byte*
>(memory);
4508 storage_t& bc = *
static_cast<storage_t*
>(userdata_pointer);
4509 #if SOL_IS_OFF(SOL_EXCEPTIONS) 4510 bc.insert(bc.cend(), p_code, p_code + memory_size);
4513 bc.insert(bc.cend(), p_code, p_code + memory_size);
4524 constexpr
inline auto bytecode_dump_writer = &basic_insert_dump_writer<bytecode>;
4538 #include <stdexcept> 4549 const char* format_string;
4550 std::array<const char*, 4> argument_strings;
4555 error_result(
int results_) : results(results_), format_string(
nullptr) {
4558 error_result(
const char* format_string_,
const char* first_message_) : results(0), format_string(format_string_), argument_strings() {
4559 argument_strings[0] = first_message_;
4564 if (er.format_string ==
nullptr) {
4567 return luaL_error(L, er.format_string, er.argument_strings[0], er.argument_strings[1], er.argument_strings[2], er.argument_strings[3]);
4571 class error :
public std::runtime_error {
4574 std::string what_reason;
4577 error(
const std::string& str) :
error(detail::direct_error,
"lua: error: " + str) {
4579 error(std::string&& str) :
error(detail::direct_error,
"lua: error: " + std::move(str)) {
4591 virtual const char* what()
const noexcept
override {
4592 return what_reason.c_str();
4609 using in_place_t = std::in_place_t;
4610 constexpr std::in_place_t in_place {};
4611 constexpr std::in_place_t in_place_of {};
4613 template <
typename T>
4614 using in_place_type_t = std::in_place_type_t<T>;
4615 template <
typename T>
4616 constexpr std::in_place_type_t<T> in_place_type {};
4619 using in_place_index_t = std::in_place_index_t<I>;
4621 constexpr in_place_index_t<I> in_place_index {};
4627 #if SOL_IS_ON(SOL_USE_BOOST) 4628 #include <boost/optional.hpp> 4632 #define SOL_TL_OPTIONAL_VERSION_MAJOR 0 4633 #define SOL_TL_OPTIONAL_VERSION_MINOR 5 4635 #include <exception> 4636 #include <functional> 4638 #include <type_traits> 4643 #if (defined(_MSC_VER) && _MSC_VER == 1900) 4644 #define SOL_TL_OPTIONAL_MSVC2015 4647 #if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__)) 4648 #define SOL_TL_OPTIONAL_GCC49 4651 #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && !defined(__clang__)) 4652 #define SOL_TL_OPTIONAL_GCC54 4655 #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && !defined(__clang__)) 4656 #define SOL_TL_OPTIONAL_GCC55 4659 #if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__)) 4660 #define SOL_TL_OPTIONAL_NO_CONSTRR 4662 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::has_trivial_copy_constructor<T>::value 4663 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign<T>::value 4665 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value 4667 #elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__)) 4668 #ifndef SOL_TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX 4669 #define SOL_TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX 4670 namespace sol {
namespace detail {
4672 struct is_trivially_copy_constructible : std::is_trivially_copy_constructible<T> { };
4673 #ifdef _GLIBCXX_VECTOR 4674 template <
class T,
class A>
4675 struct is_trivially_copy_constructible<std::vector<T, A>> : std::is_trivially_copy_constructible<T> { };
4680 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) sol::detail::is_trivially_copy_constructible<T>::value 4681 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable<T>::value 4682 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value 4684 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::is_trivially_copy_constructible<T>::value 4685 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable<T>::value 4686 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value 4689 #if __cplusplus > 201103L 4690 #define SOL_TL_OPTIONAL_CXX14 4693 #if (__cplusplus == 201103L || defined(SOL_TL_OPTIONAL_MSVC2015) || defined(SOL_TL_OPTIONAL_GCC49)) 4694 #define SOL_TL_OPTIONAL_11_CONSTEXPR 4696 #define SOL_TL_OPTIONAL_11_CONSTEXPR constexpr 4701 #ifndef SOL_TL_MONOSTATE_INPLACE_MUTEX 4702 #define SOL_TL_MONOSTATE_INPLACE_MUTEX 4712 #ifndef SOL_TL_TRAITS_MUTEX 4713 #define SOL_TL_TRAITS_MUTEX 4716 using remove_const_t =
typename std::remove_const<T>::type;
4718 using remove_reference_t =
typename std::remove_reference<T>::type;
4720 using decay_t =
typename std::decay<T>::type;
4721 template <
bool E,
class T =
void>
4722 using enable_if_t =
typename std::enable_if<E, T>::type;
4723 template <
bool B,
class T,
class F>
4724 using conditional_t =
typename std::conditional<B, T, F>::type;
4731 template <
class B,
class... Bs>
4732 struct conjunction<B, Bs...> : std::conditional<bool(B::value), conjunction<Bs...>, B>::type { };
4734 #if defined(_LIBCPP_VERSION) && __cplusplus == 201103L 4735 #define SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND 4738 #ifdef SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND 4740 struct is_pointer_to_non_const_member_func : std::false_type { };
4741 template <
class T,
class Ret,
class... Args>
4742 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)> : std::true_type { };
4743 template <
class T,
class Ret,
class... Args>
4744 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)&> : std::true_type { };
4745 template <
class T,
class Ret,
class... Args>
4746 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &&> : std::true_type { };
4747 template <
class T,
class Ret,
class... Args>
4748 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile> : std::true_type { };
4749 template <
class T,
class Ret,
class... Args>
4750 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile&> : std::true_type { };
4751 template <
class T,
class Ret,
class... Args>
4752 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile&&> : std::true_type { };
4755 struct is_const_or_const_ref : std::false_type { };
4757 struct is_const_or_const_ref<T const&> : std::true_type { };
4759 struct is_const_or_const_ref<T const> : std::true_type { };
4764 template <
typename Fn,
typename... Args,
4765 #ifdef SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND 4766 typename = enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value && is_const_or_const_ref<Args...>::value)>,
4768 typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>,
int = 0>
4769 constexpr
auto invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
4770 -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {
4771 return std::mem_fn(f)(std::forward<Args>(args)...);
4774 template <
typename Fn,
typename... Args,
typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>>
4775 constexpr
auto invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
4776 -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {
4777 return std::forward<Fn>(f)(std::forward<Args>(args)...);
4781 template <
class F,
class,
class... Us>
4784 template <
class F,
class... Us>
4785 struct invoke_result_impl<F, decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()), Us...> {
4786 using type = decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...));
4789 template <
class F,
class... Us>
4792 template <
class F,
class... Us>
4793 using invoke_result_t =
typename invoke_result<F, Us...>::type;
4801 template <
class... Ts>
4802 using void_t =
typename voider<Ts...>::type;
4814 using fixup_void = conditional_t<std::is_void<U>::value,
monostate, U>;
4816 template <
class F,
class U,
class = invoke_result_t<F, U>>
4820 template <
class F,
class = void,
class... U>
4822 template <
class F,
class... U>
4823 struct returns_void_impl<F, void_t<invoke_result_t<F, U...>>, U...> : std::is_void<invoke_result_t<F, U...>> { };
4824 template <
class F,
class... U>
4827 template <
class T,
class... U>
4828 using enable_if_ret_void = enable_if_t<returns_void<T&&, U...>::value>;
4830 template <
class T,
class... U>
4831 using disable_if_ret_void = enable_if_t<!returns_void<T&&, U...>::value>;
4833 template <
class T,
class U>
4834 using enable_forward_value = detail::enable_if_t<std::is_constructible<T, U&&>::value && !std::is_same<detail::decay_t<U>, in_place_t>::value
4835 && !std::is_same<optional<T>, detail::decay_t<U>>::value>;
4837 template <
class T,
class U,
class Other>
4838 using enable_from_other = detail::enable_if_t<std::is_constructible<T, Other>::value && !std::is_constructible<T, optional<U>&>::value
4839 && !std::is_constructible<T, optional<U>&&>::value && !std::is_constructible<T, const optional<U>&>::value
4840 && !std::is_constructible<T, const optional<U>&&>::value && !std::is_convertible<optional<U>&, T>::value
4841 && !std::is_convertible<optional<U>&&, T>::value && !std::is_convertible<const optional<U>&, T>::value
4842 && !std::is_convertible<const optional<U>&&, T>::value>;
4844 template <
class T,
class U>
4845 using enable_assign_forward = detail::enable_if_t<!std::is_same<optional<T>, detail::decay_t<U>>::value
4847 && std::is_assignable<T&, U>::value>;
4849 template <
class T,
class U,
class Other>
4850 using enable_assign_from_other = detail::enable_if_t<std::is_constructible<T, Other>::value && std::is_assignable<T&, Other>::value
4851 && !std::is_constructible<T, optional<U>&>::value && !std::is_constructible<T, optional<U>&&>::value
4852 && !std::is_constructible<T, const optional<U>&>::value && !std::is_constructible<T, const optional<U>&&>::value
4853 && !std::is_convertible<optional<U>&, T>::value && !std::is_convertible<optional<U>&&, T>::value
4854 && !std::is_convertible<const optional<U>&, T>::value && !std::is_convertible<const optional<U>&&, T>::value
4855 && !std::is_assignable<T&, optional<U>&>::value && !std::is_assignable<T&, optional<U>&&>::value
4856 && !std::is_assignable<T&, const optional<U>&>::value && !std::is_assignable<T&, const optional<U>&&>::value>;
4860 template <
class T,
class U = T>
4863 template <
class T,
class U = T>
4867 namespace swap_adl_tests {
4874 template <
class T, std::
size_t N>
4875 tag swap(T (&a)[N], T (&b)[N]);
4879 template <
class,
class>
4880 std::false_type can_swap(...) noexcept(
false);
4881 template <
class T,
class U,
class = decltype(swap(std::declval<T&>(), std::declval<U&>()))>
4882 std::true_type can_swap(
int) noexcept(noexcept(swap(std::declval<T&>(), std::declval<U&>())));
4884 template <
class,
class>
4885 std::false_type uses_std(...);
4886 template <
class T,
class U>
4887 std::is_same<decltype(swap(std::declval<T&>(), std::declval<U&>())),
tag> uses_std(
int);
4891 : std::integral_constant<bool, std::is_nothrow_move_constructible<T>::value && std::is_nothrow_move_assignable<T>::value> { };
4893 template <
class T, std::
size_t N>
4896 template <
class T,
class U>
4900 template <
class T,
class U = T>
4902 decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value
4903 && (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value
4904 || (std::is_move_assignable<T>::value && std::is_move_constructible<T>::value))> { };
4906 template <
class T, std::
size_t N>
4908 decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value
4909 && (!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value || is_swappable<T, T>::value)> { };
4911 template <
class T,
class U = T>
4913 : std::integral_constant<bool,
4914 is_swappable<T, U>::value
4915 && ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value&& detail::swap_adl_tests::is_std_swap_noexcept<T>::value)
4916 || (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value&& detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> { };
4922 template <class T, bool = ::std::is_trivially_destructible<T>::value>
4927 template <
class... U>
4928 SOL_TL_OPTIONAL_11_CONSTEXPR
optional_storage_base(in_place_t, U&&... u) : m_value(std::forward<U>(u)...), m_has_value(
true) {
4931 ~optional_storage_base() {
4934 m_has_value =
false;
4953 template <
class... U>
4954 SOL_TL_OPTIONAL_11_CONSTEXPR
optional_storage_base(in_place_t, U&&... u) : m_value(std::forward<U>(u)...), m_has_value(
true) {
4965 bool m_has_value =
false;
4974 void hard_reset() noexcept {
4976 this->m_has_value =
false;
4979 template <
class... Args>
4980 void construct(Args&&... args) noexcept {
4981 new (std::addressof(this->m_value)) T(std::forward<Args>(args)...);
4982 this->m_has_value =
true;
4985 template <
class Opt>
4986 void assign(Opt&& rhs) {
4987 if (this->has_value()) {
4988 if (rhs.has_value()) {
4989 this->m_value = std::forward<Opt>(rhs).
get();
4993 this->m_has_value =
false;
4997 else if (rhs.has_value()) {
4998 construct(std::forward<Opt>(rhs).
get());
5002 bool has_value()
const {
5003 return this->m_has_value;
5006 SOL_TL_OPTIONAL_11_CONSTEXPR T&
get() & {
5007 return this->m_value;
5009 SOL_TL_OPTIONAL_11_CONSTEXPR
const T&
get()
const& {
5010 return this->m_value;
5012 SOL_TL_OPTIONAL_11_CONSTEXPR T&&
get() && {
5013 return std::move(this->m_value);
5015 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 5016 constexpr
const T&&
get()
const&& {
5017 return std::move(this->m_value);
5024 template <
class T,
bool = SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>
5034 using base_t::base_t;
5038 if (rhs.has_value()) {
5039 this->construct(rhs.get());
5042 this->m_has_value =
false;
5051 #ifndef SOL_TL_OPTIONAL_GCC49 5052 template <class T, bool = std::is_trivially_move_constructible<T>::value>
5057 template <
class T,
bool = false>
5068 if (rhs.has_value()) {
5069 this->construct(std::move(rhs.get()));
5072 this->m_has_value =
false;
5081 bool = SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) && SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)
5082 && SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T)>
5102 #ifndef SOL_TL_OPTIONAL_GCC49 5104 bool = std::is_trivially_destructible<T>::value&& std::is_trivially_move_constructible<T>::value&& std::is_trivially_move_assignable<T>::value>
5109 template <
class T,
bool = false>
5125 std::is_nothrow_move_constructible<T>::value&& std::is_nothrow_move_assignable<T>::value) {
5126 this->assign(std::move(rhs));
5133 template <class T, bool EnableCopy = std::is_copy_constructible<T>::value,
bool EnableMove = std::is_move_constructible<T>::value>
5171 template <class T, bool EnableCopy = (std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value),
5172 bool EnableMove = (std::is_move_constructible<T>::value && std::is_move_assignable<T>::value)>
5211 using nullopt_t = std::nullopt_t;
5230 const char*
what() const noexcept
override {
5231 return "Optional has no value";
5247 static_assert(!std::is_same<T, in_place_t>::value,
"instantiation of optional with in_place_t is ill-formed");
5248 static_assert(!std::is_same<detail::decay_t<T>, nullopt_t>::value,
"instantiation of optional with nullopt_t is ill-formed");
5251 #if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55) 5263 SOL_TL_OPTIONAL_11_CONSTEXPR
auto and_then(F&& f) & {
5264 using result = detail::invoke_result_t<F, T&>;
5267 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : result(nullopt);
5273 SOL_TL_OPTIONAL_11_CONSTEXPR
auto and_then(F&& f) && {
5274 using result = detail::invoke_result_t<F, T&&>;
5277 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**
this)) : result(nullopt);
5283 constexpr
auto and_then(F&& f)
const& {
5284 using result = detail::invoke_result_t<F, const T&>;
5287 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : result(nullopt);
5290 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 5294 constexpr
auto and_then(F&& f)
const&& {
5295 using result = detail::invoke_result_t<F, const T&&>;
5298 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**
this)) : result(nullopt);
5313 SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&>
and_then(F&& f) & {
5314 using result = detail::invoke_result_t<F, T&>;
5317 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : result(nullopt);
5323 SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&&>
and_then(F&& f) && {
5324 using result = detail::invoke_result_t<F, T&&>;
5327 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**
this)) : result(nullopt);
5333 constexpr detail::invoke_result_t<F, const T&>
and_then(F&& f)
const& {
5334 using result = detail::invoke_result_t<F, const T&>;
5337 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : result(nullopt);
5340 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 5344 constexpr detail::invoke_result_t<F, const T&&>
and_then(F&& f)
const&& {
5345 using result = detail::invoke_result_t<F, const T&&>;
5348 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**
this)) : result(nullopt);
5353 #if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55) 5364 SOL_TL_OPTIONAL_11_CONSTEXPR
auto map(F&& f) & {
5365 return optional_map_impl(*
this, std::forward<F>(f));
5371 SOL_TL_OPTIONAL_11_CONSTEXPR
auto map(F&& f) && {
5372 return optional_map_impl(std::move(*
this), std::forward<F>(f));
5378 constexpr
auto map(F&& f)
const& {
5379 return optional_map_impl(*
this, std::forward<F>(f));
5385 constexpr
auto map(F&& f)
const&& {
5386 return optional_map_impl(std::move(*
this), std::forward<F>(f));
5399 SOL_TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&>(), std::declval<F&&>())) map(F&& f) & {
5400 return optional_map_impl(*
this, std::forward<F>(f));
5406 SOL_TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&&>(), std::declval<F&&>())) map(F&& f) && {
5407 return optional_map_impl(std::move(*
this), std::forward<F>(f));
5413 constexpr decltype(optional_map_impl(std::declval<const optional&>(), std::declval<F&&>())) map(F&& f) const& {
5414 return optional_map_impl(*
this, std::forward<F>(f));
5417 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 5421 constexpr decltype(optional_map_impl(std::declval<const optional&&>(), std::declval<F&&>())) map(F&& f) const&& {
5422 return optional_map_impl(std::move(*
this), std::forward<F>(f));
5436 template <
class F, detail::enable_if_ret_
void<F>* =
nullptr>
5441 std::forward<F>(f)();
5446 template <
class F, detail::disable_if_ret_
void<F>* =
nullptr>
5448 return has_value() ? *this : std::forward<F>(f)();
5453 template <
class F, detail::enable_if_ret_
void<F>* =
nullptr>
5456 return std::move(*
this);
5458 std::forward<F>(f)();
5463 template <
class F, detail::disable_if_ret_
void<F>* =
nullptr>
5465 return has_value() ? std::move(*
this) : std::forward<F>(f)();
5470 template <
class F, detail::enable_if_ret_
void<F>* =
nullptr>
5475 std::forward<F>(f)();
5480 template <
class F, detail::disable_if_ret_
void<F>* =
nullptr>
5482 return has_value() ? *this : std::forward<F>(f)();
5485 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 5486 template <
class F, detail::enable_if_ret_
void<F>* =
nullptr>
5490 return std::move(*
this);
5492 std::forward<F>(f)();
5497 template <
class F, detail::disable_if_ret_
void<F>* =
nullptr>
5499 return has_value() ? std::move(*
this) : std::forward<F>(f)();
5510 template <
class F,
class U>
5512 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : std::forward<U>(u);
5516 template <
class F,
class U>
5518 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**
this)) : std::forward<U>(u);
5522 template <
class F,
class U>
5524 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : std::forward<U>(u);
5527 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 5528 template <
class F,
class U>
5531 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**
this)) : std::forward<U>(u);
5544 template <
class F,
class U>
5546 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : std::forward<U>(u)();
5552 template <
class F,
class U>
5554 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**
this)) : std::forward<U>(u)();
5560 template <
class F,
class U>
5562 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : std::forward<U>(u)();
5565 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 5566 template <
class F,
class U>
5571 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**
this)) : std::forward<U>(u)();
5579 return has_value() ? result { u } : result { nullopt };
5585 return has_value() ? *this : rhs;
5590 return has_value() ? *this : rhs;
5595 return has_value() ? std::move(*
this) : rhs;
5598 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 5601 return has_value() ? std::move(*
this) : rhs;
5607 return has_value() ? *this : std::move(rhs);
5612 return has_value() ? *this : std::move(rhs);
5617 return has_value() ? std::move(*
this) : std::move(rhs);
5620 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 5623 return has_value() ? std::move(*
this) : std::move(rhs);
5649 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 5662 constexpr
optional() noexcept =
default;
5683 template <
class... Args>
5684 constexpr
explicit optional(detail::enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>, Args&&... args)
5685 :
base(in_place,
std::forward<Args>(args)...) {
5690 template <
class U,
class... Args>
5691 SOL_TL_OPTIONAL_11_CONSTEXPR
explicit optional(detail::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, in_place_t>,
5692 std::initializer_list<U> il, Args&&... args) {
5693 this->construct(il, std::forward<Args>(args)...);
5696 #if 0 // SOL_MODIFICATION 5697 template <class U = T, detail::enable_if_t<std::is_convertible<U&&, T>::value>* =
nullptr, detail::enable_forward_value<T, U>* =
nullptr>
5700 constexpr
optional(U&& u) :
base(in_place, std::forward<U>(u)) {
5704 template <class U = T, detail::enable_if_t<!std::is_convertible<U&&, T>::value>* =
nullptr, detail::enable_forward_value<T, U>* =
nullptr>
5705 constexpr
explicit optional(U&& u) :
base(in_place, std::forward<U>(u)) {
5708 constexpr optional(T&& u) :
base(in_place, std::move(u)) {
5716 #endif // sol2 modification 5720 template <
class U, detail::enable_from_other<T, U, const U&>* =
nullptr, detail::enable_if_t<std::is_convertible<const U&, T>::value>* =
nullptr>
5723 this->construct(*rhs);
5728 template <
class U, detail::enable_from_other<T, U, const U&>* =
nullptr, detail::enable_if_t<!std::is_convertible<const U&, T>::value>* =
nullptr>
5731 this->construct(*rhs);
5737 template <
class U, detail::enable_from_other<T, U, U&&>* =
nullptr, detail::enable_if_t<std::is_convertible<U&&, T>::value>* =
nullptr>
5740 this->construct(std::move(*rhs));
5745 template <
class U, detail::enable_from_other<T, U, U&&>* =
nullptr, detail::enable_if_t<!std::is_convertible<U&&, T>::value>* =
nullptr>
5747 this->construct(std::move(*rhs));
5751 ~optional() =
default;
5759 this->m_has_value =
false;
5769 optional& operator=(
const optional& rhs) =
default;
5775 optional& operator=(optional&& rhs) =
default;
5780 template <
class U = T, detail::enable_assign_forward<T, U>* =
nullptr>
5783 this->m_value = std::forward<U>(u);
5786 this->construct(std::forward<U>(u));
5797 template <
class U, detail::enable_assign_from_other<T, U, const U&>* =
nullptr>
5801 this->m_value = *rhs;
5809 this->construct(*rhs);
5821 template <
class U, detail::enable_assign_from_other<T, U, U>* =
nullptr>
5825 this->m_value = std::move(*rhs);
5833 this->construct(std::move(*rhs));
5842 template <
class... Args>
5844 static_assert(std::is_constructible<T, Args&&...>::value,
"T must be constructible with Args");
5847 this->construct(std::forward<Args>(args)...);
5853 template <
class U,
class... Args>
5854 detail::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, T&>
emplace(std::initializer_list<U> il, Args&&... args) {
5856 this->construct(il, std::forward<Args>(args)...);
5873 new (std::addressof(rhs.m_value)) T(std::move(this->m_value));
5874 this->m_value.T::~T();
5878 new (std::addressof(this->m_value)) T(std::move(rhs.m_value));
5879 rhs.m_value.T::~T();
5888 return std::addressof(this->m_value);
5894 return std::addressof(this->m_value);
5902 return this->m_value;
5908 return this->m_value;
5913 return std::move(this->m_value);
5916 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 5917 constexpr
const T&& operator*()
const&& {
5919 return std::move(this->m_value);
5926 return this->m_has_value;
5930 constexpr
explicit operator bool() const noexcept {
5931 return this->m_has_value;
5938 SOL_TL_OPTIONAL_11_CONSTEXPR T&
value() & {
5940 return this->m_value;
5941 #if SOL_IS_OFF(SOL_EXCEPTIONS) 5945 #endif // No exceptions allowed 5949 SOL_TL_OPTIONAL_11_CONSTEXPR
const T&
value() const& {
5951 return this->m_value;
5952 #if SOL_IS_OFF(SOL_EXCEPTIONS) 5956 #endif // No exceptions allowed 5959 SOL_TL_OPTIONAL_11_CONSTEXPR T&&
value() && {
5961 return std::move(this->m_value);
5962 #if SOL_IS_OFF(SOL_EXCEPTIONS) 5966 #endif // No exceptions allowed 5969 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 5970 SOL_TL_OPTIONAL_11_CONSTEXPR
const T&& value()
const&& {
5973 return std::move(this->m_value);
5974 #if SOL_IS_OFF(SOL_EXCEPTIONS) 5978 #endif // No exceptions allowed 5986 static_assert(std::is_copy_constructible<T>::value && std::is_convertible<U&&, T>::value,
"T must be copy constructible and convertible from U");
5987 return has_value() ? **this :
static_cast<T
>(std::forward<U>(u));
5993 static_assert(std::is_move_constructible<T>::value && std::is_convertible<U&&, T>::value,
"T must be move constructible and convertible from U");
5994 return has_value() ? **this :
static_cast<T
>(std::forward<U>(u));
6001 this->m_has_value =
false;
6012 template <
class T,
class U>
6017 template <
class T,
class U>
6022 template <
class T,
class U>
6023 inline constexpr
bool operator<(const optional<T>& lhs,
const optional<U>& rhs) {
6024 return rhs.
has_value() && (!lhs.has_value() || *lhs < *rhs);
6027 template <
class T,
class U>
6032 template <
class T,
class U>
6033 inline constexpr
bool operator<=(const optional<T>& lhs,
const optional<U>& rhs) {
6037 template <
class T,
class U>
6046 inline constexpr
bool operator==(
const optional<T>& lhs, nullopt_t) noexcept {
6051 inline constexpr
bool operator==(nullopt_t,
const optional<T>& rhs) noexcept {
6056 inline constexpr
bool operator!=(
const optional<T>& lhs, nullopt_t) noexcept {
6061 inline constexpr
bool operator!=(nullopt_t,
const optional<T>& rhs) noexcept {
6066 inline constexpr
bool operator<(const optional<T>&, nullopt_t) noexcept {
6071 inline constexpr
bool operator<(nullopt_t, const optional<T>& rhs) noexcept {
6076 inline constexpr
bool operator<=(const optional<T>& lhs, nullopt_t) noexcept {
6081 inline constexpr
bool operator<=(nullopt_t, const optional<T>&) noexcept {
6086 inline constexpr
bool operator>(
const optional<T>& lhs, nullopt_t) noexcept {
6091 inline constexpr
bool operator>(nullopt_t,
const optional<T>&) noexcept {
6096 inline constexpr
bool operator>=(
const optional<T>&, nullopt_t) noexcept {
6101 inline constexpr
bool operator>=(nullopt_t,
const optional<T>& rhs) noexcept {
6110 template <
class T,
class U>
6111 inline constexpr
bool operator==(
const optional<T>& lhs,
const U& rhs) {
6112 return lhs.
has_value() ? *lhs == rhs :
false;
6115 template <
class T,
class U>
6116 inline constexpr
bool operator==(
const U& lhs,
const optional<T>& rhs) {
6117 return rhs.
has_value() ? lhs == *rhs :
false;
6120 template <
class T,
class U>
6121 inline constexpr
bool operator!=(
const optional<T>& lhs,
const U& rhs) {
6122 return lhs.
has_value() ? *lhs != rhs :
true;
6125 template <
class T,
class U>
6126 inline constexpr
bool operator!=(
const U& lhs,
const optional<T>& rhs) {
6127 return rhs.
has_value() ? lhs != *rhs :
true;
6130 template <
class T,
class U>
6131 inline constexpr
bool operator<(const optional<T>& lhs,
const U& rhs) {
6132 return lhs.
has_value() ? *lhs < rhs :
true;
6135 template <
class T,
class U>
6136 inline constexpr
bool operator<(const U& lhs, const optional<T>& rhs) {
6137 return rhs.
has_value() ? lhs < *rhs :
false;
6140 template <
class T,
class U>
6141 inline constexpr
bool operator<=(const optional<T>& lhs,
const U& rhs) {
6142 return lhs.
has_value() ? *lhs <= rhs :
true;
6145 template <
class T,
class U>
6146 inline constexpr
bool operator<=(const U& lhs, const optional<T>& rhs) {
6147 return rhs.
has_value() ? lhs <= *rhs :
false;
6150 template <
class T,
class U>
6151 inline constexpr
bool operator>(
const optional<T>& lhs,
const U& rhs) {
6152 return lhs.
has_value() ? *lhs > rhs :
false;
6155 template <
class T,
class U>
6156 inline constexpr
bool operator>(
const U& lhs,
const optional<T>& rhs) {
6157 return rhs.
has_value() ? lhs > *rhs :
true;
6160 template <
class T,
class U>
6161 inline constexpr
bool operator>=(
const optional<T>& lhs,
const U& rhs) {
6162 return lhs.
has_value() ? *lhs >= rhs :
false;
6165 template <
class T,
class U>
6166 inline constexpr
bool operator>=(
const U& lhs,
const optional<T>& rhs) {
6167 return rhs.
has_value() ? lhs >= *rhs :
true;
6171 template <class T, detail::enable_if_t<std::is_move_constructible<T>::value>* =
nullptr, detail::enable_if_t<detail::is_swappable<T>::value>* =
nullptr>
6173 return lhs.
swap(rhs);
6180 template <class T = detail::i_am_secret, class U, class Ret = detail::conditional_t<std::is_same<T, detail::i_am_secret>::value, detail::decay_t<U>, T>>
6185 template <
class T,
class... Args>
6186 inline constexpr
optional<T> make_optional(Args&&... args) {
6187 return optional<T>(in_place, std::forward<Args>(args)...);
6189 template <
class T,
class U,
class... Args>
6190 inline constexpr
optional<T> make_optional(std::initializer_list<U> il, Args&&... args) {
6191 return optional<T>(in_place, il, std::forward<Args>(args)...);
6194 #if __cplusplus >= 201703L 6201 #ifdef SOL_TL_OPTIONAL_CXX14 6202 template <
class Opt,
class F,
class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())),
6203 detail::enable_if_t<!std::is_
void<Ret>::value>* =
nullptr>
6204 constexpr
auto optional_map_impl(Opt&& opt, F&& f) {
6205 return opt.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt)) :
optional<Ret>(nullopt);
6208 template <
class Opt,
class F,
class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())),
6209 detail::enable_if_t<std::is_
void<Ret>::value>* =
nullptr>
6210 auto optional_map_impl(Opt&& opt, F&& f) {
6211 if (opt.has_value()) {
6212 detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
6219 template <
class Opt,
class F,
class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())),
6220 detail::enable_if_t<!std::is_
void<Ret>::value>* =
nullptr>
6222 constexpr
auto optional_map_impl(Opt&& opt, F&& f) ->
optional<Ret> {
6223 return opt.
has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt)) :
optional<Ret>(nullopt);
6226 template <
class Opt,
class F,
class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())),
6227 detail::enable_if_t<std::is_
void<Ret>::value>* =
nullptr>
6230 if (opt.has_value()) {
6231 detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
6265 #if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55) 6277 SOL_TL_OPTIONAL_11_CONSTEXPR
auto and_then(F&& f) & {
6278 using result = detail::invoke_result_t<F, T&>;
6281 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : result(nullopt);
6287 SOL_TL_OPTIONAL_11_CONSTEXPR
auto and_then(F&& f) && {
6288 using result = detail::invoke_result_t<F, T&>;
6291 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : result(nullopt);
6297 constexpr
auto and_then(F&& f)
const& {
6298 using result = detail::invoke_result_t<F, const T&>;
6301 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : result(nullopt);
6304 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 6308 constexpr
auto and_then(F&& f)
const&& {
6309 using result = detail::invoke_result_t<F, const T&>;
6312 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : result(nullopt);
6327 SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&>
and_then(F&& f) & {
6328 using result = detail::invoke_result_t<F, T&>;
6331 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : result(nullopt);
6337 SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&>
and_then(F&& f) && {
6338 using result = detail::invoke_result_t<F, T&>;
6341 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : result(nullopt);
6347 constexpr detail::invoke_result_t<F, const T&>
and_then(F&& f)
const& {
6348 using result = detail::invoke_result_t<F, const T&>;
6351 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : result(nullopt);
6354 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 6358 constexpr detail::invoke_result_t<F, const T&>
and_then(F&& f)
const&& {
6359 using result = detail::invoke_result_t<F, const T&>;
6362 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : result(nullopt);
6367 #if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55) 6378 SOL_TL_OPTIONAL_11_CONSTEXPR
auto map(F&& f) & {
6379 return detail::optional_map_impl(*
this, std::forward<F>(f));
6385 SOL_TL_OPTIONAL_11_CONSTEXPR
auto map(F&& f) && {
6386 return detail::optional_map_impl(std::move(*
this), std::forward<F>(f));
6392 constexpr
auto map(F&& f)
const& {
6393 return detail::optional_map_impl(*
this, std::forward<F>(f));
6399 constexpr
auto map(F&& f)
const&& {
6400 return detail::optional_map_impl(std::move(*
this), std::forward<F>(f));
6413 SOL_TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&>(), std::declval<F&&>())) map(F&& f) & {
6414 return detail::optional_map_impl(*
this, std::forward<F>(f));
6420 SOL_TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&&>(), std::declval<F&&>())) map(F&& f) && {
6421 return detail::optional_map_impl(std::move(*
this), std::forward<F>(f));
6427 constexpr decltype(detail::optional_map_impl(std::declval<const optional&>(), std::declval<F&&>())) map(F&& f) const& {
6428 return detail::optional_map_impl(*
this, std::forward<F>(f));
6431 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 6435 constexpr decltype(detail::optional_map_impl(std::declval<const optional&&>(), std::declval<F&&>())) map(F&& f) const&& {
6436 return detail::optional_map_impl(std::move(*
this), std::forward<F>(f));
6449 template <
class F, detail::enable_if_ret_
void<F>* =
nullptr>
6454 std::forward<F>(f)();
6459 template <
class F, detail::disable_if_ret_
void<F>* =
nullptr>
6461 return has_value() ? *this : std::forward<F>(f)();
6466 template <
class F, detail::enable_if_ret_
void<F>* =
nullptr>
6469 return std::move(*
this);
6471 std::forward<F>(f)();
6476 template <
class F, detail::disable_if_ret_
void<F>* =
nullptr>
6478 return has_value() ? std::move(*
this) : std::forward<F>(f)();
6483 template <
class F, detail::enable_if_ret_
void<F>* =
nullptr>
6488 std::forward<F>(f)();
6493 template <
class F, detail::disable_if_ret_
void<F>* =
nullptr>
6495 return has_value() ? *this : std::forward<F>(f)();
6498 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 6499 template <
class F, detail::enable_if_ret_
void<F>* =
nullptr>
6503 return std::move(*
this);
6505 std::forward<F>(f)();
6510 template <
class F, detail::disable_if_ret_
void<F>* =
nullptr>
6512 return has_value() ? std::move(*
this) : std::forward<F>(f)();
6523 template <
class F,
class U>
6525 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : std::forward<U>(u);
6529 template <
class F,
class U>
6531 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**
this)) : std::forward<U>(u);
6535 template <
class F,
class U>
6537 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : std::forward<U>(u);
6540 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 6541 template <
class F,
class U>
6544 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**
this)) : std::forward<U>(u);
6557 template <
class F,
class U>
6559 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : std::forward<U>(u)();
6565 template <
class F,
class U>
6567 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**
this)) : std::forward<U>(u)();
6573 template <
class F,
class U>
6575 return has_value() ? detail::invoke(std::forward<F>(f), **
this) : std::forward<U>(u)();
6578 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 6579 template <
class F,
class U>
6584 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**
this)) : std::forward<U>(u)();
6592 return has_value() ? result { u } : result { nullopt };
6598 return has_value() ? *this : rhs;
6603 return has_value() ? *this : rhs;
6608 return has_value() ? std::move(*
this) : rhs;
6611 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 6614 return has_value() ? std::move(*
this) : rhs;
6620 return has_value() ? *this : std::move(rhs);
6625 return has_value() ? *this : std::move(rhs);
6630 return has_value() ? std::move(*
this) : std::move(rhs);
6633 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 6636 return has_value() ? std::move(*
this) : std::move(rhs);
6662 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 6671 using value_type = T&;
6679 constexpr
optional(nullopt_t) noexcept : m_value(
nullptr) {
6686 SOL_TL_OPTIONAL_11_CONSTEXPR
optional(
const optional& rhs) noexcept =
default;
6696 template <
class U = T, detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>* =
nullptr>
6698 static_assert(std::is_lvalue_reference<U>::value,
"U must be an lvalue");
6727 template <
class U = T, detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>* =
nullptr>
6729 static_assert(std::is_lvalue_reference<U>::value,
"U must be an lvalue");
6730 m_value = std::addressof(u);
6740 m_value = std::addressof(rhs.
value());
6748 template <
class... Args>
6750 static_assert(std::is_constructible<T, Args&&...>::value,
"T must be constructible with Args");
6753 this->construct(std::forward<Args>(args)...);
6763 std::swap(m_value, rhs.m_value);
6797 return m_value !=
nullptr;
6801 constexpr
explicit operator bool() const noexcept {
6802 return m_value !=
nullptr;
6809 SOL_TL_OPTIONAL_11_CONSTEXPR T&
value() {
6812 #if SOL_IS_OFF(SOL_EXCEPTIONS) 6816 #endif // No exceptions allowed 6820 SOL_TL_OPTIONAL_11_CONSTEXPR
const T&
value()
const {
6823 #if SOL_IS_OFF(SOL_EXCEPTIONS) 6827 #endif // No exceptions allowed 6834 static_assert(std::is_convertible<U&&, T&>::value,
"T must be convertible from U");
6835 return has_value() ?
const_cast<T&
>(**this) :
static_cast<T&
>(std::forward<U>(u));
6853 ::std::size_t operator()(const ::sol::optional<T>& o)
const {
6857 return ::std::hash<::sol::detail::remove_const_t<T>>()(*o);
6864 #endif // Boost vs. Better optional 6870 #if SOL_IS_ON(SOL_USE_BOOST) 6871 template <
typename T>
6872 using optional = boost::optional<T>;
6873 using nullopt_t = boost::none_t;
6874 SOL_BOOST_NONE_CONSTEXPR_I_ nullopt_t nullopt = boost::none;
6875 #endif // Boost vs. Better optional 6878 template <
typename T>
6879 using is_optional = any<is_specialization_of<T, optional>, is_specialization_of<T, std::optional>>;
6881 template <
typename T>
6882 constexpr
inline bool is_optional_v = is_optional<T>::value;
6886 template <
typename T>
6888 inline static constexpr std::nullopt_t value = std::nullopt;
6891 #if SOL_IS_ON(SOL_USE_BOOST) 6892 template <
typename T>
6894 inline static SOL_BOOST_NONE_CONSTEXPR_I_ boost::none_t value = boost::none;
6896 #endif // Boost nullopt 6898 #if SOL_IS_ON(SOL_USE_BOOST) 6899 template <
typename T>
6902 template <
typename T>
6904 #endif // Boost continues to lag behind, to not many people's surprise... 6908 #if SOL_IS_ON(SOL_USE_BOOST) 6909 #undef SOL_BOOST_NONE_CONSTEXPR_I_ 6921 template <
typename T,
typename... Args>
6922 static void construct(T&& obj, Args&&... args) {
6923 typedef meta::unqualified_t<T> Tu;
6924 std::allocator<Tu> alloc {};
6925 std::allocator_traits<std::allocator<Tu>>::construct(alloc, std::forward<T>(obj), std::forward<Args>(args)...);
6928 template <
typename T,
typename... Args>
6929 void operator()(T&& obj, Args&&... args)
const {
6930 construct(std::forward<T>(obj), std::forward<Args>(args)...);
6935 template <
typename T>
6936 static void destroy(T&& obj) {
6937 std::allocator<meta::unqualified_t<T>> alloc {};
6941 template <
typename T>
6942 void operator()(T&& obj)
const {
6943 destroy(std::forward<T>(obj));
6948 template <
typename T>
6949 void operator()(T* p)
const {
6960 template <
typename T,
typename Dx,
typename... Args>
6961 inline std::unique_ptr<T, Dx> make_unique_deleter(Args&&... args) {
6962 return std::unique_ptr<T, Dx>(
new T(std::forward<Args>(args)...));
6965 template <
typename Tag,
typename T>
6971 template <
typename Arg,
typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>,
tagged>> = meta::enabler>
6972 tagged(Arg&& arg, Args&&... args) : value_(std::forward<Arg>(arg), std::forward<Args>(args)...) {
6979 T
const& value()
const& {
6984 return std::move(value_);
6989 template <
typename... Args>
6992 template <
typename... Args>
7003 template <
typename... Functions>
7005 std::tuple<Functions...> functions;
7006 template <
typename Arg,
typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>,
constructor_wrapper>> = meta::enabler>
7007 constructor_wrapper(Arg&& arg, Args&&... args) : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) {
7011 template <
typename... Functions>
7012 inline auto initializers(Functions&&... functions) {
7016 template <
typename... Functions>
7018 std::tuple<Functions...> functions;
7019 template <
typename Arg,
typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>,
factory_wrapper>> = meta::enabler>
7020 factory_wrapper(Arg&& arg, Args&&... args) : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) {
7024 template <
typename... Functions>
7025 inline auto factories(Functions&&... functions) {
7029 template <
typename Function>
7041 template <
typename Fx>
7042 inline auto destructor(Fx&& fx) {
7059 template <
int Target,
int... In>
7062 template <
int... In>
7068 std::array<int, 64> stack_indices;
7071 template <
typename... Args>
7072 stack_dependencies(
int stack_target, Args&&... args) : target(stack_target), stack_indices(), len(
sizeof...(Args)) {
7074 (void)detail::swallow { int(), (stack_indices[i++] =
static_cast<int>(std::forward<Args>(args)), int())... };
7077 int& operator[](std::size_t i) {
7078 return stack_indices[i];
7081 const int& operator[](std::size_t i)
const {
7082 return stack_indices[i];
7085 std::size_t size()
const {
7090 template <
typename F,
typename... Policies>
7092 typedef std::index_sequence_for<Policies...> indices;
7095 std::tuple<Policies...> policies;
7097 template <
typename Fx,
typename... Args, meta::enable<meta::neg<std::is_same<meta::unqualified_t<Fx>,
policy_wrapper>>> = meta::enabler>
7098 policy_wrapper(Fx&& fx, Args&&... args) : value(std::forward<Fx>(fx)), policies(std::forward<Args>(args)...) {
7101 policy_wrapper(
const policy_wrapper&) =
default;
7102 policy_wrapper& operator=(
const policy_wrapper&) =
default;
7103 policy_wrapper(policy_wrapper&&) =
default;
7104 policy_wrapper& operator=(policy_wrapper&&) =
default;
7107 template <
typename F,
typename... Args>
7108 auto policies(F&& f, Args&&... args) {
7113 template <
typename T>
7116 template <
typename T>
7117 inline constexpr
bool is_policy_v = is_policy<T>::value;
7125 #include <type_traits> 7129 namespace sol {
namespace detail {
7131 template <
typename T, std::
size_t tag = 0,
typename =
void>
7138 ebco& operator=(
const ebco&) =
default;
7140 ebco(
const T& v) noexcept(std::is_nothrow_copy_constructible_v<T>) : m_value(v) {};
7141 ebco(T&& v) noexcept(std::is_nothrow_move_constructible_v<T>) : m_value(std::move(v)) {};
7142 ebco& operator=(
const T& v) noexcept(std::is_nothrow_copy_assignable_v<T>) {
7146 ebco& operator=(T&& v) noexcept(std::is_nothrow_move_assignable_v<T>) {
7147 m_value = std::move(v);
7150 template <
typename Arg,
typename... Args,
7151 typename = std::enable_if_t<
7152 !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
7153 ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T> && (
sizeof...(Args) > 0 || !std::is_convertible_v<Arg, T>)>>
7154 ebco(Arg&& arg, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Arg, Args...>)
7155 : m_value(std::forward<Arg>(arg), std::forward<Args>(args)...) {
7158 T& value() & noexcept {
7162 T
const& value()
const& noexcept {
7166 T&& value() && noexcept {
7167 return std::move(m_value);
7171 template <
typename T, std::
size_t tag>
7172 struct ebco<T, tag,
std::enable_if_t<!std::is_reference_v<T> && std::is_class_v<T> && !std::is_final_v<T>>> : T {
7176 ebco(
const T& v) noexcept(std::is_nothrow_copy_constructible_v<T>) : T(v) {};
7177 ebco(T&& v) noexcept(std::is_nothrow_move_constructible_v<T>) : T(std::move(v)) {};
7178 template <
typename Arg,
typename... Args,
7179 typename = std::enable_if_t<
7180 !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
7181 ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T> && (
sizeof...(Args) > 0 || !std::is_convertible_v<Arg, T>)>>
7182 ebco(Arg&& arg, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Arg, Args...>) : T(std::forward<Arg>(arg), std::forward<Args>(args)...) {
7185 ebco& operator=(
const ebco&) =
default;
7187 ebco& operator=(
const T& v) noexcept(std::is_nothrow_copy_assignable_v<T>) {
7188 static_cast<T&
>(*this) = v;
7191 ebco& operator=(T&& v) noexcept(std::is_nothrow_move_assignable_v<T>) {
7192 static_cast<T&
>(*this) = std::move(v);
7196 T& value() & noexcept {
7197 return static_cast<T&
>(*this);
7200 T
const& value()
const& noexcept {
7201 return static_cast<T const&
>(*this);
7204 T&& value() && noexcept {
7205 return std::move(static_cast<T&>(*
this));
7209 template <
typename T, std::
size_t tag>
7218 ebco(T& v) noexcept : m_ref(std::addressof(v)) {};
7220 ebco& operator=(
const ebco&) =
default;
7222 ebco& operator=(T& v) noexcept {
7223 m_ref = std::addressof(v);
7227 T& value()
const noexcept {
7232 template <
typename T, std::
size_t tag>
7239 ebco(T&& v) noexcept : ref(v) {};
7241 ebco& operator=(
const ebco&) =
delete;
7244 T& value() & noexcept {
7248 const T& value()
const& noexcept {
7252 T&& value() && noexcept {
7253 return std::move(ref);
7262 #include <initializer_list> 7264 #include <string_view> 7267 #if SOL_IS_ON(SOL_STD_VARIANT) 7269 #endif // variant shenanigans (thanks, Mac OSX) 7277 template <
typename T>
7282 #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) 7283 typedef int (*lua_CFunction_noexcept)(
lua_State* L) noexcept;
7285 typedef int (*lua_CFunction_noexcept)(
lua_State* L);
7286 #endif // noexcept function type for lua_CFunction 7288 template <
typename T>
7303 return std::addressof(value);
7319 #if SOL_IS_ON(SOL_NIL) 7321 inline constexpr
const nil_t& nil = lua_nil;
7332 }
inline constexpr global_tag {};
7340 template <
typename T>
7349 template <
typename Arg,
7350 meta::enable<meta::neg<std::is_same<meta::unqualified_t<Arg>,
yielding_t>>,
7351 meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<Arg>>>> = meta::enabler>
7352 yielding_t(Arg&& arg) : func(std::forward<Arg>(arg)) {
7354 template <
typename Arg0,
typename Arg1,
typename... Args>
7355 yielding_t(Arg0&& arg0, Arg1&& arg1, Args&&... args) : func(std::forward<Arg0>(arg0), std::forward<Arg1>(arg1), std::forward<Args>(args)...) {
7359 template <
typename F>
7364 typedef std::remove_pointer_t<lua_CFunction> lua_CFunction_ref;
7366 template <
typename T>
7369 template <
typename... Args>
7377 operator int()
const {
7387 operator int()
const {
7397 operator int()
const {
7407 operator int()
const {
7423 operator void*()
const {
7436 void* value()
const {
7440 operator void*()
const {
7445 template <
typename T>
7448 static_assert(!std::is_void_v<T>,
"the type for light will never be void");
7452 light(T& x) : m_value(std::addressof(x)) {
7454 light(T* x) : m_value(x) {
7456 explicit light(
void* x) : m_value(static_cast<T*>(x)) {
7463 operator T*()
const {
7466 operator T&()
const {
7470 void* void_value()
const {
7475 template <
typename T>
7476 auto make_light(T& l) {
7477 typedef meta::unwrapped_t<std::remove_pointer_t<std::remove_pointer_t<T>>> L;
7481 template <
typename T>
7487 using base_t::base_t;
7489 using base_t::value;
7491 operator std::add_pointer_t<std::remove_reference_t<T>>() {
7492 return std::addressof(this->base_t::value());
7495 operator std::add_pointer_t<std::add_const_t<std::remove_reference_t<T>>>()
const {
7496 return std::addressof(this->base_t::value());
7499 operator std::add_lvalue_reference_t<T>() {
7500 return this->base_t::value();
7503 operator std::add_const_t<std::add_lvalue_reference_t<T>>&()
const {
7504 return this->base_t::value();
7508 template <
typename T>
7509 auto make_user(T&& u) {
7510 typedef meta::unwrapped_t<meta::unqualified_t<T>> U;
7511 return user<U>(std::forward<T>(u));
7514 template <
typename T>
7520 using base_t::base_t;
7522 using base_t::value;
7525 template <
typename T>
7526 auto meta_registry_key(T&& key) {
7527 typedef meta::unqualified_t<T> K;
7531 template <
typename... Upvalues>
7533 lua_CFunction c_function;
7534 std::tuple<Upvalues...> upvalues;
7535 closure(lua_CFunction f, Upvalues... targetupvalues) : c_function(f), upvalues(std::forward<Upvalues>(targetupvalues)...) {
7541 lua_CFunction c_function;
7543 closure(lua_CFunction f,
int upvalue_count = 0) : c_function(f), upvalues(upvalue_count) {
7549 template <
typename... Args>
7550 closure<Args...> make_closure(lua_CFunction f, Args&&... args) {
7551 return closure<Args...>(f, std::forward<Args>(args)...);
7554 template <
typename Sig,
typename... Ps>
7556 std::tuple<Ps...> arguments;
7557 template <
typename Arg,
typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>,
function_arguments>> = meta::enabler>
7558 function_arguments(Arg&& arg, Args&&... args) : arguments(std::forward<Arg>(arg), std::forward<Args>(args)...) {
7562 template <
typename Sig = function_sig<>,
typename... Args>
7563 auto as_function(Args&&... args) {
7567 template <
typename Sig = function_sig<>,
typename... Args>
7568 auto as_function_reference(Args&&... args) {
7572 template <
typename T>
7583 as_table_t(
const meta::unqualified_t<T>& obj) noexcept(std::is_nothrow_constructible_v<base_t,
const meta::unqualified_t<T>&>) : base_t(obj) {
7585 as_table_t(meta::unqualified_t<T>&& obj) noexcept(std::is_nothrow_constructible_v<base_t, meta::unqualified_t<T>&&>) : base_t(std::move(obj)) {
7587 template <
typename Arg,
typename... Args,
7589 !std::is_same_v<as_table_t, meta::unqualified_t<Arg>> && !std::is_same_v<meta::unqualified_t<T>, meta::unqualified_t<Arg>>>* =
nullptr>
7590 as_table_t(Arg&& arg, Args&&... args) noexcept(std::is_nothrow_constructible_v<base_t, Arg, Args...>)
7591 : base_t(std::forward<Arg>(arg), std::forward<Args>(args)...) {
7594 using base_t::value;
7596 operator std::add_lvalue_reference_t<T>() {
7597 return this->base_t::value();
7600 operator std::add_const_t<std::add_lvalue_reference_t<T>>()
const {
7601 return this->base_t::value();
7605 template <
typename T>
7611 using nested_type = T;
7618 nested(
const meta::unqualified_t<T>& obj) noexcept(std::is_nothrow_constructible_v<base_t,
const meta::unqualified_t<T>&>) : base_t(obj) {
7620 nested(meta::unqualified_t<T>&& obj) noexcept(std::is_nothrow_constructible_v<base_t, meta::unqualified_t<T>&&>) : base_t(std::move(obj)) {
7622 template <
typename Arg,
typename... Args,
7624 !std::is_same_v<nested, meta::unqualified_t<Arg>> && !std::is_same_v<meta::unqualified_t<T>, meta::unqualified_t<Arg>>>* =
nullptr>
7625 nested(Arg&& arg, Args&&... args) noexcept(std::is_nothrow_constructible_v<base_t, Arg, Args...>)
7626 : base_t(std::forward<Arg>(arg), std::forward<Args>(args)...) {
7629 using base_t::value;
7631 operator std::add_lvalue_reference_t<T>() {
7632 return this->base_t::value();
7635 operator std::add_const_t<std::add_lvalue_reference_t<T>>()
const {
7636 return this->base_t::value();
7643 template <
typename T>
7648 template <
typename T>
7653 template <
typename T>
7654 nested<T> as_nested_ref(T&& container) {
7655 return nested<T>(std::forward<T>(container));
7658 template <
typename T>
7663 template <
typename T>
7677 using base_t::base_t;
7679 using base_t::value;
7681 operator std::add_lvalue_reference_t<T>() {
7686 template <
typename T>
7687 auto as_container(T&& value) {
7691 template <
typename T>
7703 using base_t::base_t;
7705 using base_t::value;
7708 template <
typename Fx>
7709 auto push_invoke(Fx&& fx) {
7713 template <
typename T>
7725 using base_t::base_t;
7727 using base_t::value;
7730 template <
typename T>
7731 auto pass_as_value(T& value_ref_) {
7743 enum insert_mode { none = 0x0, update_if_empty = 0x01, override_value = 0x02, create_if_nil = 0x04 };
7745 template <
typename T,
typename...>
7746 using is_insert_mode = std::integral_constant<bool,
7747 std::is_same_v<T, override_value_t> || std::is_same_v<T, update_if_empty_t> || std::is_same_v<T, create_if_nil_t>>;
7749 template <
typename T,
typename...>
7750 using is_not_insert_mode = meta::neg<is_insert_mode<T>>;
7763 lua_State* operator->()
const noexcept {
7782 lua_State* operator->()
const noexcept {
7792 int sequence_hint = 0;
7801 new_table(
int sequence_hint_,
int map_hint_ = 0) noexcept : sequence_hint(sequence_hint_), map_hint(map_hint_) {
7807 enum class lib : unsigned char {
7838 enum class call_syntax { dot = 0, colon = 1 };
7840 enum class load_mode {
7846 enum class call_status : int {
7848 yielded = LUA_YIELD,
7849 runtime = LUA_ERRRUN,
7850 memory = LUA_ERRMEM,
7851 handler = LUA_ERRERR,
7853 syntax = LUA_ERRSYNTAX,
7857 enum class thread_status : int {
7859 yielded = LUA_YIELD,
7860 runtime = LUA_ERRRUN,
7861 memory = LUA_ERRMEM,
7863 handler = LUA_ERRERR,
7867 enum class load_status : int {
7869 syntax = LUA_ERRSYNTAX,
7870 memory = LUA_ERRMEM,
7875 enum class gc_mode : int {
7878 default_value = incremental,
7881 enum class type : int {
7884 #if SOL_IS_ON(SOL_NIL) 7886 #endif // Objective C/C++ Keyword that's found in OSX SDK and OBJC -- check for all forms to protect 7887 string = LUA_TSTRING,
7888 number = LUA_TNUMBER,
7890 boolean = LUA_TBOOLEAN,
7891 function = LUA_TFUNCTION,
7898 inline const std::string& to_string(call_status c) {
7899 static const std::array<std::string, 10> names { {
"ok",
7907 "CRITICAL_EXCEPTION_FAILURE",
7908 "CRITICAL_INDETERMINATE_STATE_FAILURE" } };
7910 case call_status::ok:
7912 case call_status::yielded:
7914 case call_status::runtime:
7916 case call_status::memory:
7918 case call_status::handler:
7920 case call_status::gc:
7922 case call_status::syntax:
7924 case call_status::file:
7927 if (static_cast<std::ptrdiff_t>(c) == -1) {
7934 inline bool is_indeterminate_call_failure(call_status c) {
7936 case call_status::ok:
7937 case call_status::yielded:
7938 case call_status::runtime:
7939 case call_status::memory:
7940 case call_status::handler:
7941 case call_status::gc:
7942 case call_status::syntax:
7943 case call_status::file:
7949 inline const std::string& to_string(load_status c) {
7950 static const std::array<std::string, 7> names {
7951 {
"ok",
"memory",
"gc",
"syntax",
"file",
"CRITICAL_EXCEPTION_FAILURE",
"CRITICAL_INDETERMINATE_STATE_FAILURE" }
7954 case load_status::ok:
7956 case load_status::memory:
7958 case load_status::gc:
7960 case load_status::syntax:
7962 case load_status::file:
7965 if (static_cast<int>(c) == -1) {
7972 inline const std::string& to_string(load_mode c) {
7973 static const std::array<std::string, 3> names { {
7978 return names[
static_cast<std::size_t
>(c)];
7981 enum class meta_function : unsigned {
7987 call_function = call,
7998 involution = power_of,
8002 less_than_or_equal_to,
8006 bitwise_right_shift,
8023 typedef meta_function meta_method;
8025 inline const std::array<std::string, 37>& meta_function_names() {
8026 static const std::array<std::string, 37> names = { {
"new",
8064 "__sol.static_index",
8065 "__sol.static_new_index" } };
8069 inline const std::string& to_string(meta_function mf) {
8070 return meta_function_names()[
static_cast<std::size_t
>(mf)];
8073 inline type type_of(
lua_State* L,
int index) {
8074 return static_cast<type
>(lua_type(L, index));
8077 inline std::string type_name(
lua_State* L, type t) {
8078 return lua_typename(L, static_cast<int>(t));
8081 template <
typename T>
8083 : std::integral_constant<bool,
8084 (std::is_base_of_v<stateless_stack_reference, T> || std::is_base_of_v<stateless_reference, T>)&&(
8085 !std::is_base_of_v<stack_reference, T> && !std::is_base_of_v<reference, T> && !std::is_base_of_v<main_reference, T>)> { };
8087 template <
typename T>
8090 template <
typename T>
8092 : std::integral_constant<bool,
8093 std::is_base_of_v<reference,
8094 T> || std::is_base_of_v<main_reference, T> || std::is_base_of_v<stack_reference, T> || std::is_base_of_v<stateless_stack_reference, T> || std::is_base_of_v<stateless_reference, T>> {
8097 template <
typename T>
8100 template <
typename T>
8103 template <
typename T>
8106 template <
typename T>
8108 : std::integral_constant<bool,
8109 std::is_same_v<meta::unqualified_t<T>,
8110 this_state> || std::is_same_v<meta::unqualified_t<T>, this_main_state> || std::is_same_v<meta::unqualified_t<T>, this_environment> || std::is_same_v<meta::unqualified_t<T>, variadic_args>> {
8113 template <
typename T>
8116 template <
typename T>
8119 template <
typename T>
8121 : std::integral_constant<bool,
8122 !std::is_same_v<state_view,
8123 T> && !std::is_same_v<state, T> && !meta::is_initializer_list_v<T> && !meta::is_string_like_v<T> && !meta::is_string_literal_array_v<T> && !is_transparent_argument_v<T> && !is_lua_reference_v<T> && (meta::has_begin_end_v<T> || std::is_array_v<T>)> {
8126 template <
typename T>
8129 template <
typename T>
8130 struct is_to_stringable :
meta::any<meta::supports_to_string_member<meta::unqualified_t<T>>, meta::supports_adl_to_string<meta::unqualified_t<T>>,
8131 meta::supports_op_left_shift<std::ostream, meta::unqualified_t<T>>> { };
8133 template <
typename T>
8136 template <
typename T>
8139 template <
typename T>
8143 template <
typename T,
typename =
void>
8144 struct lua_type_of : std::integral_constant<type, type::userdata> { };
8146 template <
typename C,
typename T,
typename A>
8147 struct lua_type_of<
std::basic_string<C, T, A>> : std::integral_constant<type, type::string> { };
8149 template <
typename C,
typename T>
8150 struct lua_type_of<basic_string_view<C, T>> : std::integral_constant<type, type::string> { };
8152 template <std::
size_t N>
8153 struct lua_type_of<char[N]> : std::integral_constant<type, type::string> { };
8155 template <std::
size_t N>
8156 struct lua_type_of<wchar_t[N]> : std::integral_constant<type, type::string> { };
8158 #if SOL_IS_ON(SOL_CHAR8_T) 8159 template <std::
size_t N>
8160 struct lua_type_of<char8_t[N]> : std::integral_constant<type, type::string> { };
8163 template <std::
size_t N>
8164 struct lua_type_of<char16_t[N]> : std::integral_constant<type, type::string> { };
8166 template <std::
size_t N>
8167 struct lua_type_of<char32_t[N]> : std::integral_constant<type, type::string> { };
8170 struct lua_type_of<char> : std::integral_constant<type, type::string> { };
8173 struct lua_type_of<wchar_t> : std::integral_constant<type, type::string> { };
8175 #if SOL_IS_ON(SOL_CHAR8_T) 8177 struct lua_type_of<char8_t> : std::integral_constant<type, type::string> { };
8181 struct lua_type_of<char16_t> : std::integral_constant<type, type::string> { };
8184 struct lua_type_of<char32_t> : std::integral_constant<type, type::string> { };
8187 struct lua_type_of<const char*> : std::integral_constant<type, type::string> { };
8190 struct lua_type_of<const wchar_t*> : std::integral_constant<type, type::string> { };
8192 #if SOL_IS_ON(SOL_CHAR8_T) 8194 struct lua_type_of<const char8_t*> : std::integral_constant<type, type::string> { };
8198 struct lua_type_of<const char16_t*> : std::integral_constant<type, type::string> { };
8201 struct lua_type_of<const char32_t*> : std::integral_constant<type, type::string> { };
8204 struct lua_type_of<bool> : std::integral_constant<type, type::boolean> { };
8210 struct lua_type_of<nullopt_t> : std::integral_constant<type, type::lua_nil> { };
8219 struct lua_type_of<std::nullptr_t> : std::integral_constant<type, type::lua_nil> { };
8224 template <
bool b,
typename Base>
8227 template <
typename Base>
8230 template <
typename Base>
8233 template <
typename T,
typename Base>
8239 template <
typename B>
8248 template <
typename T>
8251 template <
typename T>
8252 struct lua_type_of<std::initializer_list<T>> : std::integral_constant<type, type::table> { };
8260 template <
typename Base>
8263 template <
typename... Args>
8264 struct lua_type_of<std::tuple<Args...>> : std::integral_constant<type, type::poly> { };
8266 template <
typename A,
typename B>
8267 struct lua_type_of<std::pair<A, B>> : std::integral_constant<type, type::poly> { };
8270 struct lua_type_of<void*> : std::integral_constant<type, type::lightuserdata> { };
8273 struct lua_type_of<const void*> : std::integral_constant<type, type::lightuserdata> { };
8281 template <
typename T>
8284 template <
typename T>
8287 template <
typename Base>
8290 template <
typename Base>
8294 struct lua_type_of<lua_CFunction> : std::integral_constant<type, type::function> { };
8297 struct lua_type_of<std::remove_pointer_t<lua_CFunction>> : std::integral_constant<type, type::function> { };
8299 template <
typename Base,
bool aligned>
8302 template <
typename Base,
bool aligned,
typename Handler>
8305 template <
typename Base>
8308 template <
typename Base>
8311 template <
typename Signature>
8314 template <
typename T>
8317 template <
typename T>
8339 struct lua_type_of<type> : std::integral_constant<type, type::poly> { };
8341 #if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE) 8342 template <
typename T>
8343 struct lua_type_of<T*> : std::integral_constant<type, std::is_function_v<T> ? type::function : type::userdata> { };
8345 template <
typename T>
8346 struct lua_type_of<T*> : std::integral_constant<type, type::userdata> { };
8349 template <
typename T>
8350 struct lua_type_of<T, std::enable_if_t<std::is_arithmetic_v<T> || std::is_same_v<T, lua_Number> || std::is_same_v<T, lua_Integer>>>
8351 : std::integral_constant<type, type::number> { };
8353 template <
typename T>
8354 struct lua_type_of<T, std::enable_if_t<std::is_function_v<T>>> : std::integral_constant<type, type::function> { };
8356 template <
typename T>
8357 struct lua_type_of<T, std::enable_if_t<std::is_enum_v<T>>> : std::integral_constant<type, type::number> { };
8360 struct lua_type_of<meta_function> : std::integral_constant<type, type::string> { };
8362 #if SOL_IS_ON(SOL_STD_VARIANT) 8363 template <
typename... Tn>
8364 struct lua_type_of<std::variant<Tn...>> : std::integral_constant<type, type::poly> { };
8365 #endif // std::variant deployment sucks on Clang 8367 template <
typename T>
8368 struct lua_type_of<
nested<T>> : meta::conditional_t<::sol::is_container_v<T>, std::integral_constant<type, type::table>, lua_type_of<T>> { };
8370 template <
typename C, C v,
template <
typename...>
class V,
typename... Args>
8373 template <
typename C, C v,
template <
typename...>
class V,
typename T,
typename... Args>
8376 template <
typename C, C v,
template <
typename...>
class V,
typename List>
8379 template <
typename C, C v,
template <
typename...>
class V,
typename... Args>
8383 template <
typename T>
8385 typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_;
8388 template <
typename T>
8391 template <
typename T>
8393 typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_;
8396 template <
typename A,
typename B>
8397 struct lua_size<
std::pair<A, B>> : std::integral_constant<int, lua_size<A>::value + lua_size<B>::value> { };
8399 template <
typename... Args>
8400 struct lua_size<std::tuple<Args...>> : std::integral_constant<int, detail::accumulate<int, 0, lua_size, Args...>::value> { };
8402 template <
typename T>
8409 template <
typename T>
8414 template <
typename T>
8415 inline constexpr
bool is_msvc_callable_rigged_v = is_msvc_callable_rigged<T>::value;
8418 template <
typename T>
8420 : std::integral_constant<bool,
8423 T> || ((type::userdata == lua_type_of_v<T>)&&meta::meta_detail::has_internal_marker_v<lua_type_of<T>> && !meta::meta_detail::has_internal_marker_v<lua_size<T>>)
8424 || is_lua_reference_or_proxy_v<T> || meta::is_specialization_of_v<T, std::tuple> || meta::is_specialization_of_v<T, std::pair>> { };
8426 template <
typename T>
8429 template <
typename T>
8431 #if SOL_IS_ON(SOL_FUNCTION_CALL_VALUE_SEMANTICS)
8439 template <
typename T>
8442 template <
typename T>
8445 template <
typename T>
8448 template <
typename T>
8463 template <
typename T>
8466 template <
typename T>
8472 template <
typename T>
8474 template <
typename T>
8476 template <
typename T>
8478 template <
typename T>
8480 template <
typename T>
8482 template <
typename T>
8484 template <
typename T>
8494 template <
typename T>
8497 template <
typename T>
8508 template <
typename Signature>
8514 typedef std::integral_constant<bool, meta::count_for<is_variadic_arguments, typename base_t::args_list>::value != 0> runtime_variadics_t;
8515 static const std::size_t true_arity = base_t::arity;
8518 static const std::size_t true_free_arity = base_t::free_arity;
8520 - meta::count_for<is_transparent_argument, typename base_t::args_list>::value;
8523 template <
typename T>
8525 template <
bool x,
typename T>
8527 template <
typename T>
8530 template <
typename T>
8533 template <
typename T>
8535 template <
typename T>
8538 template <
typename T>
8541 template <
typename T>
8543 template <
bool x,
typename T>
8545 template <
typename T>
8548 template <
typename T>
8551 template <
typename T>
8553 template <
typename T,
bool aligned>
8555 template <
typename T,
bool aligned,
typename Handler>
8558 template <
typename T>
8561 template <
typename T>
8564 template <
typename T>
8567 template <
typename T>
8570 template <
typename T>
8571 using is_environment = std::integral_constant<bool, is_userdata_v<T> || is_table_v<T> || meta::is_specialization_of_v<T, basic_environment>>;
8573 template <
typename T>
8574 inline constexpr
bool is_environment_v = is_environment<T>::value;
8576 template <
typename T>
8577 using is_table_like = std::integral_constant<bool, is_table_v<T> || is_environment_v<T> || is_userdata_v<T>>;
8579 template <
typename T>
8580 inline constexpr
bool is_table_like_v = is_table_like<T>::value;
8582 template <
typename T>
8584 : std::integral_constant<bool,
8585 (SOL_IS_ON(SOL_DEFAULT_AUTOMAGICAL_USERTYPES))
8586 || (std::is_array_v<
8587 meta::unqualified_t<T>> || (!std::is_same_v<meta::unqualified_t<T>, state> && !std::is_same_v<meta::unqualified_t<T>, state_view>))> {
8590 template <
typename T>
8591 inline type type_of() {
8596 template <
typename T>
8599 template <
typename... Args>
8602 template <
typename... Args>
8608 template <
typename T>
8611 template <
typename T>
8614 template <
typename... Args>
8617 template <
typename T>
8620 template <
typename F,
typename... Policies>
8623 template <
typename T>
8626 template <
typename... Args>
8629 template <
typename... Args>
8630 inline constexpr
bool any_is_constructor_v = any_is_constructor<Args...>::value;
8632 template <
typename T>
8635 template <
typename Fx>
8638 template <
typename... Args>
8641 template <
typename... Args>
8642 inline constexpr
bool any_is_destructor_v = any_is_destructor<Args...>::value;
8645 template <
typename T>
8648 template <
typename T>
8651 enum class automagic_flags : unsigned {
8653 default_constructor = 0x001,
8654 destructor = 0x002u,
8655 pairs_operator = 0x004u,
8656 to_string_operator = 0x008u,
8657 call_operator = 0x010u,
8658 less_than_operator = 0x020u,
8659 less_than_or_equal_to_operator = 0x040u,
8660 length_operator = 0x080u,
8661 equal_to_operator = 0x100u,
8662 all = default_constructor | destructor | pairs_operator | to_string_operator | call_operator | less_than_operator | less_than_or_equal_to_operator
8663 | length_operator | equal_to_operator
8666 inline constexpr automagic_flags operator|(automagic_flags left, automagic_flags right) noexcept {
8667 return static_cast<automagic_flags
>(
8668 static_cast<std::underlying_type_t<automagic_flags>
>(left) |
static_cast<std::underlying_type_t<automagic_flags>
>(right));
8671 inline constexpr automagic_flags operator&(automagic_flags left, automagic_flags right) noexcept {
8672 return static_cast<automagic_flags
>(
8673 static_cast<std::underlying_type_t<automagic_flags>
>(left) &
static_cast<std::underlying_type_t<automagic_flags>
>(right));
8676 inline constexpr automagic_flags& operator|=(automagic_flags& left, automagic_flags right) noexcept {
8677 left = left | right;
8681 inline constexpr automagic_flags& operator&=(automagic_flags& left, automagic_flags right) noexcept {
8682 left = left & right;
8686 template <
typename Left,
typename Right>
8687 constexpr
bool has_flag(Left left, Right right) noexcept {
8688 return (left & right) == right;
8691 template <
typename Left,
typename Right>
8692 constexpr
bool has_any_flag(Left left, Right right) noexcept {
8693 return (left & right) !=
static_cast<Left
>(
static_cast<std::underlying_type_t<Left>
>(0));
8696 template <
typename Left,
typename Right>
8697 constexpr
auto clear_flags(Left left, Right right) noexcept {
8698 return static_cast<Left
>(
static_cast<std::underlying_type_t<Left>
>(left) & ~
static_cast<std::underlying_type_t<Right>
>(right));
8702 bool default_constructor =
true;
8703 bool destructor =
true;
8704 bool pairs_operator =
true;
8705 bool to_string_operator =
true;
8706 bool call_operator =
true;
8707 bool less_than_operator =
true;
8708 bool less_than_or_equal_to_operator =
true;
8709 bool length_operator =
true;
8710 bool equal_to_operator =
true;
8713 template <automagic_flags compile_time_defaults = automagic_flags::all>
8720 #include <exception> 8723 #if SOL_IS_ON(SOL_PRINT_ERRORS) 8734 inline const char (&default_exception_handler_name())[11] {
8735 static const char name[11] =
"sol.\xE2\x98\xA2\xE2\x98\xA2";
8740 inline int default_exception_handler(
lua_State* L, optional<const std::exception&>, string_view what) {
8741 #if SOL_IS_ON(SOL_PRINT_ERRORS) 8742 std::cerr <<
"[sol2] An exception occurred: ";
8743 std::cerr.write(what.data(),
static_cast<std::streamsize
>(what.size()));
8744 std::cerr << std::endl;
8746 lua_pushlstring(L, what.data(), what.size());
8750 inline int call_exception_handler(
lua_State* L, optional<const std::exception&> maybe_ex, string_view what) {
8751 lua_getglobal(L, default_exception_handler_name());
8752 type t =
static_cast<type
>(lua_type(L, -1));
8753 if (t != type::lightuserdata) {
8755 return default_exception_handler(L, std::move(maybe_ex), std::move(what));
8757 void* vfunc = lua_touserdata(L, -1);
8759 if (vfunc ==
nullptr) {
8760 return default_exception_handler(L, std::move(maybe_ex), std::move(what));
8762 exception_handler_function exfunc =
reinterpret_cast<exception_handler_function
>(vfunc);
8763 return exfunc(L, std::move(maybe_ex), std::move(what));
8766 #if SOL_IS_OFF(SOL_EXCEPTIONS) 8767 template <lua_CFunction f>
8768 int static_trampoline(
lua_State* L) noexcept {
8772 #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) 8773 template <lua_CFunction_noexcept f>
8774 int static_trampoline_noexcept(
lua_State* L) noexcept {
8778 template <lua_CFunction f>
8779 int static_trampoline_noexcept(
lua_State* L) noexcept {
8784 template <
typename Fx,
typename... Args>
8785 int trampoline(
lua_State* L, Fx&& f, Args&&... args) noexcept {
8786 return f(L, std::forward<Args>(args)...);
8789 inline int c_trampoline(
lua_State* L, lua_CFunction f) noexcept {
8790 return trampoline(L, f);
8794 inline int lua_cfunction_trampoline(
lua_State* L, lua_CFunction f) {
8795 #if SOL_IS_ON(SOL_PROPAGATE_EXCEPTIONS) 8801 catch (
const char* cs) {
8802 call_exception_handler(L, optional<const std::exception&>(nullopt), string_view(cs));
8804 catch (
const std::string& s) {
8805 call_exception_handler(L, optional<const std::exception&>(nullopt), string_view(s.c_str(), s.size()));
8807 catch (
const std::exception& e) {
8808 call_exception_handler(L, optional<const std::exception&>(e), e.what());
8810 #if SOL_IS_ON(SOL_EXCEPTIONS_CATCH_ALL) 8815 call_exception_handler(L, optional<const std::exception&>(nullopt),
"caught (...) exception");
8817 #endif // LuaJIT cannot have the catchall, but we must catch std::exceps for it 8818 return lua_error(L);
8819 #endif // Safe exceptions 8822 template <lua_CFunction f>
8824 return lua_cfunction_trampoline(L, f);
8827 #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) 8828 template <lua_CFunction_noexcept f>
8829 int static_trampoline_noexcept(
lua_State* L) noexcept {
8833 template <lua_CFunction f>
8834 int static_trampoline_noexcept(
lua_State* L) noexcept {
8839 template <
typename Fx,
typename... Args>
8840 int trampoline(
lua_State* L, Fx&& f, Args&&... args) {
8842 return f(L, std::forward<Args>(args)...);
8845 #if SOL_IS_ON(SOL_PROPAGATE_EXCEPTIONS) 8846 return f(L, std::forward<Args>(args)...);
8849 return f(L, std::forward<Args>(args)...);
8851 catch (
const char* cs) {
8852 call_exception_handler(L, optional<const std::exception&>(nullopt), string_view(cs));
8854 catch (
const std::string& s) {
8855 call_exception_handler(L, optional<const std::exception&>(nullopt), string_view(s.c_str(), s.size()));
8857 catch (
const std::exception& e) {
8858 call_exception_handler(L, optional<const std::exception&>(e), e.what());
8860 #if SOL_IS_ON(SOL_EXCEPTIONS_CATCH_ALL) 8865 call_exception_handler(L, optional<const std::exception&>(nullopt),
"caught (...) exception");
8868 return lua_error(L);
8873 inline int c_trampoline(
lua_State* L, lua_CFunction f) {
8874 return trampoline(L, f);
8876 #endif // Exceptions vs. No Exceptions 8878 template <
typename F, F fx>
8879 inline int typed_static_trampoline(
lua_State* L) {
8887 return static_trampoline_noexcept<fx>(L);
8891 {
return static_trampoline<fx>(L); }
8895 inline void set_default_exception_handler(
lua_State* L, exception_handler_function exf = &detail::default_exception_handler) {
8896 static_assert(
sizeof(
void*) >=
sizeof(exception_handler_function),
8897 "void* storage is too small to transport the exception handler: please file a bug on the sol2 issue tracker to get this looked at!");
8899 std::memcpy(&storage, &exf,
sizeof(exception_handler_function));
8900 lua_pushlightuserdata(L, storage);
8901 lua_setglobal(L, detail::default_exception_handler_name());
8918 #if SOL_IS_ON(SOL_MINGW_CCTYPE_IS_POISONED) 8922 #endif // MinGW is on some stuff 8925 namespace sol {
namespace detail {
8926 inline constexpr std::array<string_view, 9> removals { {
"{anonymous}",
8927 "(anonymous namespace)",
8933 "`anonymous-namespace'",
8934 "`anonymous namespace'" } };
8936 #if SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) 8937 inline std::string ctti_get_type_name_from_sig(std::string name) {
8939 using namespace std;
8940 std::size_t start = name.find_first_of(
'[');
8941 start = name.find_first_of(
'=', start);
8942 std::size_t end = name.find_last_of(
']');
8943 if (end == std::string::npos)
8945 if (start == std::string::npos)
8947 if (start < name.size() - 1)
8949 name = name.substr(start, end - start);
8950 start = name.rfind(
"seperator_mark");
8951 if (start != std::string::npos) {
8952 name.erase(start - 2, name.length());
8954 while (!name.empty() && isblank(name.front()))
8955 name.erase(name.begin());
8956 while (!name.empty() && isblank(name.back()))
8959 for (std::size_t r = 0; r < removals.size(); ++r) {
8960 auto found = name.find(removals[r]);
8961 while (found != std::string::npos) {
8962 name.erase(found, removals[r].size());
8963 found = name.find(removals[r]);
8970 template <
typename T,
class seperator_mark =
int>
8971 inline std::string ctti_get_type_name() {
8972 return ctti_get_type_name_from_sig(__PRETTY_FUNCTION__);
8974 #elif SOL_IS_ON(SOL_COMPILER_VCXX) 8975 inline std::string ctti_get_type_name_from_sig(std::string name) {
8976 std::size_t start = name.find(
"get_type_name");
8977 if (start == std::string::npos)
8981 if (start < name.size() - 1)
8983 std::size_t end = name.find_last_of(
'>');
8984 if (end == std::string::npos)
8986 name = name.substr(start, end - start);
8987 if (name.find(
"struct", 0) == 0)
8988 name.replace(0, 6,
"", 0);
8989 if (name.find(
"class", 0) == 0)
8990 name.replace(0, 5,
"", 0);
8991 while (!name.empty() && isblank(name.front()))
8992 name.erase(name.begin());
8993 while (!name.empty() && isblank(name.back()))
8996 for (std::size_t r = 0; r < removals.size(); ++r) {
8997 auto found = name.find(removals[r]);
8998 while (found != std::string::npos) {
8999 name.erase(found, removals[r].size());
9000 found = name.find(removals[r]);
9007 template <
typename T>
9008 std::string ctti_get_type_name() {
9009 return ctti_get_type_name_from_sig(__FUNCSIG__);
9012 #error Compiler not supported for demangling 9015 template <
typename T>
9016 std::string demangle_once() {
9017 std::string realname = ctti_get_type_name<T>();
9021 inline std::string short_demangle_from_type_name(std::string realname) {
9023 static const std::array<std::string, 10> ops = {
9024 {
"operator<",
"operator<<",
"operator<<=",
"operator<=",
"operator>",
"operator>>",
"operator>>=",
"operator>=",
"operator->",
"operator->*" }
9027 std::size_t idx = 0;
9028 for (idx = static_cast<std::size_t>(realname.empty() ? 0 : realname.size() - 1); idx > 0; --idx) {
9029 if (level == 0 && realname[idx] ==
':') {
9032 bool isleft = realname[idx] ==
'<';
9033 bool isright = realname[idx] ==
'>';
9034 if (!isleft && !isright)
9036 bool earlybreak =
false;
9037 for (
const auto& op : ops) {
9038 std::size_t nisop = realname.rfind(op, idx);
9039 if (nisop == std::string::npos)
9041 std::size_t nisopidx = idx - op.size() + 1;
9042 if (nisop == nisopidx) {
9043 idx =
static_cast<std::size_t
>(nisopidx);
9051 level += isleft ? -1 : 1;
9054 realname.erase(0, realname.length() <
static_cast<std::size_t
>(idx) ? realname.length() : idx + 1);
9059 template <
typename T>
9060 std::string short_demangle_once() {
9061 std::string realname = ctti_get_type_name<T>();
9062 return short_demangle_from_type_name(realname);
9065 template <
typename T>
9066 const std::string& demangle() {
9067 static const std::string d = demangle_once<T>();
9071 template <
typename T>
9072 const std::string& short_demangle() {
9073 static const std::string d = short_demangle_once<T>();
9082 template <
typename T>
9084 static const std::string& name() {
9085 static const std::string& n = detail::short_demangle<T>();
9088 static const std::string& qualified_name() {
9089 static const std::string& q_n = detail::demangle<T>();
9093 static const std::string m = std::string(
"sol.").append(detail::demangle<T>());
9096 static const std::string& user_metatable() {
9097 static const std::string u_m = std::string(
"sol.").append(detail::demangle<T>()).append(
".user");
9100 static const std::string& user_gc_metatable() {
9101 static const std::string u_g_m = std::string(
"sol.").append(detail::demangle<T>()).append(
".user\xE2\x99\xBB");
9104 static const std::string& gc_table() {
9105 static const std::string g_t = std::string(
"sol.").append(detail::demangle<T>()).append(
".\xE2\x99\xBB");
9121 template <
typename T>
9123 using SOL_INTERNAL_UNSPECIALIZED_MARKER_ = int;
9126 template <
typename T>
9129 using pointer =
typename std::pointer_traits<std::shared_ptr<T>>::element_type*;
9135 template <
typename X>
9136 using rebind_actual_type = std::shared_ptr<X>;
9138 static bool is_null(
lua_State*,
const std::shared_ptr<T>& p) noexcept {
9139 return p ==
nullptr;
9142 static pointer
get(
lua_State*,
const std::shared_ptr<T>& p) noexcept {
9147 template <
typename T,
typename D>
9150 using pointer =
typename std::unique_ptr<T, D>::pointer;
9153 static bool is_null(
lua_State*,
const std::unique_ptr<T, D>& p) noexcept {
9154 return p ==
nullptr;
9157 static pointer
get(
lua_State*,
const std::unique_ptr<T, D>& p) noexcept {
9163 namespace meta {
namespace meta_detail {
9164 template <
typename T,
typename =
void>
9167 template <
typename T>
9169 using type =
typename T::actual_type;
9172 template <
typename T,
typename... Rest,
template <
typename...>
class Templ>
9179 template <
typename T>
9182 namespace meta {
namespace meta_detail {
9183 template <
typename T>
9184 using value_test_t = decltype(T::value);
9186 template <
typename T>
9187 using type_test_t =
typename T::type;
9189 template <
typename T>
9190 using type_element_type_t =
typename T::element_type;
9192 template <
typename T,
typename =
void>
9194 using type =
typename std::pointer_traits<typename unique_actual_type<T>::type>::element_type;
9197 template <
typename T>
9199 using type =
typename T::element_type;
9202 template <
typename T>
9204 using type =
typename T::type;
9207 template <
typename T,
typename =
void>
9208 struct unique_valid : std::integral_constant<bool, !has_internal_marker_v<T>> { };
9210 template <
typename T>
9211 struct unique_valid<T, meta::void_t<decltype(T::value)>> : std::integral_constant<bool, T::value> { };
9214 template <
typename T>
9217 template <
typename T,
typename Element =
void>
9220 template <
typename T>
9223 template <
typename T>
9224 struct is_unique_usertype : std::integral_constant<bool, meta::meta_detail::unique_valid<unique_usertype_traits<T>>::value> { };
9226 template <
typename T>
9229 namespace meta {
namespace meta_detail {
9230 template <
typename T>
9231 using adl_sol_lua_check_access_test_t
9232 = decltype(sol_lua_check_access(
types<T>(), static_cast<lua_State*>(
nullptr), -1, std::declval<stack::record&>()));
9234 template <
typename T>
9235 inline constexpr
bool is_adl_sol_lua_check_access_v = meta::is_detected_v<adl_sol_lua_check_access_test_t, T>;
9237 template <
typename T>
9238 using unique_usertype_get_with_state_test_t
9241 template <
typename T>
9242 inline constexpr
bool unique_usertype_get_with_state_v = meta::is_detected_v<unique_usertype_get_with_state_test_t, T>;
9244 template <
typename T>
9245 using unique_usertype_is_null_with_state_test_t
9248 template <
typename T>
9249 inline constexpr
bool unique_usertype_is_null_with_state_v = meta::is_detected_v<unique_usertype_is_null_with_state_test_t, T>;
9253 template <
typename T>
9254 constexpr
bool unique_is_null_noexcept() noexcept {
9255 if constexpr (meta::meta_detail::unique_usertype_is_null_with_state_v<std::remove_cv_t<T>>) {
9264 template <
typename T>
9265 bool unique_is_null(
lua_State* L_, T& value_) noexcept(unique_is_null_noexcept<std::remove_cv_t<T>>()) {
9266 using Tu = std::remove_cv_t<T>;
9267 if constexpr (meta::meta_detail::unique_usertype_is_null_with_state_v<Tu>) {
9275 template <
typename T>
9276 constexpr
bool unique_get_noexcept() noexcept {
9277 if constexpr (meta::meta_detail::unique_usertype_get_with_state_v<std::remove_cv_t<T>>) {
9286 template <
typename T>
9287 auto unique_get(
lua_State* L_, T& value_) noexcept(unique_get_noexcept<std::remove_cv_t<T>>()) {
9288 using Tu = std::remove_cv_t<T>;
9289 if constexpr (meta::meta_detail::unique_usertype_get_with_state_v<Tu>) {
9298 namespace meta {
namespace meta_detail {
9299 template <
typename T,
typename Element =
void>
9300 using is_rebind_actual_type_test_t =
typename T::template rebind_actual_type<Element>;
9302 template <
typename T,
typename Element =
void>
9303 using is_rebind_actual_type = meta::is_detected<is_rebind_actual_type_test_t, T, Element>;
9305 template <
typename T,
typename Element =
void>
9306 inline constexpr
bool is_rebind_actual_type_v = is_rebind_actual_type<T, Element>::value;
9308 template <
typename T,
typename Element,
bool = is_rebind_actual_type_v<T, Element>>
9311 template <
typename T,
typename Element>
9313 : std::integral_constant<bool, !std::is_void_v<typename T::template rebind_actual_type<Element>>> { };
9316 template <
typename T,
typename Element =
void>
9319 template <
typename T,
typename Element =
void>
9320 inline constexpr
bool is_actual_type_rebindable_for_v = is_actual_type_rebindable_for<T, Element>::value;
9327 template <
typename... Args>
9329 template <
typename... Args>
9333 const auto base_classes = base_classes_tag();
9335 template <
typename... Args>
9340 inline decltype(
auto) base_class_check_key() {
9341 static const auto& key =
"class_check";
9345 inline decltype(
auto) base_class_cast_key() {
9346 static const auto& key =
"class_cast";
9350 inline decltype(
auto) base_class_index_propogation_key() {
9351 static const auto& key = u8
"\xF0\x9F\x8C\xB2.index";
9355 inline decltype(
auto) base_class_new_index_propogation_key() {
9356 static const auto& key = u8
"\xF0\x9F\x8C\xB2.new_index";
9360 template <
typename T>
9364 static bool type_check_bases(
types<>,
const string_view&) {
9368 template <
typename Base,
typename... Args>
9373 static bool type_check(
const string_view& ti) {
9377 template <
typename... Bases>
9378 static bool type_check_with(
const string_view& ti) {
9382 static void* type_cast_bases(
types<>, T*,
const string_view&) {
9386 template <
typename Base,
typename... Args>
9390 :
static_cast<void*
>(
static_cast<Base*
>(data));
9393 static void* type_cast(
void* voiddata,
const string_view& ti) {
9394 T* data =
static_cast<T*
>(voiddata);
9398 template <
typename... Bases>
9399 static void* type_cast_with(
void* voiddata,
const string_view& ti) {
9400 T* data =
static_cast<T*
>(voiddata);
9404 template <
typename U>
9405 static bool type_unique_cast_bases(
types<>,
void*,
void*,
const string_view&) {
9409 template <
typename U,
typename Base,
typename... Args>
9410 static int type_unique_cast_bases(
types<Base, Args...>,
void* source_data,
void* target_data,
const string_view& ti) {
9412 using base_ptr =
typename uu_traits::template rebind_actual_type<Base>;
9414 if (base_ti == ti) {
9415 if (target_data !=
nullptr) {
9416 U* source =
static_cast<U*
>(source_data);
9417 base_ptr* target =
static_cast<base_ptr*
>(target_data);
9423 return type_unique_cast_bases<U>(
types<Args...>(), source_data, target_data, ti);
9426 template <
typename U>
9427 static int type_unique_cast(
void* source_data,
void* target_data,
const string_view& ti,
const string_view& rebind_ti) {
9428 if constexpr (is_actual_type_rebindable_for_v<U>) {
9429 using rebound_actual_type = unique_usertype_rebind_actual_t<U>;
9430 using maybe_bases_or_empty = meta::conditional_t<std::is_void_v<rebound_actual_type>,
types<>, bases_t>;
9432 if (rebind_ti != this_rebind_ti) {
9437 if (ti == this_ti) {
9441 return type_unique_cast_bases<U>(maybe_bases_or_empty(), source_data, target_data, ti);
9446 if (ti == this_ti) {
9450 return type_unique_cast_bases<U>(
types<>(), source_data, target_data, ti);
9454 template <
typename U,
typename... Bases>
9455 static int type_unique_cast_with(
void* source_data,
void* target_data,
const string_view& ti,
const string_view& rebind_ti) {
9456 using uc_bases_t =
types<Bases...>;
9457 if constexpr (is_actual_type_rebindable_for_v<U>) {
9458 using rebound_actual_type = unique_usertype_rebind_actual_t<U>;
9459 using cond_bases_t = meta::conditional_t<std::is_void_v<rebound_actual_type>,
types<>, uc_bases_t>;
9461 if (rebind_ti != this_rebind_ti) {
9466 if (ti == this_ti) {
9470 return type_unique_cast_bases<U>(cond_bases_t(), source_data, target_data, ti);
9475 if (ti == this_ti) {
9479 return type_unique_cast_bases<U>(
types<>(), source_data, target_data, ti);
9499 constexpr
const char* not_a_number =
"not a numeric type";
9500 constexpr
const char* not_a_number_or_number_string =
"not a numeric type or numeric string";
9501 constexpr
const char* not_a_number_integral =
"not a numeric type that fits exactly an integer (number maybe has significant decimals)";
9502 constexpr
const char* not_a_number_or_number_string_integral
9503 =
"not a numeric type or a numeric string that fits exactly an integer (e.g. number maybe has significant decimals)";
9505 constexpr
const char* not_enough_stack_space =
"not enough space left on Lua stack";
9506 constexpr
const char* not_enough_stack_space_floating =
"not enough space left on Lua stack for a floating point number";
9507 constexpr
const char* not_enough_stack_space_integral =
"not enough space left on Lua stack for an integral number";
9508 constexpr
const char* not_enough_stack_space_string =
"not enough space left on Lua stack for a string";
9509 constexpr
const char* not_enough_stack_space_meta_function_name =
"not enough space left on Lua stack for the name of a meta_function";
9510 constexpr
const char* not_enough_stack_space_userdata =
"not enough space left on Lua stack to create a sol2 userdata";
9511 constexpr
const char* not_enough_stack_space_generic =
"not enough space left on Lua stack to push valuees";
9512 constexpr
const char* not_enough_stack_space_environment =
"not enough space left on Lua stack to retrieve environment";
9513 constexpr
const char* protected_function_error =
"caught (...) unknown error during protected_function call";
9515 inline void accumulate_and_mark(
const std::string& n, std::string& aux_message,
int& marker) {
9517 aux_message +=
", ";
9524 inline std::string associated_type_name(
lua_State* L,
int index, type t) {
9528 case type::userdata: {
9529 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 9530 luaL_checkstack(L, 2,
"not enough space to push get the type name");
9531 #endif // make sure stack doesn't overflow 9532 if (lua_getmetatable(L, index) == 0) {
9535 lua_pushlstring(L,
"__name", 6);
9538 const char* name = lua_tolstring(L, -1, &sz);
9539 std::string tn(name, static_cast<std::string::size_type>(sz));
9546 return lua_typename(L, static_cast<int>(t));
9549 inline int push_type_panic_string(
lua_State* L,
int index, type expected, type actual, string_view message, string_view aux_message) noexcept {
9550 const char* err = message.size() == 0
9551 ? (aux_message.size() == 0 ?
"stack index %d, expected %s, received %s" :
"stack index %d, expected %s, received %s: %s")
9552 :
"stack index %d, expected %s, received %s: %s %s";
9553 const char* type_name = expected == type::poly ?
"anything" : lua_typename(L, static_cast<int>(expected));
9555 std::string actual_name = associated_type_name(L, index, actual);
9556 lua_pushfstring(L, err, index, type_name, actual_name.c_str(), message.data(), aux_message.data());
9561 inline int type_panic_string(
lua_State* L,
int index, type expected, type actual, string_view message =
"") noexcept(
false) {
9562 push_type_panic_string(L, index, expected, actual, message,
"");
9563 return lua_error(L);
9566 inline int type_panic_c_str(
lua_State* L,
int index, type expected, type actual,
const char* message =
nullptr) noexcept(
false) {
9567 push_type_panic_string(L, index, expected, actual, message ==
nullptr ?
"" : message,
"");
9568 return lua_error(L);
9572 int operator()(
lua_State* L,
int index, type expected, type actual)
const noexcept(
false) {
9573 return type_panic_c_str(L, index, expected, actual,
nullptr);
9575 int operator()(
lua_State* L,
int index, type expected, type actual, string_view message)
const noexcept(
false) {
9576 return type_panic_c_str(L, index, expected, actual, message.data());
9583 int operator()(
lua_State* L,
int index, type expected, type actual, string_view message)
const noexcept(
false) {
9584 push_type_panic_string(L, index, expected, actual, message,
"(type check failed in constructor)");
9585 return lua_error(L);
9589 template <
typename F =
void>
9591 int operator()(
lua_State* L,
int index, type expected, type actual, string_view message)
const noexcept(
false) {
9592 push_type_panic_string(L, index, expected, actual, message,
"(bad argument to variable or function call)");
9593 return lua_error(L);
9597 template <
typename R,
typename... Args>
9599 int operator()(
lua_State* L,
int index, type expected, type actual, string_view message)
const noexcept(
false) {
9601 std::string aux_message =
"(bad argument into '";
9602 aux_message += detail::demangle<R>();
9605 (void)detail::swallow { int(), (detail::accumulate_and_mark(detail::demangle<Args>(), aux_message, marker), int())... };
9606 aux_message +=
")')";
9607 push_type_panic_string(L, index, expected, actual, message, aux_message);
9609 return lua_error(L);
9614 inline int no_panic(
lua_State*,
int, type, type,
const char* =
nullptr) noexcept {
9618 inline void type_error(
lua_State* L,
int expected,
int actual) noexcept(
false) {
9619 luaL_error(L,
"expected %s, received %s", lua_typename(L, expected), lua_typename(L, actual));
9622 inline void type_error(
lua_State* L, type expected, type actual) noexcept(
false) {
9623 type_error(L, static_cast<int>(expected), static_cast<int>(actual));
9626 inline void type_assert(
lua_State* L,
int index, type expected, type actual) noexcept(
false) {
9627 if (expected != type::poly && expected != actual) {
9628 type_panic_c_str(L, index, expected, actual,
nullptr);
9632 inline void type_assert(
lua_State* L,
int index, type expected) {
9633 type actual = type_of(L, index);
9634 type_assert(L, index, expected, actual);
9648 if (rightL ==
nullptr || leftL ==
nullptr || leftL == rightL) {
9651 const void* leftregistry = lua_topointer(leftL, LUA_REGISTRYINDEX);
9652 const void* rightregistry = lua_topointer(rightL, LUA_REGISTRYINDEX);
9653 return leftregistry == rightregistry;
9663 int registry_index()
const noexcept {
9688 int push(
lua_State* L_)
const noexcept {
9689 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 9690 luaL_checkstack(L_, 1,
"not enough Lua stack space to push a single reference value");
9691 #endif // make sure stack doesn't overflow 9692 lua_pushvalue(L_, m_index);
9696 void pop(
lua_State* L_,
int pop_count = 1)
const noexcept {
9697 lua_pop(L_, pop_count);
9700 int stack_index()
const noexcept {
9704 const void* pointer(
lua_State* L_)
const noexcept {
9705 const void* pointer_id = lua_topointer(L_, stack_index());
9709 type get_type(
lua_State* L_)
const noexcept {
9710 int untyped_value = lua_type(L_, stack_index());
9711 return static_cast<type
>(untyped_value);
9714 bool valid(
lua_State* L)
const noexcept {
9715 type t = get_type(L);
9716 return t != type::lua_nil && t != type::none;
9723 void reset(
lua_State* L_,
int index_) noexcept {
9727 void abandon(
lua_State* =
nullptr) noexcept {
9736 m_index = right.m_index;
9740 return lua_compare(L_, this->stack_index(), r.stack_index(), LUA_OPEQ) == 1;
9770 int i = r.stack_index();
9771 if (detail::xmovable(lua_state(), r.lua_state())) {
9772 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 9773 luaL_checkstack(L, 1,
"not enough Lua stack space to push a single reference value");
9774 #endif // make sure stack doesn't overflow 9775 lua_pushvalue(r.lua_state(), r.stack_index());
9776 lua_xmove(r.lua_state(), luastate, 1);
9786 int push()
const noexcept {
9787 return push(lua_state());
9790 int push(
lua_State* L_)
const noexcept {
9791 return stateless_stack_reference::push(L_);
9794 void pop()
const noexcept {
9798 void pop(
lua_State* L_,
int pop_count_ = 1)
const noexcept {
9799 stateless_stack_reference::pop(L_, pop_count_);
9802 const void* pointer()
const noexcept {
9803 return stateless_stack_reference::pointer(lua_state());
9806 type get_type()
const noexcept {
9807 return stateless_stack_reference::get_type(lua_state());
9814 bool valid()
const noexcept {
9815 return stateless_stack_reference::valid(lua_state());
9819 stateless_stack_reference::abandon(lua_state());
9824 return lua_compare(l.lua_state(), l.stack_index(), r.stack_index(), LUA_OPEQ) == 1;
9828 return !operator==(l, r);
9832 return !lhs.valid();
9836 return !rhs.valid();
9848 return l.stack_index() == r.stack_index();
9852 return l.stack_index() != r.stack_index();
9856 using is_transparent = std::true_type;
9866 return lhs.equals(lua_state(), rhs);
9870 return rhs.equals(lua_state(), lhs);
9874 return lhs.equals(lua_state(), rhs);
9882 using is_transparent = std::true_type;
9899 using result_type = std::size_t;
9900 using is_transparent = std::true_type;
9909 result_type operator()(
const argument_type& lhs)
const noexcept {
9910 std::hash<const void*> h;
9911 return h(lhs.pointer(lua_state()));
9920 using result_type = std::size_t;
9921 using is_transparent = std::true_type;
9923 result_type operator()(
const argument_type& lhs)
const noexcept {
9924 std::hash<const void*> h;
9925 return h(lhs.pointer());
9932 #include <functional> 9936 inline const char (&default_main_thread_name())[9] {
9937 static const char name[9] =
"sol.\xF0\x9F\x93\x8C";
9943 inline void remove(
lua_State* L_,
int rawindex,
int count) {
9946 int top = lua_gettop(L_);
9950 if (rawindex == -count || top == rawindex) {
9952 lua_pop(L_, static_cast<int>(count));
9959 int index = lua_absindex(L_, rawindex);
9961 index = lua_gettop(L_) + (index + 1);
9963 int last = index + count;
9964 for (
int i = index; i < last; ++i) {
9965 lua_remove(L_, index);
9976 remove(L, index, count);
9980 template <
bool top_level>
9991 lua_pop(L, pop_count);
10001 template <
bool,
typename T,
typename =
void>
10003 using Tu = meta::unqualified_t<T>;
10007 push_popper(T object_) noexcept : m_object(object_), m_index(lua_absindex(m_object.lua_state(), -m_object.push())) {
10010 int index_of(
const Tu&)
const noexcept {
10019 template <
typename T,
typename C>
10021 using Tu = meta::unqualified_t<T>;
10026 int index_of(
const Tu&)
const noexcept {
10034 template <
typename T>
10035 struct push_popper<false, T,
std::enable_if_t<is_stack_based_v<meta::unqualified_t<T>>>> {
10036 using Tu = meta::unqualified_t<T>;
10041 int index_of(
const Tu& object_)
const noexcept {
10042 return object_.stack_index();
10049 template <
bool,
typename T,
typename =
void>
10051 using Tu = meta::unqualified_t<T>;
10059 int index_of(
const Tu&)
const noexcept {
10068 template <
typename T,
typename C>
10070 using Tu = meta::unqualified_t<T>;
10075 int index_of(
lua_State*,
const Tu&)
const noexcept {
10083 template <
typename T>
10085 using Tu = meta::unqualified_t<T>;
10091 int index_of(
const Tu& object_)
const noexcept {
10092 return object_.stack_index();
10099 template <
bool top_level = false,
typename T>
10104 template <
bool top_level = false,
typename T>
10109 template <
typename T>
10111 int push_count = object_.push();
10113 return push_popper_at(L, lua_absindex(L, -push_count), push_count);
10116 template <
bool top_level = false>
10123 #if SOL_LUA_VERSION_I_ < 502 10125 return backup_if_unsupported_;
10126 lua_getglobal(L_, detail::default_main_thread_name());
10127 auto pp = stack::pop_n(L_, 1);
10128 if (type_of(L_, -1) == type::thread) {
10129 return lua_tothread(L_, -1);
10131 return backup_if_unsupported_;
10134 return backup_if_unsupported_;
10135 lua_rawgeti(L_, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD);
10136 lua_State* Lmain = lua_tothread(L_, -1);
10139 #endif // Lua 5.2+ has the main thread unqualified_getter 10144 }
inline constexpr no_safety {};
10149 (void)backup_if_unsupported;
10151 return main_thread(L_, backup_if_unsupported);
10159 template <
bool o_main_only>
10162 int ref = LUA_NOREF;
10164 int copy_ref(
lua_State* L_)
const noexcept {
10165 if (ref == LUA_NOREF)
10168 return luaL_ref(L_, LUA_REGISTRYINDEX);
10175 ref = r.copy_ref(L_);
10189 int stack_index()
const noexcept {
10194 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 10195 luaL_checkstack(L_, 1,
"not enough Lua stack space to push this reference value");
10196 #endif // make sure stack doesn't overflow 10197 lua_pushglobaltable(L_);
10198 ref = luaL_ref(L_, LUA_REGISTRYINDEX);
10213 if (r.ref == LUA_REFNIL) {
10217 if (r.ref == LUA_NOREF || L_ ==
nullptr) {
10221 ref = r.copy_ref(L_);
10225 if (r.ref == LUA_REFNIL) {
10229 if (r.ref == LUA_NOREF || L_ ==
nullptr) {
10238 if (L_ ==
nullptr || r.lua_state() ==
nullptr || r.get_type() == type::none) {
10242 if (r.get_type() == type::lua_nil) {
10246 if (L_ != r.lua_state() && !detail::xmovable(L_, r.lua_state())) {
10250 ref = luaL_ref(L_, LUA_REGISTRYINDEX);
10257 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 10258 luaL_checkstack(L_, 1,
"not enough Lua stack space to push this reference value");
10259 #endif // make sure stack doesn't overflow 10260 lua_pushvalue(L_, index);
10261 ref = luaL_ref(L_, LUA_REGISTRYINDEX);
10266 lua_rawgeti(L_, LUA_REGISTRYINDEX, index_.index);
10267 ref = luaL_ref(L_, LUA_REGISTRYINDEX);
10287 int push(
lua_State* L_)
const noexcept {
10288 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 10289 luaL_checkstack(L_, 1,
"not enough Lua stack space to push this reference value");
10290 #endif // make sure stack doesn't overflow 10291 lua_rawgeti(L_, LUA_REGISTRYINDEX, ref);
10295 void pop(
lua_State* L_,
int n = 1)
const noexcept {
10299 int registry_index()
const noexcept {
10310 void reset(
lua_State* L_,
int index_) noexcept {
10312 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 10313 luaL_checkstack(L_, 1,
"not enough Lua stack space to push this reference value");
10314 #endif // make sure stack doesn't overflow 10315 lua_pushvalue(L_, index_);
10316 ref = luaL_ref(L_, LUA_REGISTRYINDEX);
10319 bool valid(
lua_State*)
const noexcept {
10320 return !(ref == LUA_NOREF || ref == LUA_REFNIL);
10323 const void* pointer(
lua_State* L_)
const noexcept {
10325 const void* vp = lua_topointer(L_, -si);
10330 type get_type(
lua_State* L_)
const noexcept {
10332 int result = lua_type(L_, -1);
10334 return static_cast<type
>(result);
10341 void deref(
lua_State* L_)
const noexcept {
10342 luaL_unref(L_, LUA_REGISTRYINDEX, ref);
10356 if (!right.valid(L_)) {
10359 ref = right.copy_ref(L_);
10363 auto ppl = stack::push_pop(L_, *
this);
10364 auto ppr = stack::push_pop(L_, r);
10365 return lua_compare(L_, -1, -2, LUA_OPEQ) == 1;
10369 auto ppl = stack::push_pop(L_, *
this);
10370 return lua_compare(L_, -1, r.stack_index(), LUA_OPEQ) == 1;
10378 template <
bool main_only = false>
10381 template <
bool o_main_only>
10385 template <
bool r_main_only>
10390 if (r.ref == LUA_REFNIL) {
10391 luastate = detail::pick_main_thread < main_only && !r_main_only > (r.lua_state(), r.lua_state());
10395 if (r.ref == LUA_NOREF) {
10396 luastate = r.luastate;
10400 if (detail::xmovable(lua_state(), r.lua_state())) {
10401 r.push(lua_state());
10402 ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
10405 luastate = detail::pick_main_thread < main_only && !r_main_only > (r.lua_state(), r.lua_state());
10406 ref = r.copy_ref();
10409 template <
bool r_main_only>
10414 if (r.ref == LUA_REFNIL) {
10415 luastate = detail::pick_main_thread < main_only && !r_main_only > (r.lua_state(), r.lua_state());
10419 if (r.ref == LUA_NOREF) {
10420 luastate = r.luastate;
10424 if (detail::xmovable(lua_state(), r.lua_state())) {
10425 r.push(lua_state());
10426 ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
10430 luastate = detail::pick_main_thread < main_only && !r_main_only > (r.lua_state(), r.lua_state());
10433 r.luastate =
nullptr;
10446 void deref()
const noexcept {
10447 return stateless_reference::deref(lua_state());
10450 int copy_ref()
const noexcept {
10451 return copy_ref(lua_state());
10454 int copy_ref(
lua_State* L_)
const noexcept {
10455 return stateless_reference::copy_ref(L_);
10466 template <
bool r_main_only>
10468 if (r.ref == LUA_REFNIL) {
10472 if (r.ref == LUA_NOREF || lua_state() ==
nullptr) {
10476 if (detail::xmovable(lua_state(), r.lua_state())) {
10477 r.push(lua_state());
10478 ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
10481 ref = r.copy_ref();
10484 template <
bool r_main_only>
10486 if (r.ref == LUA_REFNIL) {
10490 if (r.ref == LUA_NOREF || lua_state() ==
nullptr) {
10494 if (detail::xmovable(lua_state(), r.lua_state())) {
10495 r.push(lua_state());
10496 ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
10501 r.luastate =
nullptr;
10505 if (lua_state() ==
nullptr || r.lua_state() ==
nullptr || r.get_type() == type::none) {
10509 if (r.get_type() == type::lua_nil) {
10513 if (lua_state() != r.lua_state() && !detail::xmovable(lua_state(), r.lua_state())) {
10516 r.push(lua_state());
10517 ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
10521 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 10522 luaL_checkstack(L_, 1,
"not enough Lua stack space to push this reference value");
10523 #endif // make sure stack doesn't overflow 10524 lua_pushvalue(L_, index);
10525 ref = luaL_ref(L_, LUA_REGISTRYINDEX);
10528 lua_rawgeti(lua_state(), LUA_REGISTRYINDEX, index.index);
10529 ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
10535 if (lua_state() ==
nullptr || ref == LUA_NOREF)
10544 o.luastate =
nullptr;
10548 :
basic_reference(detail::pick_main_thread<main_only>(o.lua_state(), o.lua_state()), o) {
10552 :
stateless_reference(std::move(o)), luastate(detail::pick_main_thread<main_only>(o.lua_state(), o.lua_state())) {
10553 o.luastate =
nullptr;
10558 move_assign(std::move(r));
10563 copy_assign_complex(r);
10568 move_assign(std::move(r));
10573 copy_assign_complex(r);
10582 template <
typename Super>
10585 template <
typename Super>
10588 int push()
const noexcept {
10589 return push(lua_state());
10592 void reset() noexcept {
10593 stateless_reference::reset(luastate);
10594 luastate =
nullptr;
10597 int push(
lua_State* L_)
const noexcept {
10598 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 10599 luaL_checkstack(L_, 1,
"not enough Lua stack space to push this reference value");
10600 #endif // make sure stack doesn't overflow 10601 if (lua_state() ==
nullptr) {
10605 lua_rawgeti(lua_state(), LUA_REGISTRYINDEX, ref);
10606 if (L_ != lua_state()) {
10607 lua_xmove(lua_state(), L_, 1);
10612 void pop()
const noexcept {
10616 void pop(
lua_State* L_,
int n = 1)
const noexcept {
10617 stateless_reference::pop(L_, n);
10620 int registry_index()
const noexcept {
10621 return stateless_reference::registry_index();
10624 bool valid()
const noexcept {
10625 return stateless_reference::valid(lua_state());
10628 bool valid(
lua_State* L_)
const noexcept {
10629 return stateless_reference::valid(L_);
10632 const void* pointer()
const noexcept {
10633 return stateless_reference::pointer(lua_state());
10636 explicit operator bool()
const noexcept {
10640 type get_type()
const noexcept {
10641 return stateless_reference::get_type(lua_state());
10644 lua_State* lua_state()
const noexcept {
10649 template <
bool lb,
bool rb>
10651 auto ppl = stack::push_pop(l);
10652 auto ppr = stack::push_pop(r);
10653 return lua_compare(l.lua_state(), -1, -2, LUA_OPEQ) == 1;
10656 template <
bool lb,
bool rb>
10658 return !operator==(l, r);
10663 auto ppl = stack::push_pop(l);
10664 return lua_compare(l.lua_state(), -1, r.stack_index(), LUA_OPEQ) == 1;
10669 return !operator==(l, r);
10674 auto ppr = stack::push_pop(r);
10675 return lua_compare(l.lua_state(), -1, r.stack_index(), LUA_OPEQ) == 1;
10680 return !operator==(l, r);
10685 return !lhs.valid();
10690 return !rhs.valid();
10695 return lhs.valid();
10700 return rhs.valid();
10704 return l.registry_index() == r.registry_index();
10708 return l.registry_index() != r.registry_index();
10712 return lhs.registry_index() == LUA_REFNIL;
10716 return rhs.registry_index() == LUA_REFNIL;
10720 return lhs.registry_index() != LUA_REFNIL;
10724 return rhs.registry_index() != LUA_REFNIL;
10728 using is_transparent = std::true_type;
10734 return rhs.equals(lua_state(), lhs);
10738 return lhs.equals(lua_state(), rhs);
10742 return lhs.equals(lua_state(), rhs);
10747 using is_transparent = std::true_type;
10759 template <
bool lb,
bool rb>
10777 using result_type = std::size_t;
10778 using is_transparent = std::true_type;
10784 std::hash<const void*> h;
10785 return h(lhs.pointer(lua_state()));
10791 using result_type = std::size_t;
10792 using is_transparent = std::true_type;
10796 std::hash<const void*> h;
10797 return h(lhs.pointer());
10809 template <
typename T>
10813 template <
typename T>
10816 template <
typename T>
10817 struct is_tieable : std::integral_constant<bool, (::sol::tie_size<T>::value > 0)> { };
10819 template <
typename... Tn>
10820 struct tie_t :
public std::tuple<std::add_lvalue_reference_t<Tn>...> {
10822 typedef std::tuple<std::add_lvalue_reference_t<Tn>...> base_t;
10824 template <
typename T>
10825 void set(std::false_type, T&& target) {
10826 std::get<0>(*this) = std::forward<T>(target);
10829 template <
typename T>
10830 void set(std::true_type, T&& target) {
10833 typedef meta::conditional_t<(value_size::value < tie_size::value), value_size, tie_size> indices_size;
10834 typedef std::make_index_sequence<indices_size::value> indices;
10835 set_extra(
detail::is_speshul<meta::unqualified_t<T>>(), indices(), std::forward<T>(target));
10838 template <std::size_t... I,
typename T>
10839 void set_extra(std::true_type, std::index_sequence<I...>, T&& target) {
10841 (void)detail::swallow { 0, (get<I>(
static_cast<base_t&
>(*this)) = get<I>(
types<Tn...>(), target), 0)..., 0 };
10844 template <std::size_t... I,
typename T>
10845 void set_extra(std::false_type, std::index_sequence<I...>, T&& target) {
10847 (void)detail::swallow { 0, (get<I>(
static_cast<base_t&
>(*this)) = get<I>(target), 0)..., 0 };
10851 using base_t::base_t;
10853 template <
typename T>
10854 tie_t& operator=(T&& value) {
10856 set(tieable(), std::forward<T>(value));
10861 template <
typename... Tn>
10864 namespace adl_barrier_detail {
10865 template <
typename... Tn>
10871 using namespace adl_barrier_detail;
10879 #include <functional> 10883 inline void stack_fail(
int,
int) {
10884 #if SOL_IS_ON(SOL_EXCEPTIONS) 10885 throw error(detail::direct_error,
"imbalanced stack after operation finish");
10890 #endif // No Exceptions 10897 std::function<void(int, int)> on_mismatch;
10901 stack_guard(
lua_State* L,
int top, std::function<
void(
int,
int)> fx = detail::stack_fail) : L(L), top(top), on_mismatch(std::move(fx)) {
10903 bool check_stack(
int modification = 0)
const {
10904 int bottom = lua_gettop(L) + modification;
10905 if (top == bottom) {
10908 on_mismatch(top, bottom);
10921 #include <forward_list> 10924 #include <algorithm> 10926 #include <optional> 10927 #include <type_traits> 10933 template <
typename T>
10935 template <
typename T>
10937 template <
typename T>
10939 template <
typename T>
10942 template <
typename Tag>
10943 inline constexpr
bool is_tagged_v
10944 = meta::is_specialization_of_v<Tag,
10946 as_pointer_tag> || meta::is_specialization_of_v<Tag, as_value_tag> || meta::is_specialization_of_v<Tag, as_unique_tag> || meta::is_specialization_of_v<Tag, as_table_tag> || std::is_same_v<Tag, as_reference_tag> || std::is_same_v<Tag, with_function_tag>;
10948 using lua_reg_table =
luaL_Reg[64];
10950 using unique_destructor = void (*)(
void*);
10951 using unique_tag = detail::inheritance_unique_cast_function;
10953 inline void* alloc_newuserdata(
lua_State* L, std::size_t bytesize) {
10954 #if SOL_LUA_VERSION_I_ >= 504 10955 return lua_newuserdatauv(L, bytesize, 1);
10957 return lua_newuserdata(L, bytesize);
10961 constexpr std::uintptr_t align(std::size_t alignment, std::uintptr_t ptr, std::size_t& space) {
10966 std::uintptr_t offby =
static_cast<std::uintptr_t
>(ptr % alignment);
10967 std::uintptr_t padding = (alignment - offby) % alignment;
10973 inline void* align(std::size_t alignment,
void* ptr, std::size_t& space) {
10974 return reinterpret_cast<void*
>(align(alignment, reinterpret_cast<std::uintptr_t>(ptr), space));
10977 constexpr std::uintptr_t align_one(std::size_t alignment, std::size_t size, std::uintptr_t ptr) {
10978 std::size_t space = (std::numeric_limits<std::size_t>::max)();
10979 return align(alignment, ptr, space) + size;
10982 template <
typename... Args>
10983 constexpr std::size_t aligned_space_for(std::uintptr_t ptr) {
10984 std::uintptr_t end = ptr;
10985 ((end = align_one(
alignof(Args),
sizeof(Args), end)), ...);
10986 return static_cast<std::size_t
>(end - ptr);
10989 template <
typename... Args>
10990 constexpr std::size_t aligned_space_for() {
10991 static_assert(
sizeof...(Args) > 0);
10993 constexpr std::size_t max_arg_alignment = (std::max)({
alignof(Args)... });
10994 if constexpr (max_arg_alignment <=
alignof(std::max_align_t)) {
10996 std::size_t worst_required_size = 0;
10997 for (std::size_t ptr = 0; ptr < max_arg_alignment; ptr++) {
10998 worst_required_size = (std::max)(worst_required_size, aligned_space_for<Args...>(ptr));
11000 return worst_required_size;
11004 return (aligned_space_for<Args>(0x1) + ...);
11008 inline void* align_usertype_pointer(
void* ptr) {
11009 using use_align = std::integral_constant<bool,
11010 #if SOL_IS_OFF(SOL_ALIGN_MEMORY) 11013 (std::alignment_of<void*>::value > 1)
11016 if (!use_align::value) {
11019 std::size_t space = (std::numeric_limits<std::size_t>::max)();
11020 return align(std::alignment_of<void*>::value, ptr, space);
11023 template <
bool pre_aligned = false,
bool pre_shifted = false>
11024 void* align_usertype_unique_destructor(
void* ptr) {
11025 using use_align = std::integral_constant<bool,
11026 #if SOL_IS_OFF(SOL_ALIGN_MEMORY) 11029 (std::alignment_of<unique_destructor>::value > 1)
11032 if (!pre_aligned) {
11033 ptr = align_usertype_pointer(ptr);
11035 if (!pre_shifted) {
11036 ptr =
static_cast<void*
>(
static_cast<char*
>(ptr) +
sizeof(
void*));
11038 if (!use_align::value) {
11039 return static_cast<void*
>(
static_cast<void**
>(ptr) + 1);
11041 std::size_t space = (std::numeric_limits<std::size_t>::max)();
11042 return align(std::alignment_of<unique_destructor>::value, ptr, space);
11045 template <
bool pre_aligned = false,
bool pre_shifted = false>
11046 void* align_usertype_unique_tag(
void* ptr) {
11047 using use_align = std::integral_constant<bool,
11048 #if SOL_IS_OFF(SOL_ALIGN_MEMORY) 11051 (std::alignment_of<unique_tag>::value > 1)
11054 if (!pre_aligned) {
11055 ptr = align_usertype_unique_destructor(ptr);
11057 if (!pre_shifted) {
11058 ptr =
static_cast<void*
>(
static_cast<char*
>(ptr) +
sizeof(unique_destructor));
11060 if (!use_align::value) {
11063 std::size_t space = (std::numeric_limits<std::size_t>::max)();
11064 return align(std::alignment_of<unique_tag>::value, ptr, space);
11067 template <
typename T,
bool pre_aligned = false,
bool pre_shifted = false>
11068 void* align_usertype_unique(
void* ptr) {
11069 typedef std::integral_constant<bool,
11070 #if SOL_IS_OFF(SOL_ALIGN_MEMORY) 11073 (std::alignment_of_v<T> > 1)
11077 if (!pre_aligned) {
11078 ptr = align_usertype_unique_tag(ptr);
11080 if (!pre_shifted) {
11081 ptr =
static_cast<void*
>(
static_cast<char*
>(ptr) +
sizeof(unique_tag));
11083 if (!use_align::value) {
11086 std::size_t space = (std::numeric_limits<std::size_t>::max)();
11087 return align(std::alignment_of_v<T>, ptr, space);
11090 template <
typename T>
11091 void* align_user(
void* ptr) {
11092 typedef std::integral_constant<bool,
11093 #if SOL_IS_OFF(SOL_ALIGN_MEMORY) 11096 (std::alignment_of_v<T> > 1)
11100 if (!use_align::value) {
11103 std::size_t space = (std::numeric_limits<std::size_t>::max)();
11104 return align(std::alignment_of_v<T>, ptr, space);
11107 template <
typename T>
11108 T** usertype_allocate_pointer(
lua_State* L) {
11109 typedef std::integral_constant<bool,
11110 #if SOL_IS_OFF(SOL_ALIGN_MEMORY) 11113 (std::alignment_of<T*>::value > 1)
11117 if (!use_align::value) {
11118 T** pointerpointer =
static_cast<T**
>(alloc_newuserdata(L,
sizeof(T*)));
11119 return pointerpointer;
11121 constexpr std::size_t initial_size = aligned_space_for<T*>();
11123 std::size_t allocated_size = initial_size;
11124 void* unadjusted = alloc_newuserdata(L, initial_size);
11125 void* adjusted = align(std::alignment_of<T*>::value, unadjusted, allocated_size);
11126 if (adjusted ==
nullptr) {
11131 luaL_error(L,
"cannot properly align memory for '%s'", detail::demangle<T*>().data());
11133 return static_cast<T**
>(adjusted);
11136 inline bool attempt_alloc(
lua_State* L, std::size_t ptr_align, std::size_t ptr_size, std::size_t value_align,
11137 std::size_t allocated_size,
void*& pointer_adjusted,
void*& data_adjusted) {
11138 void* adjusted = alloc_newuserdata(L, allocated_size);
11139 pointer_adjusted = align(ptr_align, adjusted, allocated_size);
11140 if (pointer_adjusted ==
nullptr) {
11145 allocated_size -= ptr_size;
11146 adjusted =
static_cast<void*
>(
static_cast<char*
>(pointer_adjusted) + ptr_size);
11147 data_adjusted = align(value_align, adjusted, allocated_size);
11148 if (data_adjusted ==
nullptr) {
11155 inline bool attempt_alloc_unique(
lua_State* L, std::size_t ptr_align, std::size_t ptr_size, std::size_t real_align,
11156 std::size_t allocated_size,
void*& pointer_adjusted,
void*& dx_adjusted,
void*& id_adjusted,
void*& data_adjusted) {
11157 void* adjusted = alloc_newuserdata(L, allocated_size);
11158 pointer_adjusted = align(ptr_align, adjusted, allocated_size);
11159 if (pointer_adjusted ==
nullptr) {
11163 allocated_size -= ptr_size;
11165 adjusted =
static_cast<void*
>(
static_cast<char*
>(pointer_adjusted) + ptr_size);
11166 dx_adjusted = align(std::alignment_of_v<unique_destructor>, adjusted, allocated_size);
11167 if (dx_adjusted ==
nullptr) {
11171 allocated_size -=
sizeof(unique_destructor);
11173 adjusted =
static_cast<void*
>(
static_cast<char*
>(dx_adjusted) +
sizeof(unique_destructor));
11175 id_adjusted = align(std::alignment_of_v<unique_tag>, adjusted, allocated_size);
11176 if (id_adjusted ==
nullptr) {
11180 allocated_size -=
sizeof(unique_tag);
11182 adjusted =
static_cast<void*
>(
static_cast<char*
>(id_adjusted) +
sizeof(unique_tag));
11183 data_adjusted = align(real_align, adjusted, allocated_size);
11184 if (data_adjusted ==
nullptr) {
11191 template <
typename T>
11193 typedef std::integral_constant<bool,
11194 #if SOL_IS_OFF(SOL_ALIGN_MEMORY) 11197 (std::alignment_of<T*>::value > 1 || std::alignment_of_v<T> > 1)
11201 if (!use_align::value) {
11202 T** pointerpointer =
static_cast<T**
>(alloc_newuserdata(L,
sizeof(T*) +
sizeof(T)));
11203 T*& pointerreference = *pointerpointer;
11204 T* allocationtarget =
reinterpret_cast<T*
>(pointerpointer + 1);
11205 pointerreference = allocationtarget;
11206 return allocationtarget;
11209 constexpr std::size_t initial_size = aligned_space_for<T*, T>();
11211 void* pointer_adjusted;
11212 void* data_adjusted;
11214 = attempt_alloc(L, std::alignment_of_v<T*>,
sizeof(T*), std::alignment_of_v<T>, initial_size, pointer_adjusted, data_adjusted);
11216 if (pointer_adjusted ==
nullptr) {
11217 luaL_error(L,
"aligned allocation of userdata block (pointer section) for '%s' failed", detail::demangle<T>().c_str());
11220 luaL_error(L,
"aligned allocation of userdata block (data section) for '%s' failed", detail::demangle<T>().c_str());
11225 T** pointerpointer =
reinterpret_cast<T**
>(pointer_adjusted);
11226 T*& pointerreference = *pointerpointer;
11227 T* allocationtarget =
reinterpret_cast<T*
>(data_adjusted);
11228 pointerreference = allocationtarget;
11229 return allocationtarget;
11232 template <
typename T,
typename Real>
11233 Real* usertype_unique_allocate(
lua_State* L, T**& pref, unique_destructor*& dx, unique_tag*&
id) {
11234 typedef std::integral_constant<bool,
11235 #if SOL_IS_OFF(SOL_ALIGN_MEMORY) 11238 (std::alignment_of<T*>::value > 1 || std::alignment_of<unique_tag>::value > 1 || std::alignment_of<unique_destructor>::value > 1
11239 || std::alignment_of<Real>::value > 1)
11243 if (!use_align::value) {
11244 pref =
static_cast<T**
>(alloc_newuserdata(L,
sizeof(T*) +
sizeof(detail::unique_destructor) +
sizeof(unique_tag) +
sizeof(Real)));
11245 dx =
static_cast<detail::unique_destructor*
>(
static_cast<void*
>(pref + 1));
11246 id =
static_cast<unique_tag*
>(
static_cast<void*
>(dx + 1));
11247 Real* mem =
static_cast<Real*
>(
static_cast<void*
>(
id + 1));
11251 constexpr std::size_t initial_size = aligned_space_for<T*, unique_destructor, unique_tag, Real>();
11253 void* pointer_adjusted;
11256 void* data_adjusted;
11257 bool result = attempt_alloc_unique(L,
11258 std::alignment_of_v<T*>,
11260 std::alignment_of_v<Real>,
11267 if (pointer_adjusted ==
nullptr) {
11268 luaL_error(L,
"aligned allocation of userdata block (pointer section) for '%s' failed", detail::demangle<T>().c_str());
11270 else if (dx_adjusted ==
nullptr) {
11271 luaL_error(L,
"aligned allocation of userdata block (deleter section) for '%s' failed", detail::demangle<T>().c_str());
11274 luaL_error(L,
"aligned allocation of userdata block (data section) for '%s' failed", detail::demangle<T>().c_str());
11279 pref =
static_cast<T**
>(pointer_adjusted);
11280 dx =
static_cast<detail::unique_destructor*
>(dx_adjusted);
11281 id =
static_cast<unique_tag*
>(id_adjusted);
11282 Real* mem =
static_cast<Real*
>(data_adjusted);
11286 template <
typename T>
11288 typedef std::integral_constant<bool,
11289 #if SOL_IS_OFF(SOL_ALIGN_MEMORY) 11292 (std::alignment_of_v<T> > 1)
11296 if (!use_align::value) {
11297 T* pointer =
static_cast<T*
>(alloc_newuserdata(L,
sizeof(T)));
11301 constexpr std::size_t initial_size = aligned_space_for<T>();
11303 std::size_t allocated_size = initial_size;
11304 void* unadjusted = alloc_newuserdata(L, allocated_size);
11305 void* adjusted = align(std::alignment_of_v<T>, unadjusted, allocated_size);
11306 if (adjusted ==
nullptr) {
11308 luaL_error(L,
"cannot properly align memory for '%s'", detail::demangle<T>().data());
11310 return static_cast<T*
>(adjusted);
11313 template <
typename T>
11314 int usertype_alloc_destroy(
lua_State* L) noexcept {
11315 void* memory = lua_touserdata(L, 1);
11316 memory = align_usertype_pointer(memory);
11317 T** pdata =
static_cast<T**
>(memory);
11319 std::allocator<T> alloc {};
11320 std::allocator_traits<std::allocator<T>>::destroy(alloc, data);
11324 template <
typename T>
11325 int unique_destroy(
lua_State* L) noexcept {
11326 void* memory = lua_touserdata(L, 1);
11327 memory = align_usertype_unique_destructor(memory);
11328 unique_destructor& dx = *
static_cast<unique_destructor*
>(memory);
11329 memory = align_usertype_unique_tag<true>(memory);
11334 template <
typename T>
11335 int user_alloc_destroy(
lua_State* L) noexcept {
11336 void* memory = lua_touserdata(L, 1);
11337 void* aligned_memory = align_user<T>(memory);
11338 T* typed_memory =
static_cast<T*
>(aligned_memory);
11339 std::allocator<T> alloc;
11340 std::allocator_traits<std::allocator<T>>::destroy(alloc, typed_memory);
11344 template <
typename T,
typename Real>
11345 void usertype_unique_alloc_destroy(
void* memory) {
11346 void* aligned_memory = align_usertype_unique<Real, true>(memory);
11347 Real* typed_memory =
static_cast<Real*
>(aligned_memory);
11348 std::allocator<Real> alloc;
11349 std::allocator_traits<std::allocator<Real>>::destroy(alloc, typed_memory);
11352 template <
typename T>
11354 return luaL_error(L,
11355 "cannot call the destructor for '%s': it is either hidden (protected/private) or removed with '= " 11356 "delete' and thusly this type is being destroyed without properly destroying, invoking undefined " 11357 "behavior: please bind a usertype and specify a custom destructor to define the behavior properly",
11358 detail::demangle<T>().data());
11361 template <
typename T>
11362 void reserve(T&, std::size_t) {
11365 template <
typename T,
typename Al>
11366 void reserve(std::vector<T, Al>& vec, std::size_t hint) {
11370 template <
typename T,
typename Tr,
typename Al>
11371 void reserve(std::basic_string<T, Tr, Al>& str, std::size_t hint) {
11375 inline bool property_always_true(meta_function) {
11380 int& times_through;
11381 std::bitset<64>& properties;
11385 : times_through(times_through_), properties(properties_), enrollments(enrollments_) {
11388 bool operator()(meta_function mf)
const {
11389 bool p = properties[
static_cast<std::size_t
>(mf)];
11390 if (times_through > 0) {
11394 case meta_function::length:
11395 return enrollments.length_operator && !p;
11396 case meta_function::pairs:
11397 return enrollments.pairs_operator && !p;
11398 case meta_function::call:
11399 return enrollments.call_operator && !p;
11400 case meta_function::less_than:
11401 return enrollments.less_than_operator && !p;
11402 case meta_function::less_than_or_equal_to:
11403 return enrollments.less_than_or_equal_to_operator && !p;
11404 case meta_function::equal_to:
11405 return enrollments.equal_to_operator && !p;
11414 lua_reg_table& registration_table;
11417 indexed_insert(lua_reg_table& registration_table_,
int& index_ref_) : registration_table(registration_table_), index(index_ref_) {
11419 void operator()(meta_function meta_function_name_, lua_CFunction c_function_) {
11420 registration_table[index] =
luaL_Reg { to_string(meta_function_name_).c_str(), c_function_ };
11428 template <
typename T,
bool global = false,
bool raw = false,
typename =
void>
11430 template <
typename T,
typename P,
bool global = false,
bool raw = false,
typename =
void>
11433 template <
typename T,
bool global = false,
bool raw = false,
typename =
void>
11436 template <
typename T,
typename =
void>
11438 template <
typename T,
typename =
void>
11441 template <
typename T,
typename =
void>
11443 template <
typename T,
typename =
void>
11446 template <
typename T,
typename =
void>
11449 template <
typename T,
typename =
void>
11452 template <
typename T, type t,
typename =
void>
11454 template <
typename T, type t,
typename =
void>
11457 template <
typename T,
typename =
void>
11459 template <
typename T,
typename =
void>
11466 probe(
bool s,
int l) : success(s), levels(l) {
11469 operator bool()
const {
11478 record() noexcept : last(), used() {
11480 void use(
int count) noexcept {
11486 namespace stack_detail {
11487 template <
typename Function>
11489 template <
typename Function,
typename Handler>
11490 bool check_function_pointer(
lua_State* L,
int index, Handler&& handler,
record& tracking) noexcept;
11495 namespace meta {
namespace meta_detail {
11496 template <
typename T>
11497 using adl_sol_lua_get_test_t = decltype(sol_lua_get(
types<T>(), static_cast<lua_State*>(
nullptr), -1, std::declval<stack::record&>()));
11499 template <
typename T>
11500 using adl_sol_lua_interop_get_test_t
11501 = decltype(sol_lua_interop_get(
types<T>(), static_cast<lua_State*>(
nullptr), -1, static_cast<void*>(
nullptr), std::declval<stack::record&>()));
11503 template <
typename T>
11504 using adl_sol_lua_check_test_t = decltype(sol_lua_check(
types<T>(), static_cast<lua_State*>(
nullptr), -1, &no_panic, std::declval<stack::record&>()));
11506 template <
typename T>
11507 using adl_sol_lua_interop_check_test_t
11508 = decltype(sol_lua_interop_check(
types<T>(), static_cast<lua_State*>(
nullptr), -1, type::none, &no_panic, std::declval<stack::record&>()));
11510 template <
typename T>
11511 using adl_sol_lua_check_get_test_t
11512 = decltype(sol_lua_check_get(
types<T>(), static_cast<lua_State*>(
nullptr), -1, &no_panic, std::declval<stack::record&>()));
11514 template <
typename... Args>
11515 using adl_sol_lua_push_test_t = decltype(sol_lua_push(static_cast<lua_State*>(
nullptr), std::declval<Args>()...));
11517 template <
typename T,
typename... Args>
11518 using adl_sol_lua_push_exact_test_t = decltype(sol_lua_push(
types<T>(), static_cast<lua_State*>(
nullptr), std::declval<Args>()...));
11520 template <
typename T>
11521 inline constexpr
bool is_adl_sol_lua_get_v = meta::is_detected_v<adl_sol_lua_get_test_t, T>;
11523 template <
typename T>
11524 inline constexpr
bool is_adl_sol_lua_interop_get_v = meta::is_detected_v<adl_sol_lua_interop_get_test_t, T>;
11526 template <
typename T>
11527 inline constexpr
bool is_adl_sol_lua_check_v = meta::is_detected_v<adl_sol_lua_check_test_t, T>;
11529 template <
typename T>
11530 inline constexpr
bool is_adl_sol_lua_interop_check_v = meta::is_detected_v<adl_sol_lua_interop_check_test_t, T>;
11532 template <
typename T>
11533 inline constexpr
bool is_adl_sol_lua_check_get_v = meta::is_detected_v<adl_sol_lua_check_get_test_t, T>;
11535 template <
typename... Args>
11536 inline constexpr
bool is_adl_sol_lua_push_v = meta::is_detected_v<adl_sol_lua_push_test_t, Args...>;
11538 template <
typename T,
typename... Args>
11539 inline constexpr
bool is_adl_sol_lua_push_exact_v = meta::is_detected_v<adl_sol_lua_push_exact_test_t, T, Args...>;
11543 namespace stack_detail {
11544 constexpr
const char* not_enough_stack_space =
"not enough space left on Lua stack";
11545 constexpr
const char* not_enough_stack_space_floating =
"not enough space left on Lua stack for a floating point number";
11546 constexpr
const char* not_enough_stack_space_integral =
"not enough space left on Lua stack for an integral number";
11547 constexpr
const char* not_enough_stack_space_string =
"not enough space left on Lua stack for a string";
11548 constexpr
const char* not_enough_stack_space_meta_function_name =
"not enough space left on Lua stack for the name of a meta_function";
11549 constexpr
const char* not_enough_stack_space_userdata =
"not enough space left on Lua stack to create a sol2 userdata";
11550 constexpr
const char* not_enough_stack_space_generic =
"not enough space left on Lua stack to push valuees";
11551 constexpr
const char* not_enough_stack_space_environment =
"not enough space left on Lua stack to retrieve environment";
11553 template <
typename T>
11557 template <
typename T>
11561 template <
typename T>
11565 template <
typename T>
11569 template <
typename T>
11570 using strip_t =
typename strip<T>::type;
11572 template <
typename C>
11573 static int get_size_hint(C& c) {
11574 return static_cast<int>(c.size());
11577 template <
typename V,
typename Al>
11578 static int get_size_hint(
const std::forward_list<V, Al>&) {
11580 return static_cast<int>(32);
11583 template <
typename T>
11584 decltype(
auto) unchecked_unqualified_get(
lua_State* L,
int index,
record& tracking) {
11585 using Tu = meta::unqualified_t<T>;
11586 if constexpr (meta::meta_detail::is_adl_sol_lua_get_v<Tu>) {
11587 return sol_lua_get(
types<Tu>(), L, index, tracking);
11591 return g.get(L, index, tracking);
11595 template <
typename T>
11596 decltype(
auto) unchecked_get(
lua_State* L,
int index,
record& tracking) {
11597 if constexpr (meta::meta_detail::is_adl_sol_lua_get_v<T>) {
11598 return sol_lua_get(
types<T>(), L, index, tracking);
11602 return g.get(L, index, tracking);
11606 template <
typename T>
11607 decltype(
auto) unqualified_interop_get(
lua_State* L,
int index,
void* unadjusted_pointer,
record& tracking) {
11608 using Tu = meta::unqualified_t<T>;
11609 if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v<Tu>) {
11610 return sol_lua_interop_get(
types<Tu>(), L, index, unadjusted_pointer, tracking);
11615 (void)unadjusted_pointer;
11617 using Ti = stack_detail::strip_t<Tu>;
11618 return std::pair<bool, Ti*> {
false,
nullptr };
11622 template <
typename T>
11623 decltype(
auto) interop_get(
lua_State* L,
int index,
void* unadjusted_pointer,
record& tracking) {
11624 if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v<T>) {
11625 return sol_lua_interop_get(
types<T>(), L, index, unadjusted_pointer, tracking);
11628 return unqualified_interop_get<T>(L, index, unadjusted_pointer, tracking);
11632 template <
typename T,
typename Handler>
11633 bool unqualified_interop_check(
lua_State* L,
int index, type index_type, Handler&& handler,
record& tracking) {
11634 using Tu = meta::unqualified_t<T>;
11635 if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v<Tu>) {
11636 return sol_lua_interop_check(
types<Tu>(), L, index, index_type, std::forward<Handler>(handler), tracking);
11648 template <
typename T,
typename Handler>
11649 bool interop_check(
lua_State* L,
int index, type index_type, Handler&& handler,
record& tracking) {
11650 if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v<T>) {
11651 return sol_lua_interop_check(
types<T>(), L, index, index_type, std::forward<Handler>(handler), tracking);
11654 return unqualified_interop_check<T>(L, index, index_type, std::forward<Handler>(handler), tracking);
11663 undefined_method_func on_new_table;
11668 void operator()()
const {
11669 if (luaL_newmetatable(L, key) == 1) {
11672 lua_setmetatable(L, -2);
11677 inline bool maybe_indexable(
lua_State* L,
int index = -1) {
11678 type t = type_of(L, index);
11679 return t == type::userdata || t == type::table;
11683 return lua_gettop(L);
11686 inline bool is_main_thread(
lua_State* L) {
11687 int ismainthread = lua_pushthread(L);
11689 return ismainthread == 1;
11692 inline void coroutine_create_guard(
lua_State* L) {
11693 if (is_main_thread(L)) {
11696 int stacksize = lua_gettop(L);
11697 if (stacksize < 1) {
11700 if (type_of(L, 1) != type::function) {
11705 lua_pop(L, stacksize);
11708 inline void clear(
lua_State* L,
int table_index) {
11710 while (lua_next(L, table_index) != 0) {
11714 lua_pushvalue(L, -1);
11718 lua_rawset(L, table_index);
11723 auto pp = push_pop<false>(r);
11724 int stack_index = pp.index_of(r);
11725 clear(r.lua_state(), stack_index);
11729 clear(r.lua_state(), r.stack_index());
11735 clear(L_, stack_index);
11740 clear(L_, r.stack_index());
11743 template <
typename T,
typename... Args>
11744 int push(
lua_State* L, T&& t, Args&&... args) {
11745 using Tu = meta::unqualified_t<T>;
11746 if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v<T, T, Args...>) {
11747 return sol_lua_push(
types<T>(), L, std::forward<T>(t), std::forward<Args>(args)...);
11749 else if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v<Tu, T, Args...>) {
11750 return sol_lua_push(
types<Tu>(), L, std::forward<T>(t), std::forward<Args>(args)...);
11752 else if constexpr (meta::meta_detail::is_adl_sol_lua_push_v<T, Args...>) {
11753 return sol_lua_push(L, std::forward<T>(t), std::forward<Args>(args)...);
11757 return p.push(L, std::forward<T>(t), std::forward<Args>(args)...);
11762 template <
typename T,
typename Arg,
typename... Args,
typename = std::enable_if_t<!std::is_same<T, Arg>::value>>
11763 int push(
lua_State* L, Arg&& arg, Args&&... args) {
11764 using Tu = meta::unqualified_t<T>;
11765 if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v<T, Arg, Args...>) {
11766 return sol_lua_push(
types<T>(), L, std::forward<Arg>(arg), std::forward<Args>(args)...);
11768 else if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v<Tu, Arg, Args...>) {
11769 return sol_lua_push(
types<Tu>(), L, std::forward<Arg>(arg), std::forward<Args>(args)...);
11771 else if constexpr (meta::meta_detail::is_adl_sol_lua_push_v<Arg, Args...> && !detail::is_tagged_v<Tu>) {
11772 return sol_lua_push(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
11776 return p.push(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
11780 template <
typename T,
typename... Args>
11781 int push_userdata(
lua_State* L, T&& t, Args&&... args) {
11782 using U = meta::unqualified_t<T>;
11783 using Tr = meta::conditional_t<std::is_pointer_v<U>,
11786 return stack::push<Tr>(L, std::forward<T>(t), std::forward<Args>(args)...);
11789 template <
typename T,
typename Arg,
typename... Args>
11790 int push_userdata(
lua_State* L, Arg&& arg, Args&&... args) {
11791 using U = meta::unqualified_t<T>;
11792 using Tr = meta::conditional_t<std::is_pointer_v<U>,
11795 return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
11798 namespace stack_detail {
11800 template <
typename T,
typename Arg,
typename... Args>
11801 int push_reference(
lua_State* L, Arg&& arg, Args&&... args) {
11803 using use_reference_tag =
11805 meta::neg<is_value_semantic_for_function<T>>
11806 #if SOL_IS_OFF(SOL_FUNCTION_CALL_VALUE_SEMANTICS) 11807 , std::is_lvalue_reference<T>,
11808 meta::neg<std::is_const<std::remove_reference_t<T>>>,
11809 meta::neg<is_lua_primitive<meta::unqualified_t<T>>>,
11810 meta::neg<is_unique_usertype<meta::unqualified_t<T>>>
11814 using Tr = meta::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>;
11815 return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
11820 template <
typename T,
typename... Args>
11821 int push_reference(
lua_State* L, T&& t, Args&&... args) {
11822 return stack_detail::push_reference<T>(L, std::forward<T>(t), std::forward<Args>(args)...);
11825 template <
typename T,
typename Arg,
typename... Args>
11826 int push_reference(
lua_State* L, Arg&& arg, Args&&... args) {
11827 return stack_detail::push_reference<T>(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
11835 template <
typename T,
typename... Args>
11836 int multi_push(
lua_State* L, T&& t, Args&&... args) {
11837 int pushcount = push(L, std::forward<T>(t));
11838 void(detail::swallow { (pushcount += stack::push(L, std::forward<Args>(args)), 0)... });
11842 inline int multi_push_reference(
lua_State*) {
11847 template <
typename T,
typename... Args>
11848 int multi_push_reference(
lua_State* L, T&& t, Args&&... args) {
11849 int pushcount = stack::push_reference(L, std::forward<T>(t));
11850 void(detail::swallow { (pushcount += stack::push_reference(L, std::forward<Args>(args)), 0)... });
11854 template <
typename T,
typename Handler>
11855 bool unqualified_check(
lua_State* L,
int index, Handler&& handler,
record& tracking) {
11856 using Tu = meta::unqualified_t<T>;
11857 if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<Tu>) {
11858 return sol_lua_check(
types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
11862 return c.check(L, index, std::forward<Handler>(handler), tracking);
11866 template <
typename T,
typename Handler>
11867 bool unqualified_check(
lua_State* L,
int index, Handler&& handler) {
11869 return unqualified_check<T>(L, index, std::forward<Handler>(handler), tracking);
11872 template <
typename T>
11873 bool unqualified_check(
lua_State* L,
int index = -
lua_size<meta::unqualified_t<T>>::value) {
11874 auto handler = &no_panic;
11875 return unqualified_check<T>(L, index, handler);
11878 template <
typename T,
typename Handler>
11879 bool check(
lua_State* L,
int index, Handler&& handler,
record& tracking) {
11880 if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<T>) {
11881 return sol_lua_check(
types<T>(), L, index, std::forward<Handler>(handler), tracking);
11884 using Tu = meta::unqualified_t<T>;
11886 return c.check(L, index, std::forward<Handler>(handler), tracking);
11890 template <
typename T,
typename Handler>
11891 bool check(
lua_State* L,
int index, Handler&& handler) {
11893 return check<T>(L, index, std::forward<Handler>(handler), tracking);
11896 template <
typename T>
11897 bool check(
lua_State* L,
int index = -
lua_size<meta::unqualified_t<T>>::value) {
11898 auto handler = &no_panic;
11899 return check<T>(L, index, handler);
11902 template <
typename T,
typename Handler>
11903 bool check_usertype(
lua_State* L,
int index, type, Handler&& handler,
record& tracking) {
11904 using Tu = meta::unqualified_t<T>;
11906 return check<detail_t>(L, index, std::forward<Handler>(handler), tracking);
11909 template <
typename T,
typename Handler>
11910 bool check_usertype(
lua_State* L,
int index, Handler&& handler,
record& tracking) {
11911 using Tu = meta::unqualified_t<T>;
11913 return check<detail_t>(L, index, std::forward<Handler>(handler), tracking);
11916 template <
typename T,
typename Handler>
11917 bool check_usertype(
lua_State* L,
int index, Handler&& handler) {
11919 return check_usertype<T>(L, index, std::forward<Handler>(handler), tracking);
11922 template <
typename T>
11923 bool check_usertype(
lua_State* L,
int index = -
lua_size<meta::unqualified_t<T>>::value) {
11924 auto handler = &no_panic;
11925 return check_usertype<T>(L, index, handler);
11928 template <
typename T,
typename Handler>
11929 decltype(
auto) unqualified_check_get(
lua_State* L,
int index, Handler&& handler,
record& tracking) {
11930 using Tu = meta::unqualified_t<T>;
11931 if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v<T>) {
11932 return sol_lua_check_get(
types<T>(), L, index, std::forward<Handler>(handler), tracking);
11934 else if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v<Tu>) {
11935 return sol_lua_check_get(
types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
11939 return cg.get(L, index, std::forward<Handler>(handler), tracking);
11943 template <
typename T,
typename Handler>
11944 decltype(
auto) unqualified_check_get(
lua_State* L,
int index, Handler&& handler) {
11946 return unqualified_check_get<T>(L, index, handler, tracking);
11949 template <
typename T>
11950 decltype(
auto) unqualified_check_get(
lua_State* L,
int index = -
lua_size<meta::unqualified_t<T>>::value) {
11951 auto handler = &no_panic;
11952 return unqualified_check_get<T>(L, index, handler);
11955 template <
typename T,
typename Handler>
11956 decltype(
auto) check_get(
lua_State* L,
int index, Handler&& handler,
record& tracking) {
11957 if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v<T>) {
11958 return sol_lua_check_get(
types<T>(), L, index, std::forward<Handler>(handler), tracking);
11962 return cg.get(L, index, std::forward<Handler>(handler), tracking);
11966 template <
typename T,
typename Handler>
11967 decltype(
auto) check_get(
lua_State* L,
int index, Handler&& handler) {
11969 return check_get<T>(L, index, handler, tracking);
11972 template <
typename T>
11973 decltype(
auto) check_get(
lua_State* L,
int index = -
lua_size<meta::unqualified_t<T>>::value) {
11974 auto handler = &no_panic;
11975 return check_get<T>(L, index, handler);
11978 namespace stack_detail {
11980 template <
typename Handler>
11985 template <
typename T,
typename... Args,
typename Handler>
11986 bool check_types(
lua_State* L,
int firstargument, Handler&& handler,
record& tracking) {
11987 if (!stack::check<T>(L, firstargument + tracking.used, handler, tracking))
11989 return check_types<Args...>(L, firstargument, std::forward<Handler>(handler), tracking);
11992 template <
typename... Args,
typename Handler>
11994 return check_types<Args...>(L, index, std::forward<Handler>(handler), tracking);
11999 template <
typename... Args,
typename Handler>
12000 bool multi_check(
lua_State* L,
int index, Handler&& handler,
record& tracking) {
12001 return stack_detail::check_types<Args...>(L, index, std::forward<Handler>(handler), tracking);
12004 template <
typename... Args,
typename Handler>
12005 bool multi_check(
lua_State* L,
int index, Handler&& handler) {
12007 return multi_check<Args...>(L, index, std::forward<Handler>(handler), tracking);
12010 template <
typename... Args>
12011 bool multi_check(
lua_State* L,
int index) {
12012 return multi_check<Args...>(L, index);
12015 template <
typename T>
12016 auto unqualified_get(
lua_State* L,
int index,
record& tracking) -> decltype(stack_detail::unchecked_unqualified_get<T>(L, index, tracking)) {
12017 #if SOL_IS_ON(SOL_SAFE_GETTER) 12018 static constexpr
bool is_op = meta::is_optional_v<T>;
12019 if constexpr (is_op) {
12020 return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
12024 return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
12026 auto op = unqualified_check_get<T>(L, index, type_panic_c_str, tracking);
12027 return *std::move(op);
12030 return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
12034 template <
typename T>
12035 decltype(
auto) unqualified_get(
lua_State* L,
int index = -
lua_size<meta::unqualified_t<T>>::value) {
12037 return unqualified_get<T>(L, index, tracking);
12040 template <
typename T>
12041 auto get(
lua_State* L,
int index,
record& tracking) -> decltype(stack_detail::unchecked_get<T>(L, index, tracking)) {
12042 #if SOL_IS_ON(SOL_SAFE_GETTER) 12043 static constexpr
bool is_op = meta::is_optional_v<T>;
12044 if constexpr (is_op) {
12045 return stack_detail::unchecked_get<T>(L, index, tracking);
12049 return stack_detail::unchecked_get<T>(L, index, tracking);
12051 auto op = check_get<T>(L, index, type_panic_c_str, tracking);
12052 return *std::move(op);
12055 return stack_detail::unchecked_get<T>(L, index, tracking);
12059 template <
typename T>
12062 return get<T>(L, index, tracking);
12065 template <
typename T>
12066 decltype(
auto) get_usertype(
lua_State* L,
int index,
record& tracking) {
12068 return get<UT>(L, index, tracking);
12071 template <
typename T>
12072 decltype(
auto) get_usertype(
lua_State* L,
int index = -lua_size_v<meta::unqualified_t<T>>) {
12074 return get_usertype<T>(L, index, tracking);
12077 template <
typename T>
12082 template <
bool global = false,
bool raw = false,
typename Key>
12083 void get_field(
lua_State* L, Key&& key) {
12087 template <
bool global = false,
bool raw = false,
typename Key>
12088 void get_field(
lua_State* L, Key&& key,
int tableindex) {
12092 template <
bool global = false,
typename Key>
12093 void raw_get_field(
lua_State* L, Key&& key) {
12094 get_field<global, true>(L, std::forward<Key>(key));
12097 template <
bool global = false,
typename Key>
12098 void raw_get_field(
lua_State* L, Key&& key,
int tableindex) {
12099 get_field<global, true>(L, std::forward<Key>(key), tableindex);
12102 template <
bool global = false,
bool raw = false,
typename C = detail::non_lua_nil_t,
typename Key>
12107 template <
bool global = false,
bool raw = false,
typename C = detail::non_lua_nil_t,
typename Key>
12108 probe probe_get_field(
lua_State* L, Key&& key,
int tableindex) {
12112 template <
bool global = false,
typename C = detail::non_lua_nil_t,
typename Key>
12114 return probe_get_field<global, true, C>(L, std::forward<Key>(key));
12117 template <
bool global = false,
typename C = detail::non_lua_nil_t,
typename Key>
12118 probe probe_raw_get_field(
lua_State* L, Key&& key,
int tableindex) {
12119 return probe_get_field<global, true, C>(L, std::forward<Key>(key), tableindex);
12122 template <
bool global = false,
bool raw = false,
typename Key,
typename Value>
12127 template <
bool global = false,
bool raw = false,
typename Key,
typename Value>
12128 void set_field(
lua_State* L, Key&& key,
Value&& value,
int tableindex) {
12132 template <
bool global = false,
typename Key,
typename Value>
12134 set_field<global, true>(L, std::forward<Key>(key), std::forward<Value>(value));
12137 template <
bool global = false,
typename Key,
typename Value>
12138 void raw_set_field(
lua_State* L, Key&& key,
Value&& value,
int tableindex) {
12139 set_field<global, true>(L, std::forward<Key>(key), std::forward<Value>(value), tableindex);
12142 template <
typename T,
typename F>
12144 void* raw = lua_touserdata(obj.lua_state(), obj.stack_index());
12145 void* ptr_memory = detail::align_usertype_pointer(raw);
12146 void* uu_memory = detail::align_usertype_unique<T>(raw);
12147 T& uu = *
static_cast<T*
>(uu_memory);
12149 *
static_cast<void**
>(ptr_memory) = static_cast<void*>(detail::unique_get(obj.lua_state(), uu));
12152 template <
typename F>
12155 using T =
typename bt::template arg_at<0>;
12156 using Tu = meta::unqualified_t<T>;
12157 modify_unique_usertype_as<Tu>(obj, std::forward<F>(f));
12160 namespace stack_detail {
12161 template <
typename T,
typename Handler>
12162 decltype(
auto) check_get_arg(
lua_State* L_,
int index_, Handler&& handler_,
record& tracking_) {
12163 if constexpr (meta::meta_detail::is_adl_sol_lua_check_access_v<T>) {
12164 sol_lua_check_access(
types<meta::unqualified_t<T>>(), L_, index_, tracking_);
12166 return check_get<T>(L_, index_, std::forward<Handler>(handler_), tracking_);
12169 template <
typename T>
12170 decltype(
auto) unchecked_get_arg(
lua_State* L_,
int index_,
record& tracking_) {
12171 if constexpr (meta::meta_detail::is_adl_sol_lua_check_access_v<T>) {
12172 sol_lua_check_access(
types<meta::unqualified_t<T>>(), L_, index_, tracking_);
12174 return unchecked_get<T>(L_, index_, tracking_);
12182 template <
typename T>
12183 lua_CFunction make_destructor(std::true_type) {
12184 if constexpr (is_unique_usertype_v<T>) {
12185 return &unique_destroy<T>;
12187 else if constexpr (!std::is_pointer_v<T>) {
12188 return &usertype_alloc_destroy<T>;
12191 return &cannot_destroy<T>;
12195 template <
typename T>
12196 lua_CFunction make_destructor(std::false_type) {
12197 return &cannot_destroy<T>;
12200 template <
typename T>
12201 lua_CFunction make_destructor() {
12202 return make_destructor<T>(std::is_destructible<T>());
12206 template <
typename A,
typename B>
12207 bool operator()(A&&, B&&)
const {
12212 template <
typename T>
12214 return stack::push(L, stack::check<T>(L, 1, &no_panic));
12217 template <
typename T>
12218 int member_default_to_string(std::true_type,
lua_State* L) {
12219 decltype(
auto) ts = stack::get<T>(L, 1).to_string();
12220 return stack::push(L, std::forward<decltype(ts)>(ts));
12223 template <
typename T>
12224 int member_default_to_string(std::false_type,
lua_State* L) {
12225 return luaL_error(L,
12226 "cannot perform to_string on '%s': no 'to_string' overload in namespace, 'to_string' member " 12227 "function, or operator<<(ostream&, ...) present",
12228 detail::demangle<T>().data());
12231 template <
typename T>
12232 int adl_default_to_string(std::true_type,
lua_State* L) {
12233 using namespace std;
12234 decltype(
auto) ts = to_string(stack::get<T>(L, 1));
12235 return stack::push(L, std::forward<decltype(ts)>(ts));
12238 template <
typename T>
12239 int adl_default_to_string(std::false_type,
lua_State* L) {
12243 template <
typename T>
12244 int oss_default_to_string(std::true_type,
lua_State* L) {
12245 std::ostringstream oss;
12246 oss << stack::unqualified_get<T>(L, 1);
12247 return stack::push(L, oss.str());
12250 template <
typename T>
12251 int oss_default_to_string(std::false_type,
lua_State* L) {
12255 template <
typename T>
12260 template <
typename T>
12262 decltype(
auto)
self = stack::unqualified_get<T>(L, 1);
12263 return stack::push(L,
self.size());
12266 template <
typename T,
typename Op>
12267 int comparsion_operator_wrap(
lua_State* L) {
12268 if constexpr (std::is_void_v<T>) {
12269 return stack::push(L,
false);
12272 auto maybel = stack::unqualified_check_get<T>(L, 1);
12274 return stack::push(L,
false);
12276 auto mayber = stack::unqualified_check_get<T>(L, 2);
12278 return stack::push(L,
false);
12280 decltype(
auto) l = *maybel;
12281 decltype(
auto) r = *mayber;
12282 if constexpr (std::is_same_v<no_comp, Op>) {
12283 std::equal_to<> op;
12284 return stack::push(L, op(detail::ptr(l), detail::ptr(r)));
12287 if constexpr (std::is_same_v<std::equal_to<>, Op>
12288 || std::is_same_v<std::less_equal<>, Op>
12289 || std::is_same_v<std::less_equal<>, Op>) {
12290 if (detail::ptr(l) == detail::ptr(r)) {
12291 return stack::push(L,
true);
12295 return stack::push(L, op(detail::deref(l), detail::deref(r)));
12300 template <
typename T,
typename IFx,
typename Fx>
12301 void insert_default_registrations(IFx&& ifx, Fx&& fx);
12303 template <
typename T,
bool,
bool>
12306 template <
typename T>
12308 : meta::neg<std::is_reference<decltype(sol_lua_get(types<T>(), nullptr, -1, std::declval<stack::record&>()))>> { };
12310 template <
typename T>
12312 : meta::neg<std::is_reference<decltype(sol_lua_get(types<meta::unqualified_t<T>>(), nullptr, -1, std::declval<stack::record&>()))>> { };
12314 template <
typename T>
12319 template <
typename T>
12321 :
detail::get_is_primitive<T, meta::meta_detail::is_adl_sol_lua_get_v<T>, meta::meta_detail::is_adl_sol_lua_get_v<meta::unqualified_t<T>>> { };
12332 #include <functional> 12335 #include <optional> 12336 #if SOL_IS_ON(SOL_STD_VARIANT) 12338 #endif // variant shenanigans 12340 namespace sol {
namespace stack {
12341 template <
typename Handler>
12342 bool loose_table_check(
lua_State* L_,
int index, Handler&& handler, record& tracking) {
12344 type t = type_of(L_, index);
12345 if (t == type::table) {
12348 if (t != type::userdata) {
12349 handler(L_, index, type::table, t,
"value is not a table or a userdata that can behave like one");
12355 namespace stack_detail {
12356 inline bool impl_check_metatable(
lua_State* L_,
int index,
const std::string& metakey,
bool poptable) {
12357 luaL_getmetatable(L_, &metakey[0]);
12358 const type expectedmetatabletype =
static_cast<type
>(lua_type(L_, -1));
12359 if (expectedmetatabletype != type::lua_nil) {
12360 if (lua_rawequal(L_, -1, index) == 1) {
12361 lua_pop(L_, 1 + static_cast<int>(poptable));
12369 template <
typename T,
bool poptable = true>
12370 inline bool check_metatable(
lua_State* L_,
int index = -2) {
12374 template <type expected,
int (*check_func)(lua_State*,
int)>
12376 template <
typename Handler>
12377 static bool check(
lua_State* L_,
int index, Handler&& handler,
record& tracking) {
12379 bool success = check_func(L_, index) == 1;
12382 handler(L_, index, expected, type_of(L_, index),
"");
12389 template <
typename T,
typename>
12391 template <
typename Handler>
12397 template <
typename T,
typename>
12399 template <
typename Handler>
12400 static bool check(
lua_State* L_,
int index, type index_type, Handler&& handler,
record& tracking) {
12401 return stack_detail::unqualified_interop_check<T>(L_, index, index_type, std::forward<Handler>(handler), tracking);
12405 template <
typename T, type expected,
typename>
12407 template <
typename Handler>
12408 static bool check(
lua_State* L_,
int index, Handler&& handler,
record& tracking) {
12409 if constexpr (std::is_same_v<T, bool>) {
12411 bool success = lua_isboolean(L_, index) == 1;
12414 handler(L_, index, expected, type_of(L_, index),
"");
12418 else if constexpr (meta::any_same_v<T,
12420 #
if SOL_IS_ON(SOL_CHAR8_T)
12427 return stack::check<std::basic_string<T>>(L_, index, std::forward<Handler>(handler), tracking);
12429 else if constexpr (std::is_integral_v<T> || std::is_same_v<T, lua_Integer>) {
12431 #if SOL_LUA_VERSION_I_ >= 503 12433 #if SOL_IS_ON(SOL_STRINGS_ARE_NUMBERS) 12436 lua_tointegerx(L_, index, &isnum);
12437 const bool success = isnum != 0;
12440 handler(L_, index, type::number, type_of(L_, index), detail::not_a_number_or_number_string_integral);
12442 #elif SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS) 12444 if (lua_isinteger(L_, index) == 1) {
12447 const bool success =
false;
12450 handler(L_, index, type::number, type_of(L_, index), detail::not_a_number_integral);
12454 type t = type_of(L_, index);
12455 const bool success = t == type::number;
12459 handler(L_, index, type::number, type_of(L_, index), detail::not_a_number);
12464 #if SOL_IS_OFF(SOL_STRINGS_ARE_NUMBERS) 12466 type t = type_of(L_, index);
12467 if (t != type::number) {
12469 handler(L_, index, type::number, t, detail::not_a_number);
12472 #endif // Do not allow strings to be numbers 12474 #if SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS) 12476 const lua_Number v = lua_tonumberx(L_, index, &isnum);
12477 const bool success = isnum != 0 &&
static_cast<lua_Number
>(llround(v)) == v;
12479 const bool success =
true;
12480 #endif // Safe numerics and number precision checking 12483 #if SOL_IS_ON(SOL_STRINGS_ARE_NUMBERS) 12484 handler(L_, index, type::number, type_of(L_, index), detail::not_a_number_or_number_string);
12485 #elif SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS) 12486 handler(L_, index, type::number, t, detail::not_a_number_or_number_string);
12488 handler(L_, index, type::number, t, detail::not_a_number);
12494 else if constexpr (std::is_floating_point_v<T> || std::is_same_v<T, lua_Number>) {
12496 #if SOL_IS_ON(SOL_STRINGS_ARE_NUMBERS) 12497 bool success = lua_isnumber(L_, index) == 1;
12500 handler(L_, index, type::number, type_of(L_, index), detail::not_a_number_or_number_string);
12504 type t = type_of(L_, index);
12505 bool success = t == type::number;
12508 handler(L_, index, type::number, t, detail::not_a_number);
12511 #endif // Strings are Numbers 12513 else if constexpr (meta::any_same_v<T, type, this_state, this_main_state, this_environment, variadic_args>) {
12520 else if constexpr (is_unique_usertype_v<T>) {
12521 using element = unique_usertype_element_t<T>;
12522 using actual = unique_usertype_actual_t<T>;
12523 const type indextype = type_of(L_, index);
12525 if (indextype != type::userdata) {
12526 handler(L_, index, type::userdata, indextype,
"value is not a userdata");
12529 if (lua_getmetatable(L_, index) == 0) {
12532 int metatableindex = lua_gettop(L_);
12533 if (stack_detail::check_metatable<
d::u<element>>(L_, metatableindex)) {
12534 void* memory = lua_touserdata(L_, index);
12535 memory = detail::align_usertype_unique_destructor(memory);
12536 detail::unique_destructor& pdx = *
static_cast<detail::unique_destructor*
>(memory);
12537 bool success = &detail::usertype_unique_alloc_destroy<element, actual> == pdx;
12539 memory = detail::align_usertype_unique_tag<true>(memory);
12543 const char*& name_tag = *
static_cast<const char**
>(memory);
12547 handler(L_, index, type::userdata, indextype,
"value is a userdata but is not the correct unique usertype");
12553 handler(L_, index, type::userdata, indextype,
"unrecognized userdata (not pushed by sol?)");
12556 else if constexpr (meta::any_same_v<T, lua_nil_t, std::nullopt_t, nullopt_t>) {
12557 bool success = lua_isnil(L_, index);
12563 success = lua_isnone(L_, index);
12566 handler(L_, index, expected, type_of(L_, index),
"");
12570 else if constexpr (std::is_same_v<T, env_key_t>) {
12572 type t = type_of(L_, index);
12573 if (t == type::table || t == type::none || t == type::lua_nil || t == type::userdata) {
12576 handler(L_, index, type::table, t,
"value cannot not have a valid environment");
12579 else if constexpr (std::is_same_v<T, detail::non_lua_nil_t>) {
12580 return !stack::unqualified_check<lua_nil_t>(L_, index, std::forward<Handler>(handler), tracking);
12582 else if constexpr (meta::is_specialization_of_v<T, basic_lua_table>) {
12584 type t = type_of(L_, index);
12585 if (t != type::table) {
12586 handler(L_, index, type::table, t,
"value is not a table");
12591 else if constexpr (meta::is_specialization_of_v<T, basic_bytecode>) {
12593 type t = type_of(L_, index);
12594 if (t != type::function) {
12595 handler(L_, index, type::function, t,
"value is not a function that can be dumped");
12600 else if constexpr (meta::is_specialization_of_v<T, basic_environment>) {
12602 if (lua_getmetatable(L_, index) == 0) {
12605 type t = type_of(L_, -1);
12606 if (t == type::table || t == type::none || t == type::lua_nil) {
12610 if (t != type::userdata) {
12612 handler(L_, index, type::table, t,
"value does not have a valid metatable");
12617 else if constexpr (std::is_same_v<T, metatable_key_t>) {
12619 if (lua_getmetatable(L_, index) == 0) {
12622 type t = type_of(L_, -1);
12623 if (t == type::table || t == type::none || t == type::lua_nil) {
12627 if (t != type::userdata) {
12629 handler(L_, index, expected, t,
"value does not have a valid metatable");
12634 else if constexpr (std::is_same_v<T, luaL_Stream*> || std::is_same_v<T, luaL_Stream>) {
12635 if (lua_getmetatable(L_, index) == 0) {
12636 type t = type_of(L_, index);
12637 handler(L_, index, expected, t,
"value is not a valid luaL_Stream (has no metatable/is not a valid value)");
12640 luaL_getmetatable(L_, LUA_FILEHANDLE);
12641 if (type_of(L_, index) != type::table) {
12642 type t = type_of(L_, index);
12648 "value is not a valid luaL_Stream (there is no metatable for luaL_Stream -- did you forget to " 12649 "my_lua_state.open_libraries(sol::lib::state) or equivalent?)");
12652 int is_stream_table = lua_compare(L_, -1, -2, LUA_OPEQ);
12654 if (is_stream_table == 0) {
12655 type t = type_of(L_, index);
12656 handler(L_, index, expected, t,
"value is not a valid luaL_Stream (incorrect metatable)");
12661 else if constexpr (meta::is_optional_v<T>) {
12662 using ValueType =
typename T::value_type;
12664 type t = type_of(L_, index);
12665 if (t == type::none) {
12669 if (t == type::lua_nil) {
12673 return stack::unqualified_check<ValueType>(L_, index, &no_panic, tracking);
12675 #if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE) 12676 else if constexpr (std::is_function_v<T> || (std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>>)) {
12677 return stack_detail::check_function_pointer<std::remove_pointer_t<T>>(L_, index, std::forward<Handler>(handler), tracking);
12680 else if constexpr (expected == type::userdata) {
12681 if constexpr (meta::any_same_v<T, userdata_value> || meta::is_specialization_of_v<T, basic_userdata>) {
12683 type t = type_of(L_, index);
12684 bool success = t == type::userdata;
12687 handler(L_, index, type::userdata, t,
"");
12691 else if constexpr (meta::is_specialization_of_v<T, user>) {
12694 return c.check(L_, index, std::forward<Handler>(handler), tracking);
12697 if constexpr (std::is_pointer_v<T>) {
12698 return check_usertype<T>(L_, index, std::forward<Handler>(handler), tracking);
12700 else if constexpr (meta::is_specialization_of_v<T, std::reference_wrapper>) {
12701 using T_internal =
typename T::type;
12702 return stack::check<T_internal>(L_, index, std::forward<Handler>(handler), tracking);
12705 return check_usertype<T>(L_, index, std::forward<Handler>(handler), tracking);
12709 else if constexpr (expected == type::poly) {
12711 bool success = is_lua_reference_v<T> || !lua_isnone(L_, index);
12714 handler(L_, index, type::poly, type_of(L_, index),
"");
12718 else if constexpr (expected == type::lightuserdata) {
12720 type t = type_of(L_, index);
12721 bool success = t == type::userdata || t == type::lightuserdata;
12724 handler(L_, index, type::lightuserdata, t,
"");
12728 else if constexpr (expected == type::function) {
12729 if constexpr (meta::any_same_v<T, lua_CFunction, std::remove_pointer_t<lua_CFunction>,
c_closure>) {
12731 bool success = lua_iscfunction(L_, index) == 1;
12734 handler(L_, index, expected, type_of(L_, index),
"");
12740 type t = type_of(L_, index);
12741 if (t == type::lua_nil || t == type::none || t == type::function) {
12745 if (t != type::userdata && t != type::table) {
12746 handler(L_, index, type::function, t,
"must be a function or table or a userdata");
12750 static const auto& callkey = to_string(meta_function::call);
12751 if (lua_getmetatable(L_, index) == 0) {
12753 handler(L_, index, type::function, t,
"value is not a function and does not have overriden metatable");
12756 if (lua_isnoneornil(L_, -1)) {
12758 handler(L_, index, type::function, t,
"value is not a function and does not have valid metatable");
12761 lua_getfield(L_, -1, &callkey[0]);
12762 if (lua_isnoneornil(L_, -1)) {
12764 handler(L_, index, type::function, t,
"value's metatable does not have __call overridden in metatable, cannot call this type");
12772 else if constexpr (expected == type::table) {
12773 return stack::loose_table_check(L_, index, std::forward<Handler>(handler), tracking);
12777 const type indextype = type_of(L_, index);
12778 bool success = expected == indextype;
12781 handler(L_, index, expected, indextype,
"");
12788 template <
typename T>
12791 template <
typename T>
12793 template <
typename Handler>
12794 static bool check(
lua_State* L_,
int index, Handler&& handler,
record& tracking) {
12795 const type indextype = type_of(L_, index);
12796 return check(
types<T>(), L_, index, indextype, std::forward<Handler>(handler), tracking);
12799 template <
typename U,
typename Handler>
12803 lightuserdata_value> || std::is_same_v<T, userdata_value> || std::is_same_v<T, userdata> || std::is_same_v<T, lightuserdata>) {
12805 if (indextype != type::userdata) {
12806 handler(L_, index, type::userdata, indextype,
"value is not a valid userdata");
12812 #if SOL_IS_ON(SOL_USE_INTEROP) 12813 if (stack_detail::interop_check<U>(L_, index, indextype, handler, tracking)) {
12816 #endif // interop extensibility 12818 #if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE) 12819 if (lua_iscfunction(L_, index) != 0) {
12824 if (indextype != type::userdata) {
12825 handler(L_, index, type::userdata, indextype,
"value is not a valid userdata");
12828 if (lua_getmetatable(L_, index) == 0) {
12831 int metatableindex = lua_gettop(L_);
12832 if (stack_detail::check_metatable<U>(L_, metatableindex))
12834 if (stack_detail::check_metatable<U*>(L_, metatableindex))
12836 if (stack_detail::check_metatable<
d::u<U>>(L_, metatableindex))
12840 bool success =
false;
12843 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 12844 luaL_checkstack(L_, 1, detail::not_enough_stack_space_string);
12845 #endif // make sure stack doesn't overflow 12846 auto pn = stack::pop_n(L_, 1);
12847 lua_pushstring(L_, &detail::base_class_check_key()[0]);
12848 lua_rawget(L_, metatableindex);
12849 if (type_of(L_, -1) != type::lua_nil) {
12850 void* basecastdata = lua_touserdata(L_, -1);
12851 detail::inheritance_check_function ic =
reinterpret_cast<detail::inheritance_check_function
>(basecastdata);
12857 handler(L_, index, type::userdata, indextype,
"value at this index does not properly reflect the desired type");
12865 template <
typename T>
12867 template <
typename Handler>
12868 static bool check(
lua_State* L_,
int index, type indextype, Handler&& handler,
record& tracking) {
12869 if (indextype == type::lua_nil) {
12873 return check_usertype<std::remove_pointer_t<T>>(L_, index, std::forward<Handler>(handler), tracking);
12876 template <
typename Handler>
12877 static bool check(
lua_State* L_,
int index, Handler&& handler,
record& tracking) {
12878 const type indextype = type_of(L_, index);
12879 return check(L_, index, indextype, std::forward<Handler>(handler), tracking);
12883 template <
typename... Args>
12885 template <
typename Handler>
12886 static bool check(
lua_State* L_,
int index, Handler&& handler,
record& tracking) {
12887 return stack::multi_check<Args...>(L_, index, std::forward<Handler>(handler), tracking);
12891 template <
typename A,
typename B>
12893 template <
typename Handler>
12894 static bool check(
lua_State* L_,
int index, Handler&& handler,
record& tracking) {
12895 return stack::multi_check<A, B>(L_, index, std::forward<Handler>(handler), tracking);
12899 #if SOL_IS_ON(SOL_STD_VARIANT) 12901 template <
typename... Tn>
12903 typedef std::variant<Tn...> V;
12904 typedef std::variant_size<V> V_size;
12905 typedef std::integral_constant<bool, V_size::value == 0> V_is_empty;
12907 template <
typename Handler>
12908 static bool is_one(std::integral_constant<std::size_t, 0>,
lua_State* L_,
int index, Handler&& handler,
record& tracking) {
12909 if constexpr (V_is_empty::value) {
12910 if (lua_isnone(L_, index)) {
12915 handler(L_, index, type::poly, type_of(L_, index),
"value does not fit any type present in the variant");
12919 template <std::
size_t I,
typename Handler>
12920 static bool is_one(std::integral_constant<std::size_t, I>,
lua_State* L_,
int index, Handler&& handler,
record& tracking) {
12921 typedef std::variant_alternative_t<I - 1, V> T;
12922 record temp_tracking = tracking;
12923 if (stack::check<T>(L_, index, &no_panic, temp_tracking)) {
12924 tracking = temp_tracking;
12927 return is_one(std::integral_constant<std::size_t, I - 1>(), L_, index, std::forward<Handler>(handler), tracking);
12930 template <
typename Handler>
12931 static bool check(
lua_State* L_,
int index, Handler&& handler,
record& tracking) {
12932 return is_one(std::integral_constant<std::size_t, V_size::value>(), L_, index, std::forward<Handler>(handler), tracking);
12936 #endif // variant shenanigans 12944 namespace sol {
namespace stack {
12946 template <
typename X, type expected,
typename>
12948 template <
typename Handler>
12949 static bool check(
lua_State* L,
int index, Handler&& handler,
record& tracking) {
12950 using no_cv_X = meta::unqualified_t<X>;
12951 if constexpr (!std::is_reference_v<X> && is_unique_usertype_v<no_cv_X>) {
12952 using element = unique_usertype_element_t<no_cv_X>;
12953 if constexpr (is_actual_type_rebindable_for_v<no_cv_X>) {
12954 using rebound_actual_type = unique_usertype_rebind_actual_t<no_cv_X>;
12957 const type indextype = type_of(L, index);
12959 if (indextype != type::userdata) {
12960 handler(L, index, type::userdata, indextype,
"value is not a userdata");
12963 void* memory = lua_touserdata(L, index);
12964 memory = detail::align_usertype_unique_destructor(memory);
12965 detail::unique_destructor& pdx = *
static_cast<detail::unique_destructor*
>(memory);
12966 if (&detail::usertype_unique_alloc_destroy<element, no_cv_X> == pdx) {
12970 memory = detail::align_usertype_unique_tag<true, false>(memory);
12971 detail::unique_tag& ic = *
reinterpret_cast<detail::unique_tag*
>(memory);
12974 if (ic(
nullptr,
nullptr, ti, rebind_ti) != 0) {
12978 handler(L, index, type::userdata, indextype,
"value is a userdata but is not the correct unique usertype");
12982 return stack::unqualified_check<X>(L, index, std::forward<Handler>(handler), tracking);
12985 else if constexpr (!std::is_reference_v<X> && is_container_v<no_cv_X>) {
12986 if (type_of(L, index) == type::userdata) {
12987 return stack::unqualified_check<X>(L, index, std::forward<Handler>(handler), tracking);
12990 return stack::unqualified_check<nested<X>>(L, index, std::forward<Handler>(handler), tracking);
12993 else if constexpr (!std::is_reference_v<X> && meta::is_specialization_of_v<X, nested>) {
12994 using NestedX =
typename meta::unqualified_t<X>::nested_type;
12995 return stack::check<NestedX>(L, index, ::std::forward<Handler>(handler), tracking);
12998 return stack::unqualified_check<X>(L, index, std::forward<Handler>(handler), tracking);
13017 template <
typename... Functions>
13019 std::tuple<Functions...> functions;
13020 template <
typename Arg,
typename... Args, meta::disable<std::is_same<overload_set, meta::unqualified_t<Arg>>> = meta::enabler>
13021 overload_set(Arg&& arg, Args&&... args) : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) {
13023 overload_set(
const overload_set&) =
default;
13024 overload_set(overload_set&&) =
default;
13025 overload_set& operator=(
const overload_set&) =
default;
13026 overload_set& operator=(overload_set&&) =
default;
13029 template <
typename... Args>
13030 decltype(
auto) overload(Args&&... args) {
13045 namespace unicode {
13046 enum class error_code {
13048 invalid_code_point,
13050 invalid_leading_surrogate,
13051 invalid_trailing_surrogate,
13052 sequence_too_short,
13056 inline const string_view& to_string(error_code ec) {
13057 static const string_view storage[7] = {
"ok",
13058 "invalid code points",
13059 "invalid code unit",
13060 "invalid leading surrogate",
13061 "invalid trailing surrogate",
13062 "sequence too short",
13063 "overlong sequence" };
13064 return storage[
static_cast<std::size_t
>(ec)];
13067 template <
typename It>
13070 char32_t codepoint;
13074 template <
typename C>
13077 std::size_t code_units_size;
13078 std::array<C, 4> code_units;
13083 static constexpr char32_t last_code_point = 0x10FFFF;
13085 static constexpr char32_t first_lead_surrogate = 0xD800;
13086 static constexpr char32_t last_lead_surrogate = 0xDBFF;
13088 static constexpr char32_t first_trail_surrogate = 0xDC00;
13089 static constexpr char32_t last_trail_surrogate = 0xDFFF;
13091 static constexpr char32_t first_surrogate = first_lead_surrogate;
13092 static constexpr char32_t last_surrogate = last_trail_surrogate;
13094 static constexpr
bool is_lead_surrogate(char32_t u) {
13095 return u >= first_lead_surrogate && u <= last_lead_surrogate;
13097 static constexpr
bool is_trail_surrogate(char32_t u) {
13098 return u >= first_trail_surrogate && u <= last_trail_surrogate;
13100 static constexpr
bool is_surrogate(char32_t u) {
13101 return u >= first_surrogate && u <= last_surrogate;
13105 static constexpr
auto last_1byte_value = 0x7Fu;
13106 static constexpr
auto last_2byte_value = 0x7FFu;
13107 static constexpr
auto last_3byte_value = 0xFFFFu;
13109 static constexpr
auto start_2byte_mask = 0x80u;
13110 static constexpr
auto start_3byte_mask = 0xE0u;
13111 static constexpr
auto start_4byte_mask = 0xF0u;
13113 static constexpr
auto continuation_mask = 0xC0u;
13114 static constexpr
auto continuation_signature = 0x80u;
13116 static constexpr
bool is_invalid(
unsigned char b) {
13117 return b == 0xC0 || b == 0xC1 || b > 0xF4;
13120 static constexpr
bool is_continuation(
unsigned char b) {
13121 return (b & unicode_detail::continuation_mask) == unicode_detail::continuation_signature;
13124 static constexpr
bool is_overlong(char32_t u, std::size_t bytes) {
13125 return u <= unicode_detail::last_1byte_value || (u <= unicode_detail::last_2byte_value && bytes > 2)
13126 || (u <= unicode_detail::last_3byte_value && bytes > 3);
13129 static constexpr
int sequence_length(
unsigned char b) {
13130 return (b & start_2byte_mask) == 0 ? 1
13131 : (b & start_3byte_mask) != start_3byte_mask ? 2
13132 : (b & start_4byte_mask) != start_4byte_mask ? 3
13136 static constexpr char32_t decode(
unsigned char b0,
unsigned char b1) {
13137 return (static_cast<char32_t>((b0 & 0x1Fu) << 6u) | static_cast<char32_t>(b1 & 0x3Fu));
13139 static constexpr char32_t decode(
unsigned char b0,
unsigned char b1,
unsigned char b2) {
13140 return static_cast<char32_t
>((b0 & 0x0Fu) << 12u) |
static_cast<char32_t
>((b1 & 0x3Fu) << 6u) |
static_cast<char32_t
>(b2 & 0x3Fu);
13142 static constexpr char32_t decode(
unsigned char b0,
unsigned char b1,
unsigned char b2,
unsigned char b3) {
13143 return static_cast<char32_t
>(
static_cast<char32_t
>((b0 & 0x07u) << 18u) |
static_cast<char32_t
>((b1 & 0x3F) << 12)
13144 |
static_cast<char32_t
>((b2 & 0x3Fu) << 6u) |
static_cast<char32_t
>(b3 & 0x3Fu));
13148 static constexpr char32_t last_bmp_value = 0xFFFF;
13149 static constexpr char32_t normalizing_value = 0x10000;
13150 static constexpr
int lead_surrogate_bitmask = 0xFFC00;
13151 static constexpr
int trail_surrogate_bitmask = 0x3FF;
13152 static constexpr
int lead_shifted_bits = 10;
13153 static constexpr char32_t replacement = 0xFFFD;
13155 static char32_t combine_surrogates(char16_t lead, char16_t trail) {
13156 auto hi = lead - first_lead_surrogate;
13157 auto lo = trail - first_trail_surrogate;
13158 return normalizing_value + ((hi << lead_shifted_bits) | lo);
13164 er.error = error_code::ok;
13165 if (codepoint <= unicode_detail::last_1byte_value) {
13166 er.code_units_size = 1;
13167 er.code_units = std::array<char, 4> { {
static_cast<char>(codepoint) } };
13169 else if (codepoint <= unicode_detail::last_2byte_value) {
13170 er.code_units_size = 2;
13171 er.code_units = std::array<char, 4> { {
13172 static_cast<char>(0xC0 | ((codepoint & 0x7C0) >> 6)),
13173 static_cast<char>(0x80 | (codepoint & 0x3F)),
13176 else if (codepoint <= unicode_detail::last_3byte_value) {
13177 er.code_units_size = 3;
13178 er.code_units = std::array<char, 4> { {
13179 static_cast<char>(0xE0 | ((codepoint & 0xF000) >> 12)),
13180 static_cast<char>(0x80 | ((codepoint & 0xFC0) >> 6)),
13181 static_cast<char>(0x80 | (codepoint & 0x3F)),
13185 er.code_units_size = 4;
13186 er.code_units = std::array<char, 4> { {
13187 static_cast<char>(0xF0 | ((codepoint & 0x1C0000) >> 18)),
13188 static_cast<char>(0x80 | ((codepoint & 0x3F000) >> 12)),
13189 static_cast<char>(0x80 | ((codepoint & 0xFC0) >> 6)),
13190 static_cast<char>(0x80 | (codepoint & 0x3F)),
13199 if (codepoint <= unicode_detail::last_bmp_value) {
13200 er.code_units_size = 1;
13201 er.code_units = std::array<char16_t, 4> { {
static_cast<char16_t
>(codepoint) } };
13202 er.error = error_code::ok;
13205 auto normal = codepoint - unicode_detail::normalizing_value;
13206 auto lead = unicode_detail::first_lead_surrogate + ((normal & unicode_detail::lead_surrogate_bitmask) >> unicode_detail::lead_shifted_bits);
13207 auto trail = unicode_detail::first_trail_surrogate + (normal & unicode_detail::trail_surrogate_bitmask);
13208 er.code_units = std::array<char16_t, 4> { {
static_cast<char16_t
>(lead), static_cast<char16_t>(trail) } };
13209 er.code_units_size = 2;
13210 er.error = error_code::ok;
13217 er.code_units_size = 1;
13218 er.code_units[0] = codepoint;
13219 er.error = error_code::ok;
13223 template <
typename It>
13228 dr.error = error_code::sequence_too_short;
13232 unsigned char b0 =
static_cast<unsigned char>(*it);
13233 std::size_t length =
static_cast<std::size_t
>(unicode_detail::sequence_length(b0));
13236 dr.codepoint =
static_cast<char32_t
>(b0);
13237 dr.error = error_code::ok;
13243 if (unicode_detail::is_invalid(b0) || unicode_detail::is_continuation(b0)) {
13244 dr.error = error_code::invalid_code_unit;
13250 std::array<unsigned char, 4> b;
13252 for (std::size_t i = 1; i < length; ++i) {
13253 b[i] =
static_cast<unsigned char>(*it);
13254 if (!unicode_detail::is_continuation(b[i])) {
13255 dr.error = error_code::invalid_code_unit;
13265 decoded = unicode_detail::decode(b[0], b[1]);
13268 decoded = unicode_detail::decode(b[0], b[1], b[2]);
13271 decoded = unicode_detail::decode(b[0], b[1], b[2], b[3]);
13275 if (unicode_detail::is_overlong(decoded, length)) {
13276 dr.error = error_code::overlong_sequence;
13279 if (unicode_detail::is_surrogate(decoded) || decoded > unicode_detail::last_code_point) {
13280 dr.error = error_code::invalid_code_point;
13285 dr.codepoint = decoded;
13286 dr.error = error_code::ok;
13291 template <
typename It>
13296 dr.error = error_code::sequence_too_short;
13300 char16_t lead =
static_cast<char16_t
>(*it);
13302 if (!unicode_detail::is_surrogate(lead)) {
13304 dr.codepoint =
static_cast<char32_t
>(lead);
13306 dr.error = error_code::ok;
13309 if (!unicode_detail::is_lead_surrogate(lead)) {
13310 dr.error = error_code::invalid_leading_surrogate;
13317 if (!unicode_detail::is_trail_surrogate(trail)) {
13318 dr.error = error_code::invalid_trailing_surrogate;
13323 dr.codepoint = unicode_detail::combine_surrogates(lead, trail);
13325 dr.error = error_code::ok;
13329 template <
typename It>
13334 dr.error = error_code::sequence_too_short;
13337 dr.codepoint =
static_cast<char32_t
>(*it);
13339 dr.error = error_code::ok;
13347 #include <functional> 13351 #include <string_view> 13352 #if SOL_IS_ON(SOL_STD_VARIANT) 13354 #endif // Apple clang screwed up 13356 namespace sol {
namespace stack {
13358 namespace stack_detail {
13359 template <
typename Ch>
13361 std::size_t needed_size;
13367 needed_size += er.code_units_size;
13371 template <
typename Ch,
typename ErCh>
13379 std::memcpy(target_, er.code_units.data(), er.code_units_size *
sizeof(ErCh));
13380 target_ += er.code_units_size;
13384 template <
typename Ch,
typename F>
13385 inline void convert(
const char* strb,
const char* stre, F&& f) {
13387 for (
const char* strtarget = strb; strtarget < stre;) {
13388 auto dr = unicode::utf8_to_code_point(strtarget, stre);
13389 if (dr.error != unicode::error_code::ok) {
13390 cp = unicode::unicode_detail::replacement;
13395 strtarget = dr.next;
13397 if constexpr (std::is_same_v<Ch, char32_t>) {
13398 auto er = unicode::code_point_to_utf32(cp);
13402 auto er = unicode::code_point_to_utf16(cp);
13408 template <
typename BaseCh,
typename S>
13410 using Ch =
typename S::value_type;
13413 auto utf8p = lua_tolstring(L, index, &len);
13416 const char* strb = utf8p;
13417 const char* stre = utf8p + len;
13419 convert<BaseCh>(strb, stre, count_units);
13420 S r(count_units.needed_size, static_cast<Ch>(0));
13421 r.resize(count_units.needed_size);
13422 Ch* target = &r[0];
13424 convert<BaseCh>(strb, stre, copy_units);
13429 template <
typename T,
typename>
13431 static decltype(
auto)
get(
lua_State* L,
int index,
record& tracking) {
13432 if constexpr (std::is_same_v<T, bool>) {
13434 return lua_toboolean(L, index) != 0;
13436 else if constexpr (std::is_enum_v<T>) {
13438 return static_cast<T
>(lua_tointegerx(L, index,
nullptr));
13440 else if constexpr (std::is_integral_v<T> || std::is_same_v<T, lua_Integer>) {
13442 #if SOL_LUA_VERSION_I_ >= 503 13443 if (lua_isinteger(L, index) != 0) {
13444 return static_cast<T
>(lua_tointeger(L, index));
13447 return static_cast<T
>(llround(lua_tonumber(L, index)));
13449 else if constexpr (std::is_floating_point_v<T> || std::is_same_v<T, lua_Number>) {
13451 return static_cast<T
>(lua_tonumber(L, index));
13453 else if constexpr (is_lua_reference_v<T>) {
13454 if constexpr (is_global_table_v<T>) {
13456 return T(L, global_tag);
13460 return T(L, index);
13463 else if constexpr (is_unique_usertype_v<T>) {
13464 using actual = unique_usertype_actual_t<T>;
13467 void* memory = lua_touserdata(L, index);
13468 void* aligned_memory = detail::align_usertype_unique<actual>(memory);
13469 actual* typed_memory =
static_cast<actual*
>(aligned_memory);
13470 return *typed_memory;
13472 else if constexpr (meta::is_optional_v<T>) {
13473 using ValueType =
typename T::value_type;
13476 else if constexpr (std::is_same_v<T, luaL_Stream*>) {
13480 else if constexpr (std::is_same_v<T, luaL_Stream>) {
13484 #if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE) 13485 else if constexpr (std::is_function_v<T> || (std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>>)) {
13486 return stack_detail::get_function_pointer<std::remove_pointer_t<T>>(L, index, tracking);
13490 return stack_detail::unchecked_unqualified_get<detail::as_value_tag<T>>(L, index, tracking);
13495 template <
typename X,
typename>
13497 static decltype(
auto)
get(
lua_State* L,
int index,
record& tracking) {
13498 using Tu = meta::unqualified_t<X>;
13499 static constexpr
bool is_userdata_of_some_kind
13500 = !std::is_reference_v<
13501 X> && is_container_v<Tu> && std::is_default_constructible_v<Tu> && !is_lua_primitive_v<Tu> && !is_transparent_argument_v<Tu>;
13502 if constexpr (is_userdata_of_some_kind) {
13503 if (type_of(L, index) == type::userdata) {
13504 return static_cast<Tu
>(stack_detail::unchecked_unqualified_get<Tu>(L, index, tracking));
13507 return stack_detail::unchecked_unqualified_get<sol::nested<Tu>>(L, index, tracking);
13510 else if constexpr (!std::is_reference_v<X> && is_unique_usertype_v<Tu> && !is_actual_type_rebindable_for_v<Tu>) {
13511 using element = unique_usertype_element_t<Tu>;
13512 using actual = unique_usertype_actual_t<Tu>;
13514 void* memory = lua_touserdata(L, index);
13515 memory = detail::align_usertype_unique_destructor(memory);
13516 detail::unique_destructor& pdx = *
static_cast<detail::unique_destructor*
>(memory);
13517 if (&detail::usertype_unique_alloc_destroy<element, Tu> == pdx) {
13518 memory = detail::align_usertype_unique_tag<true, false>(memory);
13519 memory = detail::align_usertype_unique<actual, true, false>(memory);
13520 actual* mem =
static_cast<actual*
>(memory);
13521 return static_cast<actual
>(*mem);
13525 #if SOL_IS_ON(SOL_DEBUG_BUILD) 13530 return static_cast<actual
>(std::move(r));
13533 memory = detail::align_usertype_unique_tag<true, false>(memory);
13534 detail::unique_tag& ic = *
reinterpret_cast<detail::unique_tag*
>(memory);
13535 memory = detail::align_usertype_unique<actual, true, false>(memory);
13537 int cast_operation;
13538 if constexpr (is_actual_type_rebindable_for_v<Tu>) {
13539 using rebound_actual_type = unique_usertype_rebind_actual_t<Tu, void>;
13541 cast_operation = ic(memory, &r, ti, rebind_ti);
13544 string_view rebind_ti(
"");
13545 cast_operation = ic(memory, &r, ti, rebind_ti);
13547 switch (cast_operation) {
13551 actual* mem =
static_cast<actual*
>(memory);
13552 return static_cast<actual
>(*mem);
13557 return static_cast<actual
>(std::move(r));
13562 #if SOL_IS_ON(SOL_DEBUG_BUILD) 13567 return static_cast<actual
>(r);
13571 return stack_detail::unchecked_unqualified_get<Tu>(L, index, tracking);
13576 template <
typename T>
13578 using Tu = meta::unqualified_t<T>;
13580 template <
typename V>
13581 static void push_back_at_end(std::true_type,
types<V>,
lua_State* L, T& cont, std::size_t) {
13585 template <
typename V>
13586 static void push_back_at_end(std::false_type,
types<V> t,
lua_State* L, T& cont, std::size_t idx) {
13587 insert_at_end(meta::has_insert<Tu>(), t, L, cont, idx);
13590 template <
typename V>
13591 static void insert_at_end(std::true_type,
types<V>,
lua_State* L, T& cont, std::size_t) {
13596 template <
typename V>
13597 static void insert_at_end(std::false_type,
types<V>,
lua_State* L, T& cont, std::size_t idx) {
13601 static bool max_size_check(std::false_type, T&, std::size_t) {
13605 static bool max_size_check(std::true_type, T& cont, std::size_t idx) {
13606 return idx >= cont.max_size();
13613 static T
get(std::false_type,
lua_State* L,
int relindex,
record& tracking) {
13614 typedef typename Tu::value_type V;
13615 return get(
types<V>(), L, relindex, tracking);
13618 template <
typename V>
13656 int index = lua_absindex(L, relindex);
13658 std::size_t idx = 0;
13659 #if SOL_LUA_VERSION_I_ >= 503 13664 if (max_size_check(meta::has_max_size<Tu>(), cont, idx)) {
13668 bool isnil =
false;
13669 for (
int vi = 0; vi < lua_size<V>::value; ++vi) {
13670 #if SOL_IS_ON(SOL_LUA_NIL_IN_TABLES) && SOL_LUA_VERSION_I_ >= 600 13671 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 13672 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
13673 #endif // make sure stack doesn't overflow 13674 lua_pushinteger(L, static_cast<lua_Integer>(i + vi));
13675 if (lua_keyin(L, index) == 0) {
13681 lua_geti(L, index, i + vi);
13684 type vt =
static_cast<type
>(lua_geti(L, index, i + vi));
13685 isnil = vt == type::none || vt == type::lua_nil;
13691 #if SOL_IS_ON(SOL_LUA_NIL_IN_TABLES) && SOL_LUA_VERSION_I_ >= 600 13694 lua_pop(L, (vi + 1));
13701 #if SOL_IS_ON(SOL_LUA_NIL_IN_TABLES) && SOL_LUA_VERSION_I_ >= 600 13708 push_back_at_end(meta::has_push_back<Tu>(), t, L, cont, idx);
13715 if (idx >= cont.max_size()) {
13719 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 13720 luaL_checkstack(L, 2, detail::not_enough_stack_space_generic);
13721 #endif // make sure stack doesn't overflow 13722 bool isnil =
false;
13723 for (
int vi = 0; vi < lua_size<V>::value; ++vi) {
13724 lua_pushinteger(L, i);
13725 lua_gettable(L, index);
13726 type vt = type_of(L, -1);
13727 isnil = vt == type::lua_nil;
13732 lua_pop(L, (vi + 1));
13739 push_back_at_end(meta::has_push_back<Tu>(), t, L, cont, idx);
13747 static T
get(std::true_type,
lua_State* L,
int index,
record& tracking) {
13748 typedef typename Tu::value_type P;
13749 typedef typename P::first_type K;
13750 typedef typename P::second_type V;
13754 template <
typename K,
typename V>
13758 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 13759 luaL_checkstack(L, 3, detail::not_enough_stack_space_generic);
13760 #endif // make sure stack doesn't overflow 13763 int index = lua_absindex(L, relindex);
13765 while (lua_next(L, index) != 0) {
13766 decltype(
auto) key = stack::check_get<K>(L, -2);
13771 associative.emplace(std::forward<decltype(*key)>(*key), stack::get<V>(L, -1));
13774 return associative;
13778 template <
typename T,
typename Al>
13780 typedef std::forward_list<T, Al> C;
13786 static C
get(std::true_type,
lua_State* L,
int index,
record& tracking) {
13787 typedef typename T::value_type P;
13788 typedef typename P::first_type K;
13789 typedef typename P::second_type V;
13793 static C
get(std::false_type,
lua_State* L,
int relindex,
record& tracking) {
13794 typedef typename C::value_type V;
13795 return get(
types<V>(), L, relindex, tracking);
13798 template <
typename V>
13801 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 13802 luaL_checkstack(L, 3, detail::not_enough_stack_space_generic);
13803 #endif // make sure stack doesn't overflow 13805 int index = lua_absindex(L, relindex);
13807 auto at = cont.cbefore_begin();
13808 std::size_t idx = 0;
13809 #if SOL_LUA_VERSION_I_ >= 503 13812 if (idx >= cont.max_size()) {
13815 bool isnil =
false;
13816 for (
int vi = 0; vi < lua_size<V>::value; ++vi) {
13817 type t =
static_cast<type
>(lua_geti(L, index, i + vi));
13818 isnil = t == type::lua_nil;
13823 lua_pop(L, (vi + 1));
13835 if (idx >= cont.max_size()) {
13838 bool isnil =
false;
13839 for (
int vi = 0; vi < lua_size<V>::value; ++vi) {
13840 lua_pushinteger(L, i);
13841 lua_gettable(L, index);
13842 type t = type_of(L, -1);
13843 isnil = t == type::lua_nil;
13848 lua_pop(L, (vi + 1));
13862 template <
typename K,
typename V>
13866 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 13867 luaL_checkstack(L, 3, detail::not_enough_stack_space_generic);
13868 #endif // make sure stack doesn't overflow 13871 auto at = associative.cbefore_begin();
13872 int index = lua_absindex(L, relindex);
13874 while (lua_next(L, index) != 0) {
13875 decltype(
auto) key = stack::check_get<K>(L, -2);
13880 at = associative.emplace_after(at, std::forward<decltype(*key)>(*key), stack::get<V>(L, -1));
13883 return associative;
13887 template <
typename T>
13890 using Tu = meta::unqualified_t<T>;
13891 if constexpr (is_container_v<Tu>) {
13893 typedef typename T::value_type P;
13894 typedef typename P::first_type K;
13895 typedef typename P::second_type V;
13900 typedef typename T::value_type V;
13907 return g.get(L, index, tracking);
13912 template <
typename T>
13914 static decltype(
auto)
get(
lua_State* L,
int index,
record& tracking) {
13915 return stack::unqualified_get<T>(L, index, tracking);
13919 template <
typename T>
13921 static decltype(
auto)
get(
lua_State* L,
int index,
record& tracking) {
13922 return stack::unqualified_get<T*>(L, index, tracking);
13942 template <
typename T>
13946 void* memory = lua_touserdata(L, index);
13947 return light<T>(
static_cast<T*
>(memory));
13951 template <
typename T>
13953 static std::add_lvalue_reference_t<T>
get(
lua_State* L,
int index,
record& tracking) {
13955 void* memory = lua_touserdata(L, index);
13956 memory = detail::align_user<T>(memory);
13957 return *
static_cast<std::remove_reference_t<T>*
>(memory);
13961 template <
typename T>
13965 void* memory = lua_touserdata(L, index);
13966 memory = detail::align_user<T*>(memory);
13967 return static_cast<T*
>(memory);
13975 return static_cast<type
>(lua_type(L, index));
13984 auto str = lua_tolstring(L, index, &len);
13985 return std::string(str, len);
13994 return lua_tolstring(L, index, &sz);
14003 auto str = lua_tolstring(L, index, &len);
14004 return len > 0 ? str[0] :
'\0';
14008 template <
typename Traits>
14013 const char* str = lua_tolstring(L, index, &sz);
14014 return basic_string_view<char, Traits>(str, sz);
14018 template <
typename Traits,
typename Al>
14020 using S = std::basic_string<wchar_t, Traits, Al>;
14022 using Ch = meta::conditional_t<sizeof(wchar_t) == 2, char16_t, char32_t>;
14023 return stack_detail::get_into<Ch, S>(L, index, tracking);
14027 template <
typename Traits,
typename Al>
14029 static std::basic_string<char16_t, Traits, Al>
get(
lua_State* L,
int index,
record& tracking) {
14030 return stack_detail::get_into<char16_t, std::basic_string<char16_t, Traits, Al>>(L, index, tracking);
14034 template <
typename Traits,
typename Al>
14036 static std::basic_string<char32_t, Traits, Al>
get(
lua_State* L,
int index,
record& tracking) {
14037 return stack_detail::get_into<char32_t, std::basic_string<char32_t, Traits, Al>>(L, index, tracking);
14044 string_view utf8 = stack::get<string_view>(L, index, tracking);
14045 const char* strb = utf8.data();
14046 const char* stre = utf8.data() + utf8.size();
14048 auto dr = unicode::utf8_to_code_point(strb, stre);
14049 if (dr.error != unicode::error_code::ok) {
14050 cp = unicode::unicode_detail::replacement;
14055 auto er = unicode::code_point_to_utf16(cp);
14056 return er.code_units[0];
14063 string_view utf8 = stack::get<string_view>(L, index, tracking);
14064 const char* strb = utf8.data();
14065 const char* stre = utf8.data() + utf8.size();
14067 auto dr = unicode::utf8_to_code_point(strb, stre);
14068 if (dr.error != unicode::error_code::ok) {
14069 cp = unicode::unicode_detail::replacement;
14074 auto er = unicode::code_point_to_utf32(cp);
14075 return er.code_units[0];
14082 typedef meta::conditional_t<sizeof(wchar_t) == 2, char16_t, char32_t> Ch;
14085 auto c = g.get(L, index, tracking);
14086 return static_cast<wchar_t>(c);
14092 static meta_function
get(
lua_State* L,
int index,
record& tracking) {
14095 const auto& mfnames = meta_function_names();
14096 for (std::size_t i = 0; i < mfnames.size(); ++i)
14097 if (mfnames[i] == name)
14098 return static_cast<meta_function
>(i);
14099 return meta_function::construct;
14145 static lua_CFunction
get(
lua_State* L,
int index,
record& tracking) {
14147 return lua_tocfunction(L, index);
14155 return c_closure(lua_tocfunction(L, index), -1);
14164 const char* err = lua_tolstring(L, index, &sz);
14165 if (err ==
nullptr) {
14166 return error(detail::direct_error,
"");
14168 return error(detail::direct_error, std::string(err, sz));
14176 return lua_touserdata(L, index);
14184 return lua_touserdata(L, index);
14188 template <
typename T>
14190 static T* get_no_lua_nil(
lua_State* L,
int index,
record& tracking) {
14191 void* memory = lua_touserdata(L, index);
14192 #if SOL_IS_ON(SOL_USE_INTEROP) 14193 auto ugr = stack_detail::interop_get<T>(L, index, memory, tracking);
14197 #endif // interop extensibility 14199 void* rawdata = detail::align_usertype_pointer(memory);
14200 void** pudata =
static_cast<void**
>(rawdata);
14201 void* udata = *pudata;
14202 return get_no_lua_nil_from(L, udata, index, tracking);
14205 static T* get_no_lua_nil_from(
lua_State* L,
void* udata,
int index,
record&) {
14208 if (lua_getmetatable(L, index) == 1) {
14209 lua_getfield(L, -1, &detail::base_class_cast_key()[0]);
14210 if (type_of(L, -1) != type::lua_nil) {
14211 void* basecastdata = lua_touserdata(L, -1);
14212 detail::inheritance_cast_function ic =
reinterpret_cast<detail::inheritance_cast_function
>(basecastdata);
14219 if constexpr (std::is_function_v<T>) {
14220 T* func =
reinterpret_cast<T*
>(udata);
14224 T* obj =
static_cast<T*
>(udata);
14230 return *get_no_lua_nil(L, index, tracking);
14234 template <
typename T>
14237 type t = type_of(L, index);
14238 if (t == type::lua_nil) {
14243 return g.get_no_lua_nil(L, index, tracking);
14247 template <
typename T>
14251 return g.get_no_lua_nil(L, index, tracking);
14255 template <
typename T>
14259 return g.get(L, index, tracking);
14263 template <
typename T>
14267 return g.get(L, index, tracking);
14271 template <
typename T>
14274 #if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE) 14275 if constexpr (std::is_function_v<T>) {
14276 return stack_detail::get_function_pointer<T>(L, index, tracking);
14280 return g.get(L, index, tracking);
14284 return g.get(L, index, tracking);
14289 template <
typename... Tn>
14291 typedef std::tuple<decltype(stack::get<Tn>(
nullptr, 0))...> R;
14293 template <
typename... Args>
14294 static R apply(std::index_sequence<>,
lua_State*,
int,
record&, Args&&... args) {
14296 return R { std::forward<Args>(args)... };
14299 template <std::size_t I, std::size_t... Ix,
typename... Args>
14300 static R apply(std::index_sequence<I, Ix...>,
lua_State* L,
int index,
record& tracking, Args&&... args) {
14302 typedef std::tuple_element_t<I, std::tuple<Tn...>> T;
14303 return apply(std::index_sequence<Ix...>(), L, index, tracking, std::forward<Args>(args)..., stack::get<T>(L, index + tracking.used, tracking));
14307 return apply(std::make_index_sequence<
sizeof...(Tn)>(), L, index, tracking);
14311 template <
typename A,
typename B>
14313 static decltype(
auto)
get(
lua_State* L,
int index,
record& tracking) {
14314 return std::pair<decltype(stack::get<A>(L, index)), decltype(stack::get<B>(L, index))> { stack::get<A>(L, index, tracking),
14315 stack::get<B>(L, index + tracking.used, tracking) };
14319 #if SOL_IS_ON(SOL_STD_VARIANT) 14321 template <
typename... Tn>
14323 using V = std::variant<Tn...>;
14325 static V get_one(std::integral_constant<std::size_t, std::variant_size_v<V>>,
lua_State* L,
int index,
record& tracking) {
14329 if constexpr (std::variant_size_v<V> == 0) {
14339 template <std::
size_t I>
14340 static V get_one(std::integral_constant<std::size_t, I>,
lua_State* L,
int index,
record& tracking) {
14341 typedef std::variant_alternative_t<I, V> T;
14342 record temp_tracking = tracking;
14343 if (stack::check<T>(L, index, &no_panic, temp_tracking)) {
14344 tracking = temp_tracking;
14345 return V(std::in_place_index<I>, stack::get<T>(L, index));
14347 return get_one(std::integral_constant<std::size_t, I + 1>(), L, index, tracking);
14351 return get_one(std::integral_constant<std::size_t, 0>(), L, index, tracking);
14362 namespace sol {
namespace stack {
14380 #include <optional> 14381 #if SOL_IS_ON(SOL_STD_VARIANT) 14383 #endif // variant shenanigans (thanks, Mac OSX) 14385 namespace sol {
namespace stack {
14386 template <
typename T,
typename>
14388 typedef decltype(stack_detail::unchecked_unqualified_get<T>(
nullptr, -1, std::declval<record&>())) R;
14390 template <
typename Optional,
typename Handler>
14391 static Optional get_using(
lua_State* L,
int index, Handler&& handler,
record& tracking) {
14392 if constexpr (!meta::meta_detail::is_adl_sol_lua_check_v<T> && !meta::meta_detail::is_adl_sol_lua_get_v<T>) {
14393 if constexpr (is_lua_reference_v<T>) {
14394 if constexpr (is_global_table_v<T>) {
14404 bool success = lua_isnoneornil(L, index) == 0 && stack::check<T>(L, index, &no_panic);
14407 tracking.use(static_cast<int>(success));
14408 handler(L, index, type::poly, type_of(L, index),
"");
14409 return detail::associated_nullopt_v<Optional>;
14411 return stack_detail::unchecked_get<T>(L, index, tracking);
14414 else if constexpr ((std::is_integral_v<T> || std::is_same_v<T, lua_Integer>)&&!std::is_same_v<T, bool>) {
14415 #if SOL_LUA_VERSION_I_ >= 503 14416 if (lua_isinteger(L, index) != 0) {
14418 return static_cast<T
>(lua_tointeger(L, index));
14422 const lua_Number value = lua_tonumberx(L, index, &isnum);
14424 #if SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS) 14425 const auto integer_value = llround(value);
14426 if (static_cast<lua_Number>(integer_value) == value) {
14428 return static_cast<T
>(integer_value);
14432 return static_cast<T
>(value);
14435 const type t = type_of(L, index);
14436 tracking.use(static_cast<int>(t != type::none));
14437 handler(L, index, type::number, t,
"not an integer");
14438 return detail::associated_nullopt_v<Optional>;
14440 else if constexpr (std::is_floating_point_v<T> || std::is_same_v<T, lua_Number>) {
14442 lua_Number value = lua_tonumberx(L, index, &isnum);
14444 type t = type_of(L, index);
14445 tracking.use(static_cast<int>(t != type::none));
14446 handler(L, index, type::number, t,
"not a valid floating point number");
14447 return detail::associated_nullopt_v<Optional>;
14450 return static_cast<T
>(value);
14452 else if constexpr (std::is_enum_v<T> && !meta::any_same_v<T, meta_function, type>) {
14454 lua_Integer value = lua_tointegerx(L, index, &isnum);
14456 type t = type_of(L, index);
14457 tracking.use(static_cast<int>(t != type::none));
14458 handler(L, index, type::number, t,
"not a valid enumeration value");
14459 return detail::associated_nullopt_v<Optional>;
14462 return static_cast<T
>(value);
14465 if (!unqualified_check<T>(L, index, std::forward<Handler>(handler))) {
14466 tracking.use(static_cast<int>(!lua_isnone(L, index)));
14467 return detail::associated_nullopt_v<Optional>;
14469 return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
14473 if (!unqualified_check<T>(L, index, std::forward<Handler>(handler))) {
14474 tracking.use(static_cast<int>(!lua_isnone(L, index)));
14475 return detail::associated_nullopt_v<Optional>;
14477 return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
14481 template <
typename Handler>
14483 return get_using<optional<R>>(L, index, std::forward<Handler>(handler), tracking);
14487 #if SOL_IS_ON(SOL_STD_VARIANT) 14488 template <
typename... Tn,
typename C>
14490 typedef std::variant<Tn...> V;
14491 typedef std::variant_size<V> V_size;
14492 typedef std::integral_constant<bool, V_size::value == 0> V_is_empty;
14494 template <
typename Handler>
14499 template <
typename Handler>
14505 L, index, type::poly, type_of(L, index),
"this variant code should never be reached: if it has, you have done something so terribly wrong");
14509 template <
typename Handler>
14510 static optional<V> get_one(std::integral_constant<std::size_t, 0>,
lua_State* L,
int index, Handler&& handler,
record& tracking) {
14511 return get_empty(V_is_empty(), L, index, std::forward<Handler>(handler), tracking);
14514 template <std::
size_t I,
typename Handler>
14515 static optional<V> get_one(std::integral_constant<std::size_t, I>,
lua_State* L,
int index, Handler&& handler,
record& tracking) {
14516 typedef std::variant_alternative_t<I - 1, V> T;
14517 if (stack::check<T>(L, index, &no_panic, tracking)) {
14518 return V(std::in_place_index<I - 1>, stack::get<T>(L, index));
14520 return get_one(std::integral_constant<std::size_t, I - 1>(), L, index, std::forward<Handler>(handler), tracking);
14523 template <
typename Handler>
14525 return get_one(std::integral_constant<std::size_t, V_size::value>(), L, index, std::forward<Handler>(handler), tracking);
14528 #endif // standard variant 14535 namespace sol {
namespace stack {
14537 #if SOL_IS_ON(SOL_COMPILER_GCC) 14538 #pragma GCC diagnostic push 14539 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 14542 namespace stack_detail {
14543 template <
typename OptionalType,
typename T,
typename Handler>
14544 OptionalType get_optional(
lua_State* L,
int index, Handler&& handler,
record& tracking) {
14545 using Tu = meta::unqualified_t<T>;
14547 if constexpr (is_lua_reference_v<T>) {
14548 if constexpr (is_global_table_v<Tu>) {
14558 bool success = lua_isnoneornil(L, index) == 0 && stack::check<T>(L, index, &no_panic);
14561 tracking.use(static_cast<int>(success));
14562 handler(L, index, type::poly, type_of(L, index),
"");
14565 return OptionalType(stack_detail::unchecked_get<T>(L, index, tracking));
14568 else if constexpr (!std::is_reference_v<T> && is_unique_usertype_v<Tu> && !is_actual_type_rebindable_for_v<Tu>) {
14570 using element = unique_usertype_element_t<Tu>;
14571 using actual = unique_usertype_actual_t<Tu>;
14573 void* memory = lua_touserdata(L, index);
14574 memory = detail::align_usertype_unique_destructor(memory);
14575 detail::unique_destructor& pdx = *
static_cast<detail::unique_destructor*
>(memory);
14576 if (&detail::usertype_unique_alloc_destroy<element, Tu> == pdx) {
14577 memory = detail::align_usertype_unique_tag<true, false>(memory);
14578 memory = detail::align_usertype_unique<actual, true, false>(memory);
14579 actual* mem =
static_cast<actual*
>(memory);
14580 return static_cast<actual
>(*mem);
14583 return OptionalType();
14586 memory = detail::align_usertype_unique_tag<true, false>(memory);
14587 detail::unique_tag& ic = *
reinterpret_cast<detail::unique_tag*
>(memory);
14588 memory = detail::align_usertype_unique<actual, true, false>(memory);
14590 int cast_operation;
14592 if constexpr (is_actual_type_rebindable_for_v<Tu>) {
14593 using rebound_actual_type = unique_usertype_rebind_actual_t<Tu, void>;
14595 cast_operation = ic(memory, &r, ti, rebind_ti);
14598 string_view rebind_ti(
"");
14599 cast_operation = ic(memory, &r, ti, rebind_ti);
14601 switch (cast_operation) {
14605 actual* mem =
static_cast<actual*
>(memory);
14606 return OptionalType(*mem);
14611 return OptionalType(std::move(r));
14615 return OptionalType();
14619 if (!check<T>(L, index, std::forward<Handler>(handler))) {
14620 tracking.use(static_cast<int>(!lua_isnone(L, index)));
14621 return OptionalType();
14623 return OptionalType(stack_detail::unchecked_get<T>(L, index, tracking));
14628 #if SOL_IS_ON(SOL_COMPILER_GCC) 14629 #pragma GCC diagnostic pop 14632 template <
typename T,
typename>
14634 typedef decltype(stack_detail::unchecked_get<T>(
nullptr, -1, std::declval<record&>())) R;
14636 template <
typename Handler>
14638 return stack_detail::get_optional<optional<R>, T>(L, index, std::forward<Handler>(handler), tracking);
14642 template <
typename Optional>
14645 using T =
typename meta::unqualified_t<Optional>::value_type;
14646 return stack_detail::get_optional<Optional, T>(L, index, &no_panic, tracking);
14659 #include <type_traits> 14663 #include <string_view> 14664 #if SOL_IS_ON(SOL_STD_VARIANT) 14666 #endif // Can use variant 14670 #include <iostream> 14672 namespace sol {
namespace detail {
namespace debug {
14673 inline std::string dump_types(
lua_State* L) {
14674 std::string visual;
14675 std::size_t size = lua_gettop(L) + 1;
14676 for (std::size_t i = 1; i < size; ++i) {
14680 visual += type_name(L, stack::get<type>(L, static_cast<int>(i)));
14685 inline void print_stack(
lua_State* L) {
14686 std::cout << dump_types(L) << std::endl;
14689 inline void print_section(
const std::string& message,
lua_State* L) {
14690 std::cout <<
"-- " << message <<
" -- [ " << dump_types(L) <<
" ]" << std::endl;
14696 namespace sol {
namespace stack {
14697 namespace stack_detail {
14698 template <
typename T>
14699 inline bool integer_value_fits(
const T& value) {
14704 constexpr
bool is_same_signedness
14705 = (std::is_signed_v<T> && std::is_signed_v<lua_Integer>) || (std::is_unsigned_v<T> && std::is_unsigned_v<lua_Integer>);
14706 constexpr
bool probaby_fits_within_lua_Integer =
sizeof(T) ==
sizeof(lua_Integer)
14707 #if SOL_IS_ON(SOL_ALL_INTEGER_VALUES_FIT) 14708 && ((std::has_unique_object_representations_v<T> && std::has_unique_object_representations_v<lua_Integer>) ?
true : is_same_signedness)
14710 && is_same_signedness
14713 if constexpr (
sizeof(T) <
sizeof(lua_Integer) || probaby_fits_within_lua_Integer) {
14718 auto u_min =
static_cast<std::intmax_t
>((std::numeric_limits<lua_Integer>::min)());
14719 auto u_max =
static_cast<std::uintmax_t
>((std::numeric_limits<lua_Integer>::max)());
14720 auto t_min =
static_cast<std::intmax_t
>((std::numeric_limits<T>::min)());
14721 auto t_max =
static_cast<std::uintmax_t
>((std::numeric_limits<T>::max)());
14722 return (u_min <= t_min || value >= static_cast<T>(u_min)) && (u_max >= t_max || value <= static_cast<T>(u_max));
14726 template <
typename T>
14727 int msvc_is_ass_with_if_constexpr_push_enum(std::true_type,
lua_State* L,
const T& value) {
14728 if constexpr (meta::any_same_v<std::underlying_type_t<T>,
14730 #
if SOL_IS_ON(SOL_CHAR8_T)
14737 if constexpr (std::is_signed_v<T>) {
14738 return stack::push(L, static_cast<std::int_least32_t>(value));
14741 return stack::push(L, static_cast<std::uint_least32_t>(value));
14745 return stack::push(L,
static_cast<std::underlying_type_t<T>
>(value));
14749 template <
typename T>
14750 int msvc_is_ass_with_if_constexpr_push_enum(std::false_type,
lua_State*,
const T&) {
14755 inline int push_environment_of(
lua_State* L,
int target_index = -1) {
14756 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 14757 luaL_checkstack(L, 1, detail::not_enough_stack_space_environment);
14758 #endif // make sure stack doesn't overflow 14759 #if SOL_LUA_VERSION_I_ < 502 14761 lua_getfenv(L, target_index);
14764 if (lua_iscfunction(L, target_index) != 0) {
14765 const char* maybe_upvalue_name = lua_getupvalue(L, target_index, 1);
14766 if (maybe_upvalue_name !=
nullptr) {
14774 const char* maybe_upvalue_name = lua_getupvalue(L, target_index,
upvalue_index);
14775 if (maybe_upvalue_name ==
nullptr) {
14780 string_view upvalue_name(maybe_upvalue_name);
14781 if (upvalue_name ==
"_ENV") {
14792 template <
typename T>
14793 int push_environment_of(
const T& target) {
14794 lua_State* target_L = target.lua_state();
14796 int env_count = push_environment_of(target_L, target_index);
14797 sol_c_assert(env_count == 1);
14798 lua_rotate(target_L, target_index, 1);
14799 lua_pop(target_L, 1);
14803 template <
typename T>
14805 template <
typename F,
typename... Args>
14806 static int push_fx(
lua_State* L, F&& f, Args&&... args) {
14807 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 14808 luaL_checkstack(L, 1, detail::not_enough_stack_space_userdata);
14809 #endif // make sure stack doesn't overflow 14815 T* obj = detail::usertype_allocate<T>(L);
14817 std::allocator<T> alloc {};
14818 std::allocator_traits<std::allocator<T>>::construct(alloc, obj, std::forward<Args>(args)...);
14822 template <
typename K,
typename... Args>
14823 static int push_keyed(
lua_State* L, K&& k, Args&&... args) {
14825 return push_fx(L, fx, std::forward<Args>(args)...);
14828 template <
typename Arg,
typename... Args>
14829 static int push(
lua_State* L, Arg&& arg, Args&&... args) {
14832 return push_fx(L, std::forward<Args>(args)...);
14844 template <
typename T>
14846 typedef meta::unqualified_t<T> U;
14848 template <
typename F>
14849 static int push_fx(
lua_State* L, F&& f, T* obj) {
14850 if (obj ==
nullptr)
14851 return stack::push(L, lua_nil);
14852 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 14853 luaL_checkstack(L, 1, detail::not_enough_stack_space_userdata);
14854 #endif // make sure stack doesn't overflow 14855 T** pref = detail::usertype_allocate_pointer<T>(L);
14861 template <
typename K>
14862 static int push_keyed(
lua_State* L, K&& k, T* obj) {
14864 return push_fx(L, fx, obj);
14867 template <
typename Arg,
typename... Args>
14868 static int push(
lua_State* L, Arg&& arg, Args&&... args) {
14871 return push_fx(L, std::forward<Args>(args)...);
14881 template <
typename T>
14882 static int push(
lua_State* L, T&& obj) {
14883 return stack::push(L, detail::ptr(obj));
14887 namespace stack_detail {
14888 template <
typename T>
14890 using element = unique_usertype_element_t<T>;
14891 using actual = unique_usertype_actual_t<T>;
14893 template <
typename Arg,
typename... Args>
14894 static int push(
lua_State* L, Arg&& arg, Args&&... args) {
14895 if constexpr (std::is_base_of_v<actual, meta::unqualified_t<Arg>>) {
14896 if (detail::unique_is_null(L, arg)) {
14897 return stack::push(L, lua_nil);
14899 return push_deep(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
14902 return push_deep(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
14906 template <
typename... Args>
14907 static int push_deep(
lua_State* L, Args&&... args) {
14908 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 14909 luaL_checkstack(L, 1, detail::not_enough_stack_space_userdata);
14910 #endif // make sure stack doesn't overflow 14911 element** pointer_to_memory =
nullptr;
14912 detail::unique_destructor* fx =
nullptr;
14913 detail::unique_tag*
id =
nullptr;
14914 actual* typed_memory = detail::usertype_unique_allocate<element, actual>(L, pointer_to_memory, fx, id);
14916 detail::lua_reg_table registration_table {};
14919 detail::insert_default_registrations<element>(insert_callable, detail::property_always_true);
14920 registration_table[index] = { to_string(meta_function::garbage_collect).c_str(), detail::make_destructor<T>() };
14921 luaL_setfuncs(L, registration_table, 0);
14923 lua_setmetatable(L, -2);
14924 *fx = detail::usertype_unique_alloc_destroy<element, actual>;
14926 detail::default_construct::construct(typed_memory, std::forward<Args>(args)...);
14927 *pointer_to_memory = detail::unique_get<T>(L, *typed_memory);
14933 template <
typename T>
14935 template <
typename... Args>
14936 static int push(
lua_State* L, Args&&... args) {
14939 return p.push(L, std::forward<Args>(args)...);
14943 template <
typename T,
typename>
14945 template <
typename... Args>
14946 static int push(
lua_State* L, Args&&... args) {
14947 using Tu = meta::unqualified_t<T>;
14948 if constexpr (is_lua_reference_v<Tu>) {
14949 using int_arr =
int[];
14950 int_arr p { (std::forward<Args>(args).push(L))... };
14953 else if constexpr (std::is_same_v<Tu, bool>) {
14954 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 14955 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
14956 #endif // make sure stack doesn't overflow 14957 lua_pushboolean(L, std::forward<Args>(args)...);
14960 else if constexpr (std::is_integral_v<Tu> || std::is_same_v<Tu, lua_Integer>) {
14961 const Tu& value(std::forward<Args>(args)...);
14962 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 14963 luaL_checkstack(L, 1, detail::not_enough_stack_space_integral);
14964 #endif // make sure stack doesn't overflow 14965 #if SOL_LUA_VERSION_I_ >= 503 14966 if (stack_detail::integer_value_fits<Tu>(value)) {
14967 lua_pushinteger(L, static_cast<lua_Integer>(value));
14970 #endif // Lua 5.3 and above 14971 #if SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS) 14972 if (static_cast<T>(llround(static_cast<lua_Number>(value))) != value) {
14973 #if SOL_IS_OFF(SOL_EXCEPTIONS) 14975 sol_m_assert(
false,
"integer value will be misrepresented in lua");
14976 lua_pushinteger(L, static_cast<lua_Integer>(value));
14979 throw error(detail::direct_error,
"integer value will be misrepresented in lua");
14980 #endif // No Exceptions 14982 #endif // Safe Numerics and Number Precision Check 14983 lua_pushnumber(L, static_cast<lua_Number>(value));
14986 else if constexpr (std::is_floating_point_v<Tu> || std::is_same_v<Tu, lua_Number>) {
14987 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 14988 luaL_checkstack(L, 1, detail::not_enough_stack_space_floating);
14989 #endif // make sure stack doesn't overflow 14990 lua_pushnumber(L, std::forward<Args>(args)...);
14993 else if constexpr (std::is_same_v<Tu, luaL_Stream*>) {
14994 luaL_Stream* source { std::forward<Args>(args)... };
14996 stream->f = source->f;
14997 #if SOL_IS_ON(SOL_LUAL_STREAM_USE_CLOSE_FUNCTION) 14998 stream->closef = source->closef;
14999 #endif // LuaJIT and Lua 5.1 and below do not have 15002 else if constexpr (std::is_same_v<Tu, luaL_Stream>) {
15003 luaL_Stream& source(std::forward<Args>(args)...);
15005 stream->f = source.f;
15006 #if SOL_IS_ON(SOL_LUAL_STREAM_USE_CLOSE_FUNCTION) 15007 stream->closef = source.closef;
15008 #endif // LuaJIT and Lua 5.1 and below do not have 15011 else if constexpr (std::is_enum_v<Tu>) {
15012 return stack_detail::msvc_is_ass_with_if_constexpr_push_enum(std::true_type(), L, std::forward<Args>(args)...);
15014 else if constexpr (std::is_pointer_v<Tu>) {
15015 return stack::push<detail::as_pointer_tag<std::remove_pointer_t<T>>>(L, std::forward<Args>(args)...);
15017 else if constexpr (is_unique_usertype_v<Tu>) {
15018 return stack::push<detail::as_unique_tag<T>>(L, std::forward<Args>(args)...);
15021 return stack::push<detail::as_value_tag<T>>(L, std::forward<Args>(args)...);
15026 template <
typename T>
15028 static int push(
lua_State* L,
const std::reference_wrapper<T>& t) {
15029 return stack::push(L, std::addressof(detail::deref(t.get())));
15033 template <
typename T>
15037 static int push(
lua_State* L,
const T& tablecont) {
15038 return push(has_kvp(), std::false_type(), L, tablecont);
15042 return push(has_kvp(), std::true_type(), L, tablecont);
15045 static int push(std::true_type,
lua_State* L,
const T& tablecont) {
15046 return push(has_kvp(), std::true_type(), L, tablecont);
15049 static int push(std::false_type,
lua_State* L,
const T& tablecont) {
15050 return push(has_kvp(), std::false_type(), L, tablecont);
15053 template <
bool is_nested>
15054 static int push(std::true_type, std::integral_constant<bool, is_nested>,
lua_State* L,
const T& tablecont) {
15055 auto& cont = detail::deref(detail::unwrap(tablecont));
15056 lua_createtable(L, static_cast<int>(cont.size()), 0);
15057 int tableindex = lua_gettop(L);
15058 for (
const auto& pair : cont) {
15060 set_field(L, pair.first, as_nested_ref(pair.second), tableindex);
15063 set_field(L, pair.first, pair.second, tableindex);
15069 template <
bool is_nested>
15070 static int push(std::false_type, std::integral_constant<bool, is_nested>,
lua_State* L,
const T& tablecont) {
15071 auto& cont = detail::deref(detail::unwrap(tablecont));
15072 lua_createtable(L, stack_detail::get_size_hint(cont), 0);
15073 int tableindex = lua_gettop(L);
15074 std::size_t index = 1;
15075 for (
const auto& i : cont) {
15076 #if SOL_LUA_VERSION_I_ >= 503 15077 int p = is_nested ? stack::push(L, as_nested_ref(i)) : stack::push(L, i);
15078 for (
int pi = 0; pi < p; ++pi) {
15079 lua_seti(L, tableindex, static_cast<lua_Integer>(index++));
15082 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15083 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15084 #endif // make sure stack doesn't overflow 15085 lua_pushinteger(L, static_cast<lua_Integer>(index));
15086 int p = is_nested ? stack::push(L, as_nested_ref(i)) : stack::push(L, i);
15089 lua_settable(L, tableindex);
15092 int firstindex = tableindex + 1 + 1;
15093 for (
int pi = 0; pi < p; ++pi) {
15094 stack::push(L, index);
15095 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15096 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15097 #endif // make sure stack doesn't overflow 15098 lua_pushvalue(L, firstindex);
15099 lua_settable(L, tableindex);
15105 #endif // Lua Version 5.3 and others 15113 template <
typename T>
15116 using inner_t = std::remove_pointer_t<meta::unwrap_unqualified_t<T>>;
15117 if constexpr (is_container_v<inner_t>) {
15118 return stack::push<detail::as_table_tag<T>>(L, value_.value());
15121 return stack::push(L, value_.value());
15125 static int push(
lua_State* L,
const T& value_) {
15126 using inner_t = std::remove_pointer_t<meta::unwrap_unqualified_t<T>>;
15127 if constexpr (is_container_v<inner_t>) {
15128 return stack::push<detail::as_table_tag<T>>(L, value_);
15131 return stack::push(L, value_);
15136 template <
typename T>
15138 static int push(
lua_State* L,
const T& nested_value) noexcept {
15139 using Tu = meta::unwrap_unqualified_t<T>;
15140 using inner_t = std::remove_pointer_t<Tu>;
15141 if constexpr (is_container_v<inner_t>) {
15142 return stack::push<detail::as_table_tag<T>>(L, nested_value, nested_tag);
15145 return stack::push<Tu>(L, nested_value);
15150 using Tu = meta::unwrap_unqualified_t<T>;
15151 using inner_t = std::remove_pointer_t<Tu>;
15152 if constexpr (is_container_v<inner_t>) {
15153 return stack::push<detail::as_table_tag<T>>(L, nested_wrapper_.value(), nested_tag);
15156 return stack::push<Tu>(L, nested_wrapper_.value());
15161 template <
typename T>
15163 static int push(
lua_State* L,
const std::initializer_list<T>& il) noexcept {
15165 return p.push(L, il);
15172 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15173 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15174 #endif // make sure stack doesn't overflow 15190 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15191 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15192 #endif // make sure stack doesn't overflow 15193 lua_pushlstring(L, to_string(meta_function::metatable).c_str(), 4);
15200 static int push(
lua_State* L, lua_CFunction func,
int n = 0) noexcept {
15201 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15202 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15203 #endif // make sure stack doesn't overflow 15204 lua_pushcclosure(L, func, n);
15211 static int push(
lua_State* L, lua_CFunction func,
int n = 0) {
15212 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15213 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15214 #endif // make sure stack doesn't overflow 15215 lua_pushcclosure(L, func, n);
15220 #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) 15223 static int push(
lua_State* L, detail::lua_CFunction_noexcept func,
int n = 0) {
15224 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15225 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15226 #endif // make sure stack doesn't overflow 15227 lua_pushcclosure(L, func, n);
15234 static int push(
lua_State* L, detail::lua_CFunction_noexcept func,
int n = 0) {
15235 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15236 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15237 #endif // make sure stack doesn't overflow 15238 lua_pushcclosure(L, func, n);
15242 #endif // noexcept function type 15247 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15248 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15249 #endif // make sure stack doesn't overflow 15250 lua_pushcclosure(L, cc.c_function, cc.upvalues);
15255 template <
typename Arg,
typename... Args>
15257 template <std::size_t... I,
typename T>
15258 static int push(std::index_sequence<I...>,
lua_State* L, T&& c) {
15259 using f_tuple = decltype(std::forward<T>(c).upvalues);
15260 int pushcount = multi_push(L, std::get<I>(std::forward<f_tuple>(std::forward<T>(c).upvalues))...);
15261 return stack::push(L,
c_closure(c.c_function, pushcount));
15264 template <
typename T>
15266 return push(std::make_index_sequence<1 +
sizeof...(Args)>(), L, std::forward<T>(c));
15273 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15274 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15275 #endif // make sure stack doesn't overflow 15276 lua_pushlightuserdata(L, userdata);
15284 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15285 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15286 #endif // make sure stack doesn't overflow 15287 lua_pushlightuserdata(L, const_cast<void*>(userdata));
15295 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15296 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15297 #endif // make sure stack doesn't overflow 15298 lua_pushlightuserdata(L, userdata);
15303 template <
typename T>
15306 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15307 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15308 #endif // make sure stack doesn't overflow 15309 lua_pushlightuserdata(L, static_cast<void*>(l.value()));
15314 template <
typename T>
15316 template <
bool with_meta =
true,
typename Key,
typename... Args>
15317 static int push_with(
lua_State* L, Key&& name, Args&&... args) {
15318 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15319 luaL_checkstack(L, 1, detail::not_enough_stack_space_userdata);
15320 #endif // make sure stack doesn't overflow 15322 T* data = detail::user_allocate<T>(L);
15325 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15326 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15327 #endif // make sure stack doesn't overflow 15328 if (luaL_newmetatable(L, name) != 0) {
15329 lua_CFunction cdel = detail::user_alloc_destroy<T>;
15330 lua_pushcclosure(L, cdel, 0);
15331 lua_setfield(L, -2,
"__gc");
15333 lua_setmetatable(L, -2);
15335 std::allocator<T> alloc {};
15336 std::allocator_traits<std::allocator<T>>::construct(alloc, data, std::forward<Args>(args)...);
15340 template <
typename Arg,
typename... Args>
15341 static int push(
lua_State* L, Arg&& arg, Args&&... args) {
15342 if constexpr (std::is_same_v<meta::unqualified_t<Arg>,
metatable_key_t>) {
15343 const auto name = &arg[0];
15344 return push_with<true>(L, name, std::forward<Args>(args)...);
15346 else if constexpr (std::is_same_v<meta::unqualified_t<Arg>,
no_metatable_t>) {
15349 return push_with<false>(L, name, std::forward<Args>(args)...);
15353 return push_with(L, name, std::forward<Arg>(arg), std::forward<Args>(args)...);
15359 return push_with(L, name, u.value);
15364 return push_with(L, name, std::move(u.value()));
15369 return push_with<false>(L, name, u.value());
15374 return push_with<false>(L, name, std::move(u.value()));
15381 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15382 luaL_checkstack(L, 1, detail::not_enough_stack_space_userdata);
15383 #endif // make sure stack doesn't overflow 15384 void** ud = detail::usertype_allocate_pointer<void>(L);
15385 *ud = data.value();
15392 static int push_sized(
lua_State* L,
const char* str, std::size_t len) {
15393 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15394 luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
15395 #endif // make sure stack doesn't overflow 15396 lua_pushlstring(L, str, len);
15400 static int push(
lua_State* L,
const char* str) {
15401 if (str ==
nullptr)
15402 return stack::push(L, lua_nil);
15403 return push_sized(L, str, std::char_traits<char>::length(str));
15406 static int push(
lua_State* L,
const char* strb,
const char* stre) {
15407 return push_sized(L, strb, static_cast<std::size_t>(stre - strb));
15410 static int push(
lua_State* L,
const char* str, std::size_t len) {
15411 return push_sized(L, str, len);
15417 static int push_sized(
lua_State* L,
const char* str, std::size_t len) {
15420 return p.push_sized(L, str, len);
15423 static int push(
lua_State* L,
const char* str) {
15426 return p.push(L, str);
15429 static int push(
lua_State* L,
const char* strb,
const char* stre) {
15432 return p.push(L, strb, stre);
15435 static int push(
lua_State* L,
const char* str, std::size_t len) {
15438 return p.push(L, str, len);
15442 template <
size_t N>
15444 static int push(
lua_State* L,
const char (&str)[N]) {
15445 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15446 luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
15447 #endif // make sure stack doesn't overflow 15448 lua_pushlstring(L, str, std::char_traits<char>::length(str));
15452 static int push(
lua_State* L,
const char (&str)[N], std::size_t sz) {
15453 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15454 luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
15455 #endif // make sure stack doesn't overflow 15456 lua_pushlstring(L, str, sz);
15463 static int push(
lua_State* L,
char c) {
15464 const char str[2] = { c,
'\0' };
15465 return stack::push(L, static_cast<const char*>(str), 1u);
15469 #if SOL_IS_ON(SOL_CHAR8_T) 15472 static int push_sized(
lua_State* L,
const char8_t* str, std::size_t len) {
15473 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15474 luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
15475 #endif // make sure stack doesn't overflow 15476 lua_pushlstring(L, reinterpret_cast<const char*>(str), len);
15480 static int push(
lua_State* L,
const char8_t* str) {
15481 if (str ==
nullptr)
15482 return stack::push(L, lua_nil);
15483 return push_sized(L, str, std::char_traits<char>::length(reinterpret_cast<const char*>(str)));
15486 static int push(
lua_State* L,
const char8_t* strb,
const char8_t* stre) {
15487 return push_sized(L, strb, static_cast<std::size_t>(stre - strb));
15490 static int push(
lua_State* L,
const char8_t* str, std::size_t len) {
15491 return push_sized(L, str, len);
15497 static int push_sized(
lua_State* L,
const char8_t* str, std::size_t len) {
15500 return p.push_sized(L, str, len);
15503 static int push(
lua_State* L,
const char8_t* str) {
15506 return p.push(L, str);
15509 static int push(
lua_State* L,
const char8_t* strb,
const char8_t* stre) {
15512 return p.push(L, strb, stre);
15515 static int push(
lua_State* L,
const char8_t* str, std::size_t len) {
15518 return p.push(L, str, len);
15522 template <
size_t N>
15524 static int push(
lua_State* L,
const char8_t (&str)[N]) {
15525 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15526 luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
15527 #endif // make sure stack doesn't overflow 15528 const char* str_as_char =
reinterpret_cast<const char*
>(
static_cast<const char8_t*
>(str));
15529 lua_pushlstring(L, str_as_char, std::char_traits<char>::length(str_as_char));
15533 static int push(
lua_State* L,
const char8_t (&str)[N], std::size_t sz) {
15534 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15535 luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
15536 #endif // make sure stack doesn't overflow 15537 lua_pushlstring(L, str, sz);
15544 static int push(
lua_State* L, char8_t c) {
15545 const char8_t str[2] = { c,
'\0' };
15546 return stack::push(L, static_cast<const char8_t*>(str), 1u);
15551 template <
typename Ch,
typename Traits,
typename Al>
15553 static int push(
lua_State* L,
const std::basic_string<Ch, Traits, Al>& str) {
15554 if constexpr (!std::is_same_v<Ch, char>) {
15555 return stack::push(L, str.data(), str.size());
15558 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15559 luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
15560 #endif // make sure stack doesn't overflow 15561 lua_pushlstring(L, str.c_str(), str.size());
15566 static int push(
lua_State* L,
const std::basic_string<Ch, Traits, Al>& str, std::size_t sz) {
15567 if constexpr (!std::is_same_v<Ch, char>) {
15568 return stack::push(L, str.data(), sz);
15571 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15572 luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
15573 #endif // make sure stack doesn't overflow 15574 lua_pushlstring(L, str.c_str(), sz);
15580 template <
typename Ch,
typename Traits>
15582 static int push(
lua_State* L,
const basic_string_view<Ch, Traits>& sv) {
15583 return stack::push(L, sv.data(), sv.length());
15586 static int push(
lua_State* L,
const basic_string_view<Ch, Traits>& sv, std::size_t n) {
15587 return stack::push(L, sv.data(), n);
15593 static int push(
lua_State* L, meta_function m) {
15594 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15595 luaL_checkstack(L, 1, detail::not_enough_stack_space_meta_function_name);
15596 #endif // make sure stack doesn't overflow 15597 const std::string& str = to_string(m);
15598 lua_pushlstring(L, str.c_str(), str.size());
15606 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15607 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15608 #endif // make sure stack doesn't overflow 15609 lua_pushvalue(L, ai);
15617 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15618 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15619 #endif // make sure stack doesn't overflow 15620 lua_pushvalue(L, ri);
15628 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15629 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
15630 #endif // make sure stack doesn't overflow 15631 lua_rawgeti(L, LUA_REGISTRYINDEX, ri);
15638 static int push(
lua_State* L,
const wchar_t* wstr) {
15639 return push(L, wstr, std::char_traits<wchar_t>::length(wstr));
15642 static int push(
lua_State* L,
const wchar_t* wstr, std::size_t sz) {
15643 return push(L, wstr, wstr + sz);
15646 static int push(
lua_State* L,
const wchar_t* strb,
const wchar_t* stre) {
15647 if constexpr (
sizeof(
wchar_t) == 2) {
15648 const char16_t* sb =
reinterpret_cast<const char16_t*
>(strb);
15649 const char16_t* se =
reinterpret_cast<const char16_t*
>(stre);
15650 return stack::push(L, sb, se);
15653 const char32_t* sb =
reinterpret_cast<const char32_t*
>(strb);
15654 const char32_t* se =
reinterpret_cast<const char32_t*
>(stre);
15655 return stack::push(L, sb, se);
15662 static int push(
lua_State* L,
const wchar_t* str) {
15665 return p.push(L, str);
15668 static int push(
lua_State* L,
const wchar_t* strb,
const wchar_t* stre) {
15671 return p.push(L, strb, stre);
15674 static int push(
lua_State* L,
const wchar_t* str, std::size_t len) {
15677 return p.push(L, str, len);
15683 static int convert_into(
lua_State* L,
char* start, std::size_t,
const char16_t* strb,
const char16_t* stre) {
15684 char* target = start;
15686 for (
const char16_t* strtarget = strb; strtarget < stre;) {
15687 auto dr = unicode::utf16_to_code_point(strtarget, stre);
15688 if (dr.error != unicode::error_code::ok) {
15689 cp = unicode::unicode_detail::replacement;
15694 auto er = unicode::code_point_to_utf8(cp);
15695 const char* utf8data = er.code_units.data();
15696 std::memcpy(target, utf8data, er.code_units_size);
15697 target += er.code_units_size;
15698 strtarget = dr.next;
15701 return stack::push(L, start, target);
15704 static int push(
lua_State* L,
const char16_t* u16str) {
15705 return push(L, u16str, std::char_traits<char16_t>::length(u16str));
15708 static int push(
lua_State* L,
const char16_t* u16str, std::size_t sz) {
15709 return push(L, u16str, u16str + sz);
15712 static int push(
lua_State* L,
const char16_t* strb,
const char16_t* stre) {
15713 char sbo[SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_];
15716 std::size_t max_possible_code_units =
static_cast<std::size_t
>(
static_cast<std::size_t
>(stre - strb) * static_cast<std::size_t>(4));
15717 if (max_possible_code_units <= SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_) {
15718 return convert_into(L, sbo, max_possible_code_units, strb, stre);
15721 std::size_t needed_size = 0;
15722 for (
const char16_t* strtarget = strb; strtarget < stre;) {
15723 auto dr = unicode::utf16_to_code_point(strtarget, stre);
15724 auto er = unicode::code_point_to_utf8(dr.codepoint);
15725 needed_size += er.code_units_size;
15726 strtarget = dr.next;
15728 if (needed_size < SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_) {
15729 return convert_into(L, sbo, needed_size, strb, stre);
15731 std::string u8str(
"", 0);
15732 u8str.resize(needed_size);
15733 char* target =
const_cast<char*
>(u8str.data());
15734 return convert_into(L, target, needed_size, strb, stre);
15740 static int push(
lua_State* L,
const char16_t* str) {
15743 return p.push(L, str);
15746 static int push(
lua_State* L,
const char16_t* strb,
const char16_t* stre) {
15749 return p.push(L, strb, stre);
15752 static int push(
lua_State* L,
const char16_t* str, std::size_t len) {
15755 return p.push(L, str, len);
15761 static int convert_into(
lua_State* L,
char* start, std::size_t,
const char32_t* strb,
const char32_t* stre) {
15762 char* target = start;
15764 for (
const char32_t* strtarget = strb; strtarget < stre;) {
15765 auto dr = unicode::utf32_to_code_point(strtarget, stre);
15766 if (dr.error != unicode::error_code::ok) {
15767 cp = unicode::unicode_detail::replacement;
15772 auto er = unicode::code_point_to_utf8(cp);
15773 const char* data = er.code_units.data();
15774 std::memcpy(target, data, er.code_units_size);
15775 target += er.code_units_size;
15776 strtarget = dr.next;
15778 return stack::push(L, start, target);
15781 static int push(
lua_State* L,
const char32_t* u32str) {
15782 return push(L, u32str, u32str + std::char_traits<char32_t>::length(u32str));
15785 static int push(
lua_State* L,
const char32_t* u32str, std::size_t sz) {
15786 return push(L, u32str, u32str + sz);
15789 static int push(
lua_State* L,
const char32_t* strb,
const char32_t* stre) {
15790 char sbo[SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_];
15793 std::size_t max_possible_code_units =
static_cast<std::size_t
>(
static_cast<std::size_t
>(stre - strb) * static_cast<std::size_t>(4));
15794 if (max_possible_code_units <= SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_) {
15795 return convert_into(L, sbo, max_possible_code_units, strb, stre);
15798 std::size_t needed_size = 0;
15799 for (
const char32_t* strtarget = strb; strtarget < stre;) {
15800 auto dr = unicode::utf32_to_code_point(strtarget, stre);
15801 auto er = unicode::code_point_to_utf8(dr.codepoint);
15802 needed_size += er.code_units_size;
15803 strtarget = dr.next;
15805 if (needed_size < SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_) {
15806 return convert_into(L, sbo, needed_size, strb, stre);
15808 std::string u8str(
"", 0);
15809 u8str.resize(needed_size);
15810 char* target =
const_cast<char*
>(u8str.data());
15811 return convert_into(L, target, needed_size, strb, stre);
15817 static int push(
lua_State* L,
const char32_t* str) {
15820 return p.push(L, str);
15823 static int push(
lua_State* L,
const char32_t* strb,
const char32_t* stre) {
15826 return p.push(L, strb, stre);
15829 static int push(
lua_State* L,
const char32_t* str, std::size_t len) {
15832 return p.push(L, str, len);
15836 template <
size_t N>
15838 static int push(
lua_State* L,
const wchar_t (&str)[N]) {
15839 return push(L, str, std::char_traits<wchar_t>::length(str));
15842 static int push(
lua_State* L,
const wchar_t (&str)[N], std::size_t sz) {
15843 const wchar_t* str_ptr =
static_cast<const wchar_t*
>(str);
15844 return stack::push<const wchar_t*>(L, str_ptr, str_ptr + sz);
15848 template <
size_t N>
15850 static int push(
lua_State* L,
const char16_t (&str)[N]) {
15851 return push(L, str, std::char_traits<char16_t>::length(str));
15854 static int push(
lua_State* L,
const char16_t (&str)[N], std::size_t sz) {
15855 const char16_t* str_ptr =
static_cast<const char16_t*
>(str);
15856 return stack::push<const char16_t*>(L, str_ptr, str_ptr + sz);
15860 template <
size_t N>
15862 static int push(
lua_State* L,
const char32_t (&str)[N]) {
15863 return push(L, str, std::char_traits<char32_t>::length(str));
15866 static int push(
lua_State* L,
const char32_t (&str)[N], std::size_t sz) {
15867 const char32_t* str_ptr =
static_cast<const char32_t*
>(str);
15868 return stack::push<const char32_t*>(L, str_ptr, str_ptr + sz);
15874 static int push(
lua_State* L,
wchar_t c) {
15875 const wchar_t str[2] = { c,
'\0' };
15876 return stack::push(L, static_cast<const wchar_t*>(str), 1u);
15882 static int push(
lua_State* L, char16_t c) {
15883 const char16_t str[2] = { c,
'\0' };
15884 return stack::push(L, static_cast<const char16_t*>(str), 1u);
15890 static int push(
lua_State* L, char32_t c) {
15891 const char32_t str[2] = { c,
'\0' };
15892 return stack::push(L, static_cast<const char32_t*>(str), 1u);
15896 template <
typename... Args>
15898 template <std::size_t... I,
typename T>
15899 static int push(std::index_sequence<I...>,
lua_State* L, T&& t) {
15900 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 15901 luaL_checkstack(L, static_cast<int>(
sizeof...(I)), detail::not_enough_stack_space_generic);
15902 #endif // make sure stack doesn't overflow 15904 (void)detail::swallow { 0, (pushcount += stack::push(L, std::get<I>(std::forward<T>(t))), 0)... };
15908 template <
typename T>
15910 return push(std::index_sequence_for<Args...>(), L, std::forward<T>(t));
15914 template <
typename A,
typename B>
15916 template <
typename T>
15918 int pushcount = stack::push(L, std::get<0>(std::forward<T>(t)));
15919 pushcount += stack::push(L, std::get<1>(std::forward<T>(t)));
15924 template <
typename T>
15926 using ValueType =
typename meta::unqualified_t<T>::value_type;
15928 template <
typename Optional>
15929 static int push(
lua_State* L, Optional&& op) {
15930 using QualifiedValueType = meta::conditional_t<std::is_lvalue_reference_v<Optional>, ValueType&, ValueType&&>;
15932 return stack::push(L, nullopt);
15934 return stack::push(L, static_cast<QualifiedValueType>(op.value()));
15938 template <
typename T>
15941 return stack::push<T>(L, value_.value());
15945 return stack::push<T>(L, std::move(value_).value());
15951 static int push(
lua_State* L, nullopt_t) noexcept {
15952 return stack::push(L, lua_nil);
15958 static int push(
lua_State* L, std::nullptr_t) noexcept {
15959 return stack::push(L, lua_nil);
15980 lua_createtable(L, nt.sequence_hint, nt.map_hint);
15985 template <
typename Allocator>
15987 template <
typename T>
15988 static int push(
lua_State* L, T&& bc,
const char* bytecode_name) {
15989 const auto first = bc.data();
15990 const auto bcsize = bc.size();
15993 (void)luaL_loadbuffer(
15994 L, reinterpret_cast<const char*>(first),
static_cast<std::size_t
>(bcsize * (
sizeof(*first) /
sizeof(
const char))), bytecode_name);
15998 template <
typename T>
15999 static int push(
lua_State* L, T&& bc) {
16000 return push(L, std::forward<bc>(bc),
"bytecode");
16004 #if SOL_IS_ON(SOL_STD_VARIANT) 16005 namespace stack_detail {
16013 template <
typename T>
16014 int operator()(T&& value)
const {
16015 return stack::push<T>(L, std::forward<T>(value));
16021 template <
typename... Tn>
16023 static int push(
lua_State* L,
const std::variant<Tn...>& v) {
16027 static int push(
lua_State* L, std::variant<Tn...>&& v) {
16031 #endif // Variant because Clang is terrible 16042 namespace sol {
namespace stack {
16043 template <
typename T,
typename>
16045 inline static decltype(
auto) pop(
lua_State* L) {
16046 if constexpr (is_stack_based_v<meta::unqualified_t<T>>) {
16047 static_assert(!is_stack_based_v<meta::unqualified_t<T>>,
16048 "You cannot pop something that lives solely on the stack: it will not remain on the stack when popped and thusly will go out of " 16054 lua_pop(L, tracking.used);
16065 namespace sol {
namespace stack {
16067 namespace stack_detail {
16068 template <
typename T,
bool global,
bool raw>
16069 inline constexpr
bool is_get_direct_tableless_v = (global && !raw && meta::is_c_str_or_string_v<T>);
16071 template <
typename T,
bool global,
bool raw>
16072 inline constexpr
bool is_get_direct_v = (is_get_direct_tableless_v<T, global, raw>)
16073 || (!global && !raw && (meta::is_c_str_or_string_v<T> || meta::is_string_of_v<T, char>))
16074 || (!global && raw && (std::is_integral_v<T> && !std::is_same_v<T, bool>))
16075 #
if SOL_LUA_VERSION_I_ >= 503
16076 || (!global && !raw && (std::is_integral_v<T> && !std::is_same_v<T, bool>))
16078 #
if SOL_LUA_VERSION_I_ >= 502
16079 || (!global && raw && std::is_pointer_v<T> && std::is_void_v<std::remove_pointer_t<T>>)
16080 #endif // void pointer keys 5.2 or better 16083 template <
typename T,
bool global,
bool raw>
16084 inline constexpr
bool is_set_direct_tableless_v = (global && !raw && meta::is_c_str_or_string_v<T>);
16086 template <
typename T,
bool global,
bool raw>
16087 inline constexpr
bool is_set_direct_v = (is_set_direct_tableless_v<T, global, raw>)
16088 || (!global && !raw && (meta::is_c_str_or_string_v<T> || meta::is_string_of_v<T, char>))
16089 || (!global && raw && (std::is_integral_v<T> && !std::is_same_v<T, bool>))
16090 #
if SOL_LUA_VERSION_I_ >= 503
16091 || (!global && !raw && (std::is_integral_v<T> && !std::is_same_v<T, bool>))
16093 #
if SOL_LUA_VERSION_I_ >= 502
16094 || (!global && raw && (std::is_pointer_v<T> && std::is_void_v<std::remove_pointer_t<T>>))
16099 template <
typename T,
bool global,
bool raw,
typename>
16101 static inline constexpr
int default_table_index
16102 = meta::conditional_t<stack_detail::is_get_direct_v<T, global, raw>, std::integral_constant<int, -1>, std::integral_constant<int, -2>>::value;
16104 template <
typename Key>
16105 void get(
lua_State* L, Key&& key,
int tableindex = default_table_index) {
16106 if constexpr (std::is_same_v<T, update_if_empty_t> || std::is_same_v<T, override_value_t> || std::is_same_v<T, create_if_nil_t>) {
16111 else if constexpr (std::is_same_v<T, env_key_t>) {
16113 #if SOL_LUA_VERSION_I_ < 502 16115 lua_getfenv(L, tableindex);
16118 if (lua_getupvalue(L, tableindex, 1) ==
nullptr) {
16123 else if constexpr (std::is_same_v<T, metatable_key_t>) {
16125 if (lua_getmetatable(L, tableindex) == 0)
16128 else if constexpr (raw) {
16129 if constexpr (std::is_integral_v<T> && !std::is_same_v<bool, T>) {
16130 lua_rawgeti(L, tableindex, static_cast<lua_Integer>(key));
16132 #if SOL_LUA_VERSION_I_ >= 502 16133 else if constexpr (std::is_pointer_v<T> && std::is_void_v<std::remove_pointer_t<T>>) {
16134 lua_rawgetp(L, tableindex, key);
16136 #endif // Lua 5.2.x+ 16138 push(L, std::forward<Key>(key));
16139 lua_rawget(L, tableindex);
16143 if constexpr (meta::is_c_str_or_string_v<T>) {
16144 if constexpr (global) {
16146 lua_getglobal(L, &key[0]);
16149 lua_getfield(L, tableindex, &key[0]);
16152 else if constexpr (std::is_same_v<T, meta_function>) {
16153 const auto& real_key = to_string(key);
16154 lua_getfield(L, tableindex, &real_key[0]);
16156 #if SOL_LUA_VERSION_I_ >= 503 16157 else if constexpr (std::is_integral_v<T> && !std::is_same_v<bool, T>) {
16158 lua_geti(L, tableindex, static_cast<lua_Integer>(key));
16160 #endif // Lua 5.3.x+ 16162 push(L, std::forward<Key>(key));
16163 lua_gettable(L, tableindex);
16169 template <
typename... Args,
bool b,
bool raw,
typename C>
16171 template <std::size_t... I,
typename Keys>
16172 void apply(std::index_sequence<0, I...>,
lua_State* L, Keys&& keys,
int tableindex) {
16173 get_field<b, raw>(L, std::get<0>(std::forward<Keys>(keys)), tableindex);
16174 void(detail::swallow { (get_field<false, raw>(L, std::get<I>(std::forward<Keys>(keys))), 0)... });
16176 lua_pop(L, static_cast<int>(
sizeof...(I)));
16180 template <
typename Keys>
16182 apply(std::make_index_sequence<
sizeof...(Args)>(), L, std::forward<Keys>(keys), lua_absindex(L, -1));
16185 template <
typename Keys>
16186 void get(
lua_State* L, Keys&& keys,
int tableindex) {
16187 apply(std::make_index_sequence<
sizeof...(Args)>(), L, std::forward<Keys>(keys), tableindex);
16191 template <
typename A,
typename B,
bool b,
bool raw,
typename C>
16193 template <
typename Keys>
16194 void get(
lua_State* L, Keys&& keys,
int tableindex) {
16195 get_field<b, raw>(L, std::get<0>(std::forward<Keys>(keys)), tableindex);
16196 get_field<false, raw>(L, std::get<1>(std::forward<Keys>(keys)));
16198 lua_pop(L, static_cast<int>(2));
16202 template <
typename Keys>
16204 get_field<b, raw>(L, std::get<0>(std::forward<Keys>(keys)));
16205 get_field<false, raw>(L, std::get<1>(std::forward<Keys>(keys)));
16207 lua_pop(L, static_cast<int>(2));
16212 template <
typename T,
bool global,
bool raw,
typename>
16214 static constexpr
int default_table_index
16215 = meta::conditional_t<stack_detail::is_set_direct_v<T, global, raw>, std::integral_constant<int, -2>, std::integral_constant<int, -3>>::value;
16217 template <
typename Key,
typename Value>
16218 void set(
lua_State* L, Key&& key,
Value&& value,
int tableindex = default_table_index) {
16219 if constexpr (std::is_same_v<T, update_if_empty_t> || std::is_same_v<T, override_value_t>) {
16225 else if constexpr (std::is_same_v<T, metatable_key_t>) {
16227 push(L, std::forward<Value>(value));
16228 lua_setmetatable(L, tableindex);
16230 else if constexpr (raw) {
16231 if constexpr (std::is_integral_v<T> && !std::is_same_v<bool, T>) {
16232 push(L, std::forward<Value>(value));
16233 lua_rawseti(L, tableindex, static_cast<lua_Integer>(key));
16235 #if SOL_LUA_VERSION_I_ >= 502 16236 else if constexpr (std::is_pointer_v<T> && std::is_void_v<std::remove_pointer_t<T>>) {
16237 push(L, std::forward<Value>(value));
16238 lua_rawsetp(L, tableindex, std::forward<Key>(key));
16240 #endif // Lua 5.2.x 16242 push(L, std::forward<Key>(key));
16243 push(L, std::forward<Value>(value));
16244 lua_rawset(L, tableindex);
16248 if constexpr (meta::is_c_str_or_string_v<T>) {
16249 if constexpr (global) {
16250 push(L, std::forward<Value>(value));
16251 lua_setglobal(L, &key[0]);
16255 push(L, std::forward<Value>(value));
16256 lua_setfield(L, tableindex, &key[0]);
16259 #if SOL_LUA_VERSION_I_ >= 503 16260 else if constexpr (std::is_integral_v<T> && !std::is_same_v<bool, T>) {
16261 push(L, std::forward<Value>(value));
16262 lua_seti(L, tableindex, static_cast<lua_Integer>(key));
16264 #endif // Lua 5.3.x 16266 push(L, std::forward<Key>(key));
16267 push(L, std::forward<Value>(value));
16268 lua_settable(L, tableindex);
16274 template <
typename... Args,
bool b,
bool raw,
typename C>
16276 template <
bool g, std::
size_t I,
typename Keys,
typename Value>
16277 void apply(std::index_sequence<I>,
lua_State* L, Keys&& keys,
Value&& value,
int tableindex) {
16278 I < 1 ? set_field<g, raw>(L, std::get<I>(std::forward<Keys>(keys)), std::forward<Value>(value), tableindex)
16279 : set_field<g, raw>(L, std::get<I>(std::forward<Keys>(keys)), std::forward<Value>(value));
16282 template <
bool g, std::size_t I0, std::size_t I1, std::size_t... I,
typename Keys,
typename Value>
16283 void apply(std::index_sequence<I0, I1, I...>,
lua_State* L, Keys&& keys,
Value&& value,
int tableindex) {
16284 I0 < 1 ? get_field<g, raw>(L, std::get<I0>(std::forward<Keys>(keys)), tableindex)
16285 : get_field<g, raw>(L, std::get<I0>(std::forward<Keys>(keys)), -1);
16286 apply<false>(std::index_sequence<I1, I...>(), L, std::forward<Keys>(keys), std::forward<Value>(value), -1);
16289 template <
bool g, std::size_t I0, std::size_t... I,
typename Keys,
typename Value>
16290 void top_apply(std::index_sequence<I0, I...>,
lua_State* L, Keys&& keys,
Value&& value,
int tableindex) {
16291 apply<g>(std::index_sequence<I0, I...>(), L, std::forward<Keys>(keys), std::forward<Value>(value), tableindex);
16292 lua_pop(L, static_cast<int>(
sizeof...(I)));
16295 template <
typename Keys,
typename Value>
16296 void set(
lua_State* L, Keys&& keys,
Value&& value,
int tableindex = -3) {
16297 top_apply<b>(std::make_index_sequence<
sizeof...(Args)>(), L, std::forward<Keys>(keys), std::forward<Value>(value), tableindex);
16301 template <
typename A,
typename B,
bool b,
bool raw,
typename C>
16303 template <
typename Keys,
typename Value>
16304 void set(
lua_State* L, Keys&& keys,
Value&& value,
int tableindex = -1) {
16305 get_field<b, raw>(L, std::get<0>(std::forward<Keys>(keys)), tableindex);
16306 set_field<false, raw>(L, std::get<1>(std::forward<Keys>(keys)), std::forward<Value>(value), lua_gettop(L));
16316 namespace sol {
namespace stack {
16317 template <
typename T,
typename P,
bool b,
bool raw,
typename>
16319 template <
typename Key>
16321 if constexpr (!b) {
16322 if (!maybe_indexable(L, tableindex)) {
16323 return probe(
false, 0);
16326 get_field<b, raw>(L, std::forward<Key>(key), tableindex);
16327 return probe(check<P>(L), 1);
16331 template <
typename A,
typename B,
typename P,
bool b,
bool raw,
typename C>
16333 template <
typename Keys>
16335 if (!b && !maybe_indexable(L, tableindex)) {
16336 return probe(
false, 0);
16338 get_field<b, raw>(L, std::get<0>(keys), tableindex);
16339 if (!maybe_indexable(L)) {
16340 return probe(
false, 1);
16342 get_field<false, raw>(L, std::get<1>(keys), tableindex);
16343 return probe(check<P>(L), 2);
16347 template <
typename... Args,
typename P,
bool b,
bool raw,
typename C>
16349 template <std::
size_t I,
typename Keys>
16350 probe apply(std::index_sequence<I>,
int sofar,
lua_State* L, Keys&& keys,
int tableindex) {
16351 get_field<(I < 1) && b, raw>(L, std::get<I>(keys), tableindex);
16352 return probe(check<P>(L), sofar);
16355 template <std::size_t I, std::size_t I1, std::size_t... In,
typename Keys>
16356 probe apply(std::index_sequence<I, I1, In...>,
int sofar,
lua_State* L, Keys&& keys,
int tableindex) {
16357 get_field < I<1 && b, raw>(L, std::get<I>(keys), tableindex);
16358 if (!maybe_indexable(L)) {
16359 return probe(
false, sofar);
16361 return apply(std::index_sequence<I1, In...>(), sofar + 1, L, std::forward<Keys>(keys), -1);
16364 template <
typename Keys>
16366 if constexpr (!b) {
16367 if (!maybe_indexable(L, tableindex)) {
16368 return probe(
false, 0);
16370 return apply(std::index_sequence_for<Args...>(), 1, L, std::forward<Keys>(keys), tableindex);
16373 return apply(std::index_sequence_for<Args...>(), 1, L, std::forward<Keys>(keys), tableindex);
16386 using typical_chunk_name_t =
char[SOL_ID_SIZE_I_];
16387 using typical_file_chunk_name_t =
char[SOL_FILE_ID_SIZE_I_];
16389 inline const std::string& default_chunk_name() {
16390 static const std::string name =
"";
16394 template <std::
size_t N>
16395 const char* make_chunk_name(
const string_view& code,
const std::string& chunkname,
char (&basechunkname)[N]) {
16396 if (chunkname.empty()) {
16397 auto it = code.cbegin();
16398 auto e = code.cend();
16400 static const std::size_t n = N - 4;
16401 for (i = 0; i < n && it != e; ++i, ++it) {
16402 basechunkname[i] = *it;
16405 for (std::size_t c = 0; c < 3; ++i, ++c) {
16406 basechunkname[i] =
'.';
16409 basechunkname[i] =
'\0';
16410 return &basechunkname[0];
16413 return chunkname.c_str();
16418 stack::push(r.lua_state(), lua_nil);
16419 while (lua_next(r.lua_state(), -2)) {
16421 auto pn = stack::pop_n(r.lua_state(), 1);
16422 stack::set_field<false, true>(r.lua_state(), key, lua_nil, r.stack_index());
16426 inline void clear_entries(
const reference& registry_reference) {
16427 auto pp = stack::push_pop(registry_reference);
16429 clear_entries(ref);
16434 namespace stack_detail {
16435 template <
typename T>
16436 inline int push_as_upvalues(
lua_State* L, T& item) {
16437 typedef std::decay_t<T>
TValue;
16438 static const std::size_t itemsize =
sizeof(TValue);
16439 static const std::size_t voidsize =
sizeof(
void*);
16440 static const std::size_t voidsizem1 = voidsize - 1;
16441 static const std::size_t data_t_count = (
sizeof(TValue) + voidsizem1) / voidsize;
16442 typedef std::array<void*, data_t_count> data_t;
16444 data_t data { {} };
16445 std::memcpy(&data[0], std::addressof(item), itemsize);
16447 for (
const auto& v : data) {
16448 lua_pushlightuserdata(L, v);
16454 template <
typename T>
16455 inline std::pair<T, int> get_as_upvalues(
lua_State* L,
int index = 2) {
16456 static const std::size_t data_t_count = (
sizeof(T) + (
sizeof(
void*) - 1)) /
sizeof(
void*);
16457 typedef std::array<void*, data_t_count> data_t;
16458 data_t voiddata { {} };
16459 for (std::size_t i = 0, d = 0; d <
sizeof(T); ++i, d +=
sizeof(
void*)) {
16462 return std::pair<T, int>(*
reinterpret_cast<T*
>(
static_cast<void*
>(voiddata.data())), index);
16465 template <
typename T>
16466 inline std::pair<T, int> get_as_upvalues_using_function(
lua_State* L,
int function_index = -1) {
16467 static const std::size_t data_t_count = (
sizeof(T) + (
sizeof(
void*) - 1)) /
sizeof(
void*);
16468 typedef std::array<void*, data_t_count> data_t;
16469 function_index = lua_absindex(L, function_index);
16471 data_t voiddata { {} };
16472 for (std::size_t d = 0; d <
sizeof(T); d +=
sizeof(
void*)) {
16475 const char* upvalue_name = lua_getupvalue(L, function_index, index + 2);
16476 if (upvalue_name ==
nullptr) {
16480 voiddata[index] = lua_touserdata(L, -1);
16484 return std::pair<T, int>(*
reinterpret_cast<T*
>(
static_cast<void*
>(voiddata.data())), index);
16487 template <
bool checked,
typename Handler,
typename Fx,
typename... Args>
16488 static decltype(
auto) eval(
types<>, std::index_sequence<>,
lua_State*,
int, Handler&&,
record&, Fx&& fx, Args&&... args) {
16489 return std::forward<Fx>(fx)(std::forward<Args>(args)...);
16492 template <
bool checked,
typename Arg,
typename... Args, std::size_t I, std::size_t... Is,
typename Handler,
typename Fx,
typename... FxArgs>
16494 record& tracking_, Fx&& fx_, FxArgs&&... fxargs_) {
16495 #if SOL_IS_ON(SOL_PROPAGATE_EXCEPTIONS) 16498 if constexpr (checked) {
16499 return eval<checked>(
types<Args...>(),
16500 std::index_sequence<Is...>(),
16503 std::forward<Handler>(handler_),
16505 std::forward<Fx>(fx_),
16506 std::forward<FxArgs>(fxargs_)...,
16507 *stack_detail::check_get_arg<Arg>(L_, start_index_ + tracking_.used, handler_, tracking_));
16512 return eval<checked>(
types<Args...>(),
16513 std::index_sequence<Is...>(),
16516 std::forward<Handler>(handler_),
16518 std::forward<Fx>(fx_),
16519 std::forward<FxArgs>(fxargs_)...,
16520 stack_detail::unchecked_get_arg<Arg>(L_, start_index_ + tracking_.used, tracking_));
16524 template <
bool checkargs = detail::default_safe_function_calls, std::size_t... I,
typename R,
typename... Args,
typename Fx,
typename... FxArgs>
16526 int start_index_, Fx&& fx_, FxArgs&&... args_) {
16527 static_assert(meta::all_v<meta::is_not_move_only<Args>...>,
16528 "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 " 16529 "a reference and std::move it manually if this was your intention.");
16532 #if SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS) 16533 if constexpr (checkargs) {
16534 multi_check<Args...>(L_, start_index_, handler);
16537 if constexpr (std::is_void_v<R>) {
16539 argument_types_, argument_indices_, L_, start_index_, handler, tracking, std::forward<Fx>(fx_), std::forward<FxArgs>(args_)...);
16542 return eval<checkargs>(
16543 argument_types_, argument_indices_, L_, start_index_, handler, tracking, std::forward<Fx>(fx_), std::forward<FxArgs>(args_)...);
16547 template <
typename T>
16548 void raw_table_set(
lua_State* L, T&& arg,
int tableindex = -2) {
16549 int push_count = push(L, std::forward<T>(arg));
16550 sol_c_assert(push_count == 1);
16551 std::size_t unique_index =
static_cast<std::size_t
>(luaL_len(L, tableindex) + 1u);
16552 lua_rawseti(L, tableindex, unique_index);
16557 template <
typename T>
16558 int set_ref(
lua_State* L, T&& arg,
int tableindex = -2) {
16559 int push_count = push(L, std::forward<T>(arg));
16560 sol_c_assert(push_count == 1);
16561 return luaL_ref(L, tableindex);
16564 template <
bool check_args = detail::default_safe_function_calls,
typename R,
typename... Args,
typename Fx,
typename... FxArgs>
16566 using args_indices = std::make_index_sequence<
sizeof...(Args)>;
16567 if constexpr (std::is_void_v<R>) {
16568 stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
16571 return stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
16575 template <
bool check_args = detail::default_safe_function_calls,
typename R,
typename... Args,
typename Fx,
typename... FxArgs>
16577 if constexpr (std::is_void_v<R>) {
16578 call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
16581 return call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
16585 template <
bool check_args = detail::default_safe_function_calls,
typename R,
typename... Args,
typename Fx,
typename... FxArgs>
16588 if constexpr (std::is_void_v<R>) {
16589 call<check_args>(tr,
16592 (std::max)(static_cast<int>(lua_gettop(L) - expected_count_t::value),
static_cast<int>(0)),
16593 std::forward<Fx>(fx),
16594 std::forward<FxArgs>(args)...);
16597 return call<check_args>(tr,
16600 (std::max)(static_cast<int>(lua_gettop(L) - expected_count_t::value),
static_cast<int>(0)),
16601 std::forward<Fx>(fx),
16602 std::forward<FxArgs>(args)...);
16606 template <
bool check_args = detail::default_safe_function_calls,
bool clean_stack =
true,
typename Ret0,
typename... Ret,
typename... Args,
16607 typename Fx,
typename... FxArgs>
16609 if constexpr (std::is_void_v<Ret0>) {
16610 call<check_args>(tr, ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
16611 if constexpr (clean_stack) {
16619 = call<check_args>(
types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
16620 using R = meta::unqualified_t<decltype(r)>;
16621 using is_stack =
meta::any<is_stack_based<R>, std::is_same<R, absolute_index>, std::is_same<R, ref_index>, std::is_same<R, raw_index>>;
16622 if constexpr (clean_stack && !is_stack::value) {
16625 return push_reference(L, std::forward<decltype(r)>(r));
16629 template <
bool check_args = detail::default_safe_function_calls,
bool clean_stack =
true,
typename Fx,
typename... FxArgs>
16630 inline int call_lua(
lua_State* L,
int start, Fx&& fx, FxArgs&&... fxargs) {
16632 using args_list =
typename traits_type::args_list;
16633 using returns_list =
typename traits_type::returns_list;
16634 return call_into_lua<check_args, clean_stack>(returns_list(), args_list(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
16637 inline call_syntax get_call_syntax(
lua_State* L,
const string_view& key,
int index) {
16638 if (lua_gettop(L) < 1) {
16639 return call_syntax::dot;
16641 luaL_getmetatable(L, key.data());
16642 auto pn = pop_n(L, 1);
16643 if (lua_compare(L, -1, index, LUA_OPEQ) != 1) {
16644 return call_syntax::dot;
16646 return call_syntax::colon;
16649 inline void script(
16650 lua_State* L, lua_Reader reader,
void* data,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
16651 detail::typical_chunk_name_t basechunkname = {};
16652 const char* chunknametarget = detail::make_chunk_name(
"lua_Reader", chunkname, basechunkname);
16653 if (lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) {
16658 inline void script(
16659 lua_State* L,
const string_view& code,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
16661 detail::typical_chunk_name_t basechunkname = {};
16662 const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
16663 if (luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) {
16668 inline void script_file(
lua_State* L,
const std::string& filename, load_mode mode = load_mode::any) {
16669 if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) {
16674 inline void luajit_exception_handler(
lua_State* L,
int (*handler)(
lua_State*, lua_CFunction) = detail::c_trampoline) {
16675 #if SOL_IS_ON(SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE) 16676 if (L ==
nullptr) {
16679 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 16680 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
16681 #endif // make sure stack doesn't overflow 16682 lua_pushlightuserdata(L, (
void*)handler);
16683 auto pn = pop_n(L, 1);
16684 luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON);
16691 inline void luajit_exception_off(
lua_State* L) {
16692 #if SOL_IS_ON(SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE) 16693 if (L ==
nullptr) {
16696 luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF);
16712 template <
typename R = reference,
bool should_pop = !is_stack_based_v<R>,
typename T>
16713 R make_reference(
lua_State* L, T&& value) {
16714 int backpedal = stack::push(L, std::forward<T>(value));
16715 R r = stack::get<R>(L, -backpedal);
16717 lua_pop(L, backpedal);
16722 template <
typename T,
typename R = reference,
bool should_pop = !is_stack_based_v<R>,
typename... Args>
16723 R make_reference(
lua_State* L, Args&&... args) {
16724 int backpedal = stack::push<T>(L, std::forward<Args>(args)...);
16725 R r = stack::get<R>(L, -backpedal);
16727 lua_pop(L, backpedal);
16732 template <
typename R = reference,
bool should_pop = !is_stack_based_v<R>,
typename T>
16733 R make_reference_userdata(
lua_State* L, T&& value) {
16734 int backpedal = stack::push_userdata(L, std::forward<T>(value));
16735 R r = stack::get<R>(L, -backpedal);
16737 lua_pop(L, backpedal);
16742 template <
typename T,
typename R = reference,
bool should_pop = !is_stack_based_v<R>,
typename... Args>
16743 R make_reference_userdata(
lua_State* L, Args&&... args) {
16744 int backpedal = stack::push_userdata<T>(L, std::forward<Args>(args)...);
16745 R r = stack::get<R>(L, -backpedal);
16747 lua_pop(L, backpedal);
16760 template <
typename ref_t>
16763 using base_t = ref_t;
16765 template <
typename T>
16766 decltype(
auto) as_stack(std::true_type)
const {
16767 return stack::get<T>(base_t::lua_state(), base_t::stack_index());
16770 template <
typename T>
16771 decltype(
auto) as_stack(std::false_type)
const {
16773 return stack::pop<T>(base_t::lua_state());
16776 template <
typename T>
16777 bool is_stack(std::true_type)
const {
16778 return stack::check<T>(base_t::lua_state(), base_t::stack_index(), &no_panic);
16781 template <
typename T>
16782 bool is_stack(std::false_type)
const {
16783 int r = base_t::registry_index();
16784 if (r == LUA_REFNIL)
16786 if (r == LUA_NOREF)
16788 auto pp = stack::push_pop(*
this);
16789 return stack::check<T>(base_t::lua_state(), -1, &no_panic);
16798 template <
typename T,
typename... Args, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>,
basic_object_base>>> = meta::enabler>
16799 basic_object_base(T&& arg, Args&&... args) : base_t(std::forward<T>(arg), std::forward<Args>(args)...) {
16802 template <
typename T>
16803 decltype(
auto) as()
const {
16807 template <
typename T>
16818 template <
typename base_type>
16823 template <
bool invert_and_pop = false>
16824 basic_object(std::integral_constant<bool, invert_and_pop>,
lua_State* L_,
int index_ = -1) noexcept : base_t(L_, index_) {
16825 if (invert_and_pop) {
16826 lua_pop(L_, -index_);
16837 template <
typename T,
16838 meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>,
basic_object>>, meta::neg<std::is_same<base_type, stack_reference>>,
16843 template <
typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
16848 basic_object() noexcept =
default;
16849 template <
typename T,
16850 meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_object>>, meta::neg<std::is_same<base_type, stack_reference>>,
16851 is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
16852 basic_object(T&& r) : base_t(std::forward<T>(r)) {
16854 template <
typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
16855 basic_object(
lua_State* L_, T&& r) : base_t(L_, std::forward<T>(r)) {
16859 basic_object(
lua_nil_t r) : base_t(r) {
16861 basic_object(
const basic_object&) =
default;
16862 basic_object(basic_object&&) =
default;
16863 basic_object(
const stack_reference& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {
16865 basic_object(
stack_reference&& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {
16867 template <
typename Super>
16868 basic_object(
const proxy_base<Super>& r) noexcept : basic_object(r.operator basic_object()) {
16870 template <
typename Super>
16871 basic_object(
proxy_base<Super>&& r) noexcept : basic_object(r.operator basic_object()) {
16875 basic_object(
lua_State* L_,
int index_ = -1) noexcept : base_t(L_, index_) {
16883 template <
typename T,
typename... Args>
16884 basic_object(
lua_State* L_, in_place_type_t<T>, Args&&... args) noexcept
16887 template <
typename T,
typename... Args>
16888 basic_object(
lua_State* L_, in_place_t, T&& arg, Args&&... args) noexcept
16889 : basic_object(L_, in_place_type<T>, std::forward<T>(arg), std::forward<Args>(args)...) {
16891 basic_object& operator=(
const basic_object&) =
default;
16892 basic_object& operator=(basic_object&&) =
default;
16893 basic_object& operator=(
const base_type& b) {
16894 base_t::operator=(b);
16897 basic_object& operator=(base_type&& b) {
16898 base_t::operator=(std::move(b));
16901 template <
typename Super>
16903 this->operator=(r.operator basic_object());
16906 template <
typename Super>
16908 this->operator=(r.operator basic_object());
16913 template <
typename T>
16914 object make_object(
lua_State* L_, T&& value) {
16915 return make_reference<object, true>(L_, std::forward<T>(value));
16918 template <
typename T,
typename... Args>
16919 object make_object(
lua_State* L_, Args&&... args) {
16920 return make_reference<T, object, true>(L_, std::forward<Args>(args)...);
16923 template <
typename T>
16924 object make_object_userdata(
lua_State* L_, T&& value) {
16925 return make_reference_userdata<object, true>(L_, std::forward<T>(value));
16928 template <
typename T,
typename... Args>
16929 object make_object_userdata(
lua_State* L_, Args&&... args) {
16930 return make_reference_userdata<T, object, true>(L_, std::forward<Args>(args)...);
16950 template <
typename T>
16951 using proxy_key_t = meta::conditional_t<meta::is_specialization_of_v<meta::unqualified_t<T>, std::tuple>, T,
16952 std::tuple<meta::conditional_t<std::is_array_v<meta::unqualified_t<T>>, std::remove_reference_t<T>&, meta::unqualified_t<T>>>>;
16955 template <
typename Super>
16958 const Super& super = *
static_cast<const Super*
>(
static_cast<const void*
>(
this));
16959 return super.lua_state();
16962 operator std::string()
const {
16963 const Super& super = *
static_cast<const Super*
>(
static_cast<const void*
>(
this));
16964 return super.template get<std::string>();
16967 template <
typename T, meta::enable<meta::neg<meta::is_
string_constructible<T>>, is_proxy_primitive<meta::unqualified_t<T>>> = meta::enabler>
16968 operator T()
const {
16969 const Super& super = *
static_cast<const Super*
>(
static_cast<const void*
>(
this));
16970 return super.template get<T>();
16973 template <
typename T,
16974 meta::enable<meta::neg<meta::is_string_constructible<T>>, meta::neg<is_proxy_primitive<meta::unqualified_t<T>>>> = meta::enabler>
16975 operator T&()
const {
16976 const Super& super = *
static_cast<const Super*
>(
static_cast<const void*
>(
this));
16977 return super.template get<T&>();
16988 #include <iterator> 16991 template <
typename proxy_t,
bool is_const>
16993 typedef meta::conditional_t<is_const, const proxy_t, proxy_t> reference;
16994 typedef meta::conditional_t<is_const, const proxy_t*, proxy_t*> pointer;
16995 typedef proxy_t value_type;
16996 typedef std::ptrdiff_t difference_type;
16997 typedef std::random_access_iterator_tag iterator_category;
17003 stack_iterator() : L(
nullptr), index((std::numeric_limits<int>::max)()), stacktop((std::numeric_limits<int>::max)()), sp() {
17007 stack_iterator(
lua_State* luastate,
int idx,
int topidx) : L(luastate), index(idx), stacktop(topidx), sp(luastate, idx) {
17010 reference operator*() {
17011 return proxy_t(L, index);
17014 reference operator*()
const {
17015 return proxy_t(L, index);
17018 pointer operator->() {
17019 sp = proxy_t(L, index);
17023 pointer operator->()
const {
17024 const_cast<proxy_t&
>(sp) = proxy_t(L, index);
17035 this->operator++();
17046 this->operator--();
17051 index +=
static_cast<int>(idx);
17056 index -=
static_cast<int>(idx);
17061 return index - r.index;
17070 reference operator[](difference_type idx)
const {
17071 return proxy_t(L, index + static_cast<int>(idx));
17075 if (stacktop == (std::numeric_limits<int>::max)()) {
17076 return r.index == r.stacktop;
17078 else if (r.stacktop == (std::numeric_limits<int>::max)()) {
17079 return index == stacktop;
17081 return index == r.index;
17085 return !(this->operator==(r));
17089 return index < r.index;
17093 return index > r.index;
17097 return index <= r.index;
17101 return index >= r.index;
17105 template <
typename proxy_t,
bool is_const>
17130 template <
typename T>
17131 decltype(
auto)
get()
const {
17132 return stack::get<T>(m_L, stack_index());
17135 template <
typename T>
17137 return stack::check<T>(m_L, stack_index());
17140 template <
typename T>
17141 decltype(
auto) as()
const {
17145 type get_type()
const noexcept {
17146 return type_of(lua_state(), stack_index());
17154 lua_pushvalue(L_, m_index);
17161 int stack_index()
const {
17177 return proxy_reference.push();
17194 template <
typename... Ret,
typename... Args>
17195 decltype(
auto) call(Args&&... args);
17197 template <
typename... Args>
17198 decltype(
auto) operator()(Args&&... args) {
17199 return call<>(std::forward<Args>(args)...);
17238 typedef std::ptrdiff_t difference_type;
17239 typedef std::size_t size_type;
17242 typedef std::reverse_iterator<iterator> reverse_iterator;
17243 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
17247 : L(Ls), index(idx), returncount(retnum), popcount(popped), err(pferr) {
17258 : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) {
17267 returncount = o.returncount;
17268 popcount = o.popcount;
17282 call_status status()
const noexcept {
17286 bool valid()
const noexcept {
17287 return status() == call_status::ok || status() == call_status::yielded;
17290 #if SOL_IS_ON(SOL_COMPILER_GCC) 17291 #pragma GCC diagnostic push 17292 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 17295 template <
typename T>
17296 decltype(
auto)
get(
int index_offset = 0)
const {
17297 using UT = meta::unqualified_t<T>;
17298 int target = index + index_offset;
17299 if constexpr (meta::is_optional_v<UT>) {
17300 using ValueType =
typename UT::value_type;
17301 if constexpr (std::is_same_v<ValueType, error>) {
17305 return UT(
error(detail::direct_error, stack::get<std::string>(L, target)));
17311 return stack::get<UT>(L, target);
17315 if constexpr (std::is_same_v<T, error>) {
17316 #if SOL_IS_ON(SOL_SAFE_PROXIES) 17318 type t = type_of(L, target);
17319 type_panic_c_str(L, target, t, type::none,
"bad get from protected_function_result (is an error)");
17321 #endif // Check Argument Safety 17322 return error(detail::direct_error, stack::get<std::string>(L, target));
17325 #if SOL_IS_ON(SOL_SAFE_PROXIES) 17327 type t = type_of(L, target);
17328 type_panic_c_str(L, target, t, type::none,
"bad get from protected_function_result (is not an error)");
17330 #endif // Check Argument Safety 17331 return stack::get<T>(L, target);
17336 #if SOL_IS_ON(SOL_COMPILER_GCC) 17337 #pragma GCC diagnostic pop 17340 type get_type(
int index_offset = 0)
const noexcept {
17341 return type_of(L, index + static_cast<int>(index_offset));
17344 stack_proxy operator[](difference_type index_offset)
const {
17345 return stack_proxy(L, index + static_cast<int>(index_offset));
17349 return iterator(L, index, stack_index() + return_count());
17352 return iterator(L, stack_index() + return_count(), stack_index() + return_count());
17354 const_iterator begin()
const {
17355 return const_iterator(L, index, stack_index() + return_count());
17357 const_iterator end()
const {
17358 return const_iterator(L, stack_index() + return_count(), stack_index() + return_count());
17360 const_iterator cbegin()
const {
17363 const_iterator cend()
const {
17367 reverse_iterator rbegin() {
17368 return std::reverse_iterator<iterator>(begin());
17370 reverse_iterator rend() {
17371 return std::reverse_iterator<iterator>(end());
17373 const_reverse_iterator rbegin()
const {
17374 return std::reverse_iterator<const_iterator>(begin());
17376 const_reverse_iterator rend()
const {
17377 return std::reverse_iterator<const_iterator>(end());
17379 const_reverse_iterator crbegin()
const {
17380 return std::reverse_iterator<const_iterator>(cbegin());
17382 const_reverse_iterator crend()
const {
17383 return std::reverse_iterator<const_iterator>(cend());
17386 lua_State* lua_state()
const noexcept {
17389 int stack_index()
const noexcept {
17392 int return_count()
const noexcept {
17393 return returncount;
17395 int pop_count()
const noexcept {
17398 void abandon() noexcept {
17403 err = call_status::runtime;
17408 stack::remove(L, index, popcount);
17416 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 17417 luaL_checkstack(L, static_cast<int>(pfr.pop_count()), detail::not_enough_stack_space_generic);
17418 #endif // make sure stack doesn't overflow 17420 for (
int i = 0; i < pfr.pop_count(); ++i) {
17421 lua_pushvalue(L, i + pfr.stack_index());
17447 typedef std::ptrdiff_t difference_type;
17448 typedef std::size_t size_type;
17451 typedef std::reverse_iterator<iterator> reverse_iterator;
17452 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
17474 returncount = o.returncount;
17487 template <
typename T>
17488 decltype(
auto)
get(difference_type index_offset = 0)
const {
17489 return stack::get<T>(L, index +
static_cast<int>(index_offset));
17492 type get_type(difference_type index_offset = 0)
const noexcept {
17493 return type_of(L, index + static_cast<int>(index_offset));
17496 stack_proxy operator[](difference_type index_offset)
const {
17497 return stack_proxy(L, index + static_cast<int>(index_offset));
17501 return iterator(L, index, stack_index() + return_count());
17504 return iterator(L, stack_index() + return_count(), stack_index() + return_count());
17506 const_iterator begin()
const {
17507 return const_iterator(L, index, stack_index() + return_count());
17509 const_iterator end()
const {
17510 return const_iterator(L, stack_index() + return_count(), stack_index() + return_count());
17512 const_iterator cbegin()
const {
17515 const_iterator cend()
const {
17519 reverse_iterator rbegin() {
17520 return std::reverse_iterator<iterator>(begin());
17522 reverse_iterator rend() {
17523 return std::reverse_iterator<iterator>(end());
17525 const_reverse_iterator rbegin()
const {
17526 return std::reverse_iterator<const_iterator>(begin());
17528 const_reverse_iterator rend()
const {
17529 return std::reverse_iterator<const_iterator>(end());
17531 const_reverse_iterator crbegin()
const {
17532 return std::reverse_iterator<const_iterator>(cbegin());
17534 const_reverse_iterator crend()
const {
17535 return std::reverse_iterator<const_iterator>(cend());
17538 call_status status()
const noexcept {
17539 return call_status::ok;
17542 bool valid()
const noexcept {
17543 return status() == call_status::ok || status() == call_status::yielded;
17549 int stack_index()
const {
17552 int return_count()
const {
17553 return returncount;
17555 void abandon() noexcept {
17561 if (L !=
nullptr) {
17562 lua_pop(L, returncount);
17572 for (
int i = 0; i < fr.return_count(); ++i) {
17573 lua_pushvalue(L, i + fr.stack_index());
17594 template <std::size_t I,
typename... Args,
typename T>
17595 stack_proxy get(
types<Args...>, meta::index_value<0>, meta::index_value<I>,
const T& fr) {
17596 return stack_proxy(fr.lua_state(), fr.stack_index() +
static_cast<int>(I));
17599 template <std::size_t I, std::size_t N,
typename Arg,
typename... Args,
typename T, meta::enable<meta::boolean<(N > 0)>> = meta::enabler>
17601 return get(
types<Args...>(), meta::index_value<N - 1>(), meta::index_value<I + lua_size<Arg>::value>(), fr);
17611 template <std::
size_t I>
17613 return stack_proxy(fr.lua_state(), fr.stack_index() +
static_cast<int>(I));
17616 template <std::size_t I,
typename... Args>
17618 return detail::get(t, meta::index_value<I>(), meta::index_value<0>(), fr);
17621 template <std::
size_t I>
17623 return stack_proxy(fr.lua_state(), fr.stack_index() +
static_cast<int>(I));
17626 template <std::size_t I,
typename... Args>
17628 return detail::get(t, meta::index_value<I>(), meta::index_value<0>(), fr);
17643 template <
typename T>
17644 using array_return_type = meta::conditional_t<std::is_array<T>::value, std::add_lvalue_reference_t<T>, T>;
17647 template <
typename F,
typename =
void>
17652 typedef typename traits_type::returns_list returns_list;
17654 template <
typename... Args>
17655 static decltype(
auto) call(F& f, Args&&... args) {
17656 return f(std::forward<Args>(args)...);
17660 template <
typename... Args>
17661 decltype(
auto) operator()(F& fx, Args&&... args)
const {
17662 return call(fx, std::forward<Args>(args)...);
17667 template <
typename F>
17668 struct wrapper<F,
std::enable_if_t<std::is_function<std::remove_pointer_t<meta::unqualified_t<F>>>::value>> {
17672 typedef typename traits_type::returns_list returns_list;
17674 template <F fx,
typename... Args>
17675 static decltype(
auto) invoke(Args&&... args) {
17676 return fx(std::forward<Args>(args)...);
17679 template <
typename... Args>
17680 static decltype(
auto) call(F& fx, Args&&... args) {
17681 return fx(std::forward<Args>(args)...);
17685 template <
typename... Args>
17686 decltype(
auto) operator()(F& fx, Args&&... args)
const {
17687 return call(fx, std::forward<Args>(args)...);
17693 template <
typename... Args>
17694 decltype(
auto) operator()(Args&&... args)
const {
17695 return invoke<fx>(std::forward<Args>(args)...);
17700 template <
typename F>
17701 struct wrapper<F,
std::enable_if_t<std::is_member_object_pointer<meta::unqualified_t<F>>::value>> {
17703 typedef typename traits_type::object_type object_type;
17704 typedef typename traits_type::return_type return_type;
17707 typedef typename traits_type::returns_list returns_list;
17710 static auto call(object_type& mem) -> detail::array_return_type<decltype(mem.*fx)> {
17714 template <F fx,
typename Arg,
typename... Args>
17715 static decltype(
auto) invoke(object_type& mem, Arg&& arg, Args&&...) {
17716 return mem.*fx = std::forward<Arg>(arg);
17719 template <
typename Fx>
17720 static auto call(Fx&& fx, object_type& mem) -> detail::array_return_type<decltype(mem.*fx)> {
17724 template <
typename Fx,
typename Arg,
typename... Args>
17725 static void call(Fx&& fx, object_type& mem, Arg&& arg, Args&&...) {
17726 using actual_type = meta::unqualified_t<detail::array_return_type<decltype(mem.*fx)>>;
17727 if constexpr (std::is_array_v<actual_type>) {
17730 auto first = cbegin(arg);
17731 auto last = cend(arg);
17732 for (std::size_t i = 0; first != last; ++i, ++first) {
17733 (mem.*fx)[i] = *first;
17737 (mem.*fx) = std::forward<Arg>(arg);
17742 template <
typename Fx,
typename... Args>
17743 decltype(
auto) operator()(Fx&& fx, object_type& mem, Args&&... args)
const {
17744 return call(std::forward<Fx>(fx), mem, std::forward<Args>(args)...);
17750 template <
typename... Args>
17751 decltype(
auto) operator()(Args&&... args)
const {
17752 return invoke<fx>(std::forward<Args>(args)...);
17757 template <
typename F,
typename R,
typename O,
typename... FArgs>
17759 typedef O object_type;
17763 typedef meta::tuple_types<R> returns_list;
17765 template <F fx,
typename... Args>
17766 static R invoke(O& mem, Args&&... args) {
17767 return (mem.*fx)(std::forward<Args>(args)...);
17770 template <
typename Fx,
typename... Args>
17771 static R call(Fx&& fx, O& mem, Args&&... args) {
17772 return (mem.*fx)(std::forward<Args>(args)...);
17776 template <
typename Fx,
typename... Args>
17777 decltype(
auto) operator()(Fx&& fx, O& mem, Args&&... args)
const {
17778 return call(std::forward<Fx>(fx), mem, std::forward<Args>(args)...);
17784 template <
typename... Args>
17785 decltype(
auto) operator()(O& mem, Args&&... args)
const {
17786 return invoke<fx>(mem, std::forward<Args>(args)...);
17791 template <
typename R,
typename O,
typename... Args>
17794 template <
typename R,
typename O,
typename... Args>
17797 template <
typename R,
typename O,
typename... Args>
17800 template <
typename R,
typename O,
typename... Args>
17803 template <
typename R,
typename O,
typename... Args>
17806 template <
typename R,
typename O,
typename... Args>
17809 template <
typename R,
typename O,
typename... Args>
17812 template <
typename R,
typename O,
typename... Args>
17815 template <
typename R,
typename O,
typename... Args>
17818 template <
typename R,
typename O,
typename... Args>
17821 template <
typename R,
typename O,
typename... Args>
17824 template <
typename R,
typename O,
typename... Args>
17827 template <
typename R,
typename O,
typename... Args>
17830 template <
typename R,
typename O,
typename... Args>
17833 template <
typename R,
typename O,
typename... Args>
17836 #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) 17839 template <
typename R,
typename O,
typename... Args>
17842 template <
typename R,
typename O,
typename... Args>
17845 template <
typename R,
typename O,
typename... Args>
17848 template <
typename R,
typename O,
typename... Args>
17851 template <
typename R,
typename O,
typename... Args>
17854 template <
typename R,
typename O,
typename... Args>
17857 template <
typename R,
typename O,
typename... Args>
17860 template <
typename R,
typename O,
typename... Args>
17863 template <
typename R,
typename O,
typename... Args>
17864 struct wrapper<R (O::*)(Args..., ...) const volatile& noexcept>
17867 template <
typename R,
typename O,
typename... Args>
17870 template <
typename R,
typename O,
typename... Args>
17873 template <
typename R,
typename O,
typename... Args>
17877 template <
typename R,
typename O,
typename... Args>
17880 template <
typename R,
typename O,
typename... Args>
17883 template <
typename R,
typename O,
typename... Args>
17884 struct wrapper<R (O::*)(Args..., ...) const volatile&& noexcept>
17887 #endif // noexcept is part of a function's type 17895 namespace sol {
namespace function_detail {
17896 template <
typename Fx,
int start = 1,
bool is_yielding = false>
17901 return lua_yield(L, nr);
17917 #include <type_traits> 17925 template <
typename R,
typename W>
17932 template <
typename Rx,
typename Wx>
17937 return write_base_t::value();
17940 const W& write()
const {
17941 return write_base_t::value();
17945 return read_base_t::value();
17948 const R& read()
const {
17949 return read_base_t::value();
17953 template <
typename F,
typename G>
17954 inline decltype(
auto) property(F&& f, G&& g) {
17957 if constexpr (left_traits::free_arity < right_traits::free_arity) {
17965 template <
typename F>
17966 inline decltype(
auto) property(F&& f) {
17968 if constexpr (left_traits::free_arity < 2) {
17976 template <
typename F>
17977 inline decltype(
auto) readonly_property(F&& f) {
17981 template <
typename F>
17982 inline decltype(
auto) writeonly_property(F&& f) {
17986 template <
typename T>
17992 using base_t::base_t;
17995 return base_t::value();
17997 operator const T&()
const {
17998 return base_t::value();
18003 template <
typename R,
typename T>
18004 inline auto readonly(R T::*v) {
18008 template <
typename T>
18014 using base_t::base_t;
18017 template <
typename V>
18018 inline auto var(V&& v) {
18019 typedef std::decay_t<V> T;
18024 template <
typename T>
18025 using is_member_object = std::integral_constant<bool, std::is_member_object_pointer_v<T> || is_specialization_of_v<T, readonly_wrapper>>;
18027 template <
typename T>
18028 inline constexpr
bool is_member_object_v = is_member_object<T>::value;
18030 template <
typename T>
18031 using is_member_object_or_function = std::integral_constant<bool, is_member_object_v<T> || std::is_member_pointer_v<T>>;
18033 template <
typename T>
18034 inline constexpr
bool is_member_object_or_function_v = is_member_object_or_function<T>::value;
18047 template <
typename T>
18051 template <
typename Arg,
typename... Args, meta::disable<std::is_same<protect_t, meta::unqualified_t<Arg>>> = meta::enabler>
18052 protect_t(Arg&& arg, Args&&... args) : value(std::forward<Arg>(arg), std::forward<Args>(args)...) {
18055 protect_t(
const protect_t&) =
default;
18056 protect_t(protect_t&&) =
default;
18057 protect_t& operator=(
const protect_t&) =
default;
18058 protect_t& operator=(protect_t&&) =
default;
18061 template <
typename T>
18062 auto protect(T&& value) {
18071 namespace u_detail {
18075 namespace policy_detail {
18076 template <
int I,
int... In>
18078 if constexpr (
sizeof...(In) == 0) {
18084 if (type_of(L, ai) != type::userdata) {
18087 lua_createtable(L, static_cast<int>(
sizeof...(In)), 0);
18089 auto per_dep = [&L, &deps](
int i) {
18090 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 18091 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
18092 #endif // make sure stack doesn't overflow 18093 lua_pushvalue(L, i);
18094 luaL_ref(L, deps.stack_index());
18097 (void)detail::swallow { int(), (per_dep(In), int())... };
18098 lua_setuservalue(L, ai);
18102 template <
int... In>
18110 if (type_of(L, ai) != type::userdata) {
18113 lua_createtable(L, static_cast<int>(sdeps.size()), 0);
18115 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 18116 luaL_checkstack(L, static_cast<int>(sdeps.size()), detail::not_enough_stack_space_generic);
18117 #endif // make sure stack doesn't overflow 18118 for (std::size_t i = 0; i < sdeps.size(); ++i) {
18119 lua_pushvalue(L, sdeps.stack_indices[i]);
18120 luaL_ref(L, deps.stack_index());
18122 lua_setuservalue(L, ai);
18125 template <
typename P, meta::disable<std::is_base_of<detail::policy_base_tag, meta::unqualified_t<P>>> = meta::enabler>
18126 inline void handle_policy(P&& p,
lua_State* L,
int& pushed) {
18127 pushed = std::forward<P>(p)(L, pushed);
18131 namespace function_detail {
18132 inline int no_construction_error(
lua_State* L) {
18133 return luaL_error(L,
"sol: cannot call this constructor (tagged as non-constructible)");
18137 namespace call_detail {
18139 template <
typename R,
typename W>
18144 template <
typename R,
typename W>
18149 template <
typename T,
typename List>
18152 template <
typename T,
typename... Args>
18154 static void call(Args...) {
18158 template <
typename T,
bool checked,
bool clean_stack>
18165 : obj_(obj_ptr), obj_lua_ref_(&obj_lua_ref), p_umf_(&umf) {
18168 template <
typename Fx, std::size_t I,
typename... R,
typename... Args>
18171 int result = stack::call_into_lua<checked, clean_stack>(r, a, L, start, func, this->obj_);
18175 if constexpr (clean_stack) {
18176 obj_lua_ref_->push();
18178 obj_lua_ref_->pop();
18187 namespace overload_detail {
18188 template <std::size_t... M,
typename Match,
typename... Args>
18189 inline int overload_match_arity(
types<>, std::index_sequence<>, std::index_sequence<M...>, Match&&,
lua_State* L,
int,
int, Args&&...) {
18190 return luaL_error(L,
"sol: no matching function call takes this number of arguments and the specified types");
18193 template <
typename Fx,
typename... Fxs, std::size_t I, std::size_t... In, std::size_t... M,
typename Match,
typename... Args>
18194 inline int overload_match_arity(
types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx,
lua_State* L,
18195 int fxarity,
int start, Args&&... args) {
18197 typedef meta::tuple_types<typename traits::return_type> return_types;
18198 typedef typename traits::free_args_list args_list;
18200 if constexpr (!traits::runtime_variadics_t::value
18201 &&
meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
18203 std::index_sequence<In...>(),
18204 std::index_sequence<M...>(),
18205 std::forward<Match>(matchfx),
18209 std::forward<Args>(args)...);
18212 if constexpr (!traits::runtime_variadics_t::value) {
18213 if (traits::free_arity != fxarity) {
18215 std::index_sequence<In...>(),
18216 std::index_sequence<traits::free_arity, M...>(),
18217 std::forward<Match>(matchfx),
18221 std::forward<Args>(args)...);
18225 if (!stack::stack_detail::check_types(args_list(), L, start, &no_panic, tracking)) {
18227 std::index_sequence<In...>(),
18228 std::index_sequence<M...>(),
18229 std::forward<Match>(matchfx),
18233 std::forward<Args>(args)...);
18235 return matchfx(
types<Fx>(), meta::index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
18239 template <std::size_t... M,
typename Match,
typename... Args>
18240 inline int overload_match_arity_single(
18241 types<>, std::index_sequence<>, std::index_sequence<M...>, Match&& matchfx,
lua_State* L,
int fxarity,
int start, Args&&... args) {
18242 return overload_match_arity(
types<>(),
18243 std::index_sequence<>(),
18244 std::index_sequence<M...>(),
18245 std::forward<Match>(matchfx),
18249 std::forward<Args>(args)...);
18252 template <
typename Fx, std::size_t I, std::size_t... M,
typename Match,
typename... Args>
18253 inline int overload_match_arity_single(
18254 types<Fx>, std::index_sequence<I>, std::index_sequence<M...>, Match&& matchfx,
lua_State* L,
int fxarity,
int start, Args&&... args) {
18256 typedef meta::tuple_types<typename traits::return_type> return_types;
18257 typedef typename traits::free_args_list args_list;
18259 if constexpr (!traits::runtime_variadics_t::value
18260 &&
meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
18261 return overload_match_arity(
types<>(),
18262 std::index_sequence<>(),
18263 std::index_sequence<M...>(),
18264 std::forward<Match>(matchfx),
18268 std::forward<Args>(args)...);
18270 if constexpr (!traits::runtime_variadics_t::value) {
18271 if (traits::free_arity != fxarity) {
18272 return overload_match_arity(
types<>(),
18273 std::index_sequence<>(),
18274 std::index_sequence<traits::free_arity, M...>(),
18275 std::forward<Match>(matchfx),
18279 std::forward<Args>(args)...);
18282 return matchfx(
types<Fx>(), meta::index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
18285 template <
typename Fx,
typename Fx1,
typename... Fxs, std::size_t I, std::size_t I1, std::size_t... In, std::size_t... M,
typename Match,
18287 inline int overload_match_arity_single(
types<Fx, Fx1, Fxs...>, std::index_sequence<I, I1, In...>, std::index_sequence<M...>, Match&& matchfx,
18288 lua_State* L,
int fxarity,
int start, Args&&... args) {
18290 typedef meta::tuple_types<typename traits::return_type> return_types;
18291 typedef typename traits::free_args_list args_list;
18293 if constexpr (!traits::runtime_variadics_t::value
18294 &&
meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
18296 std::index_sequence<I1, In...>(),
18297 std::index_sequence<M...>(),
18298 std::forward<Match>(matchfx),
18302 std::forward<Args>(args)...);
18305 if constexpr (!traits::runtime_variadics_t::value) {
18306 if (traits::free_arity != fxarity) {
18308 std::index_sequence<I1, In...>(),
18309 std::index_sequence<traits::free_arity, M...>(),
18310 std::forward<Match>(matchfx),
18314 std::forward<Args>(args)...);
18318 if (!stack::stack_detail::check_types(args_list(), L, start, &no_panic, tracking)) {
18320 std::index_sequence<I1, In...>(),
18321 std::index_sequence<M...>(),
18322 std::forward<Match>(matchfx),
18326 std::forward<Args>(args)...);
18328 return matchfx(
types<Fx>(), meta::index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
18333 template <
typename... Functions,
typename Match,
typename... Args>
18334 inline int overload_match_arity(Match&& matchfx,
lua_State* L,
int fxarity,
int start, Args&&... args) {
18336 std::make_index_sequence<
sizeof...(Functions)>(),
18337 std::index_sequence<>(),
18338 std::forward<Match>(matchfx),
18342 std::forward<Args>(args)...);
18345 template <
typename... Functions,
typename Match,
typename... Args>
18346 inline int overload_match(Match&& matchfx,
lua_State* L,
int start, Args&&... args) {
18347 int fxarity = lua_gettop(L) - (start - 1);
18348 return overload_match_arity<Functions...>(std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
18351 template <
typename T,
typename... TypeLists,
typename Match,
typename... Args>
18352 inline int construct_match(Match&& matchfx,
lua_State* L,
int fxarity,
int start, Args&&... args) {
18354 return overload_match_arity<decltype(void_call<T, TypeLists>::call)...>(
18355 std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
18358 template <
typename T,
bool checked,
bool clean_stack,
typename... TypeLists>
18359 inline int construct_trampolined(
lua_State* L) {
18361 int argcount = lua_gettop(L);
18363 argcount -=
static_cast<int>(syntax);
18365 T* obj = detail::usertype_allocate<T>(L);
18373 userdataref.push();
18377 template <
typename T,
bool checked,
bool clean_stack,
typename... TypeLists>
18379 return detail::static_trampoline<&construct_trampolined<T, checked, clean_stack, TypeLists...>>(L);
18382 template <
typename F,
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename =
void>
18384 template <
typename Fx,
typename... Args>
18385 static int call(
lua_State* L, Fx&& f, Args&&... args) {
18386 using uFx = meta::unqualified_t<Fx>;
18387 static constexpr
bool is_ref = is_lua_reference_v<uFx>;
18388 if constexpr (is_ref) {
18389 if constexpr (is_index) {
18390 return stack::push(L, std::forward<Fx>(f), std::forward<Args>(args)...);
18393 std::forward<Fx>(f) = stack::unqualified_get<F>(L, boost + (is_variable ? 3 : 1));
18399 using traits_type =
typename wrap::traits_type;
18400 using fp_t =
typename traits_type::function_pointer_type;
18401 constexpr
bool is_function_pointer_convertible = std::is_class_v<uFx> && std::is_convertible_v<std::decay_t<Fx>, fp_t>;
18402 if constexpr (is_function_pointer_convertible) {
18405 L, fx, std::forward<Args>(args)...);
18408 using returns_list =
typename wrap::returns_list;
18409 using args_list =
typename wrap::free_args_list;
18410 using caller =
typename wrap::caller;
18411 return stack::call_into_lua<checked, clean_stack>(
18412 returns_list(), args_list(), L, boost + 1, caller(), std::forward<Fx>(f), std::forward<Args>(args)...);
18418 template <
typename T,
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18420 template <
typename F>
18422 if constexpr (is_index) {
18423 constexpr
bool is_stack = is_stack_based_v<meta::unqualified_t<decltype(detail::unwrap(f.value()))>>;
18424 if constexpr (clean_stack && !is_stack) {
18427 return stack::push_reference(L, detail::unwrap(f.value()));
18430 if constexpr (std::is_const_v<meta::unwrapped_t<T>>) {
18432 return luaL_error(L,
"sol: cannot write to a readonly (const) variable");
18435 using R = meta::unwrapped_t<T>;
18436 if constexpr (std::is_assignable_v<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>) {
18437 detail::unwrap(f.value()) = stack::unqualified_get<meta::unwrapped_t<T>>(L, boost + (is_variable ? 3 : 1));
18444 return luaL_error(L,
"sol: cannot write to this variable: copy assignment/constructor not available");
18451 template <
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18453 static int call(
lua_State* L, lua_CFunction_ref f) {
18458 template <
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18460 static int call(
lua_State* L, lua_CFunction f) {
18465 #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) 18466 template <
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18468 static int call(
lua_State* L, detail::lua_CFunction_noexcept f) {
18472 #endif // noexcept function types 18474 template <
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18477 return luaL_error(L, is_index ?
"sol: cannot read from a writeonly property" :
"sol: cannot write to a readonly property");
18481 template <
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18484 return function_detail::no_construction_error(L);
18488 template <
typename... Args,
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18496 template <
typename T,
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18498 static int call(
lua_State* L, std::reference_wrapper<T> f) {
18500 return alcw.call(L, f.get());
18504 template <
typename T,
typename F,
bool is_index,
bool is_variable,
bool checked = detail::default_safe_function_calls,
int boost = 0,
18505 bool clean_stack =
true,
typename =
void>
18507 template <
typename Fx,
typename... Args>
18508 static int call(
lua_State* L, Fx&& fx, Args&&... args) {
18509 if constexpr (std::is_member_function_pointer_v<F>) {
18511 using object_type =
typename wrap::object_type;
18512 if constexpr (
sizeof...(Args) < 1) {
18513 using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>;
18514 static_assert(std::is_base_of_v<object_type, Ta>,
18515 "It seems like you might have accidentally bound a class type with a member function method that does not correspond to the " 18516 "class. For example, there could be a small type in your new_usertype<T>(...) binding, where you specify one class \"T\" " 18517 "but then bind member methods from a complete unrelated class. Check things over!");
18518 #if SOL_IS_ON(SOL_SAFE_USERTYPE) 18519 auto maybeo = stack::check_get<Ta*>(L, 1);
18520 if (!maybeo || maybeo.value() ==
nullptr) {
18521 return luaL_error(L,
18522 "sol: received nil for 'self' argument (use ':' for accessing member functions, make sure member variables are " 18523 "preceeded by the " 18524 "actual object with '.' syntax)");
18526 object_type* o =
static_cast<object_type*
>(maybeo.value());
18527 return call(L, std::forward<Fx>(fx), *o);
18529 object_type& o =
static_cast<object_type&
>(*stack::unqualified_get<non_null<Ta*>>(L, 1));
18530 return call(L, std::forward<Fx>(fx), o);
18534 using returns_list =
typename wrap::returns_list;
18535 using args_list =
typename wrap::args_list;
18536 using caller =
typename wrap::caller;
18537 return stack::call_into_lua<checked, clean_stack>(
18538 returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward<Fx>(fx), std::forward<Args>(args)...);
18541 else if constexpr (std::is_member_object_pointer_v<F>) {
18543 using object_type =
typename wrap::object_type;
18544 if constexpr (is_index) {
18545 if constexpr (
sizeof...(Args) < 1) {
18546 using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>;
18547 static_assert(std::is_base_of_v<object_type, Ta>,
18548 "It seems like you might have accidentally bound a class type with a member function method that does not correspond " 18549 "to the class. For example, there could be a small type in your new_usertype<T>(...) binding, where you specify one " 18550 "class \"T\" but then bind member methods from a complete unrelated class. Check things over!");
18551 #if SOL_IS_ON(SOL_SAFE_USERTYPE) 18552 auto maybeo = stack::check_get<Ta*>(L, 1);
18553 if (!maybeo || maybeo.value() ==
nullptr) {
18555 return luaL_error(L,
"sol: 'self' argument is lua_nil (bad '.' access?)");
18557 return luaL_error(L,
"sol: 'self' argument is lua_nil (pass 'self' as first argument)");
18559 object_type* o =
static_cast<object_type*
>(maybeo.value());
18560 return call(L, std::forward<Fx>(fx), *o);
18562 object_type& o =
static_cast<object_type&
>(*stack::get<non_null<Ta*>>(L, 1));
18563 return call(L, std::forward<Fx>(fx), o);
18567 using returns_list =
typename wrap::returns_list;
18568 using caller =
typename wrap::caller;
18569 return stack::call_into_lua<checked, clean_stack>(returns_list(),
18572 boost + (is_variable ? 3 : 2),
18574 std::forward<Fx>(fx),
18575 std::forward<Args>(args)...);
18580 using return_type =
typename traits_type::return_type;
18581 constexpr
bool ret_is_const = std::is_const_v<std::remove_reference_t<return_type>>;
18582 if constexpr (ret_is_const) {
18584 (void)detail::swallow { 0, (
static_cast<void>(args), 0)... };
18585 return luaL_error(L,
"sol: cannot write to a readonly (const) variable");
18588 using u_return_type = meta::unqualified_t<return_type>;
18589 constexpr
bool is_assignable = std::is_copy_assignable_v<u_return_type> || std::is_array_v<u_return_type>;
18590 if constexpr (!is_assignable) {
18592 (void)detail::swallow { 0, ((void)args, 0)... };
18593 return luaL_error(L,
"sol: cannot write to this variable: copy assignment/constructor not available");
18596 using args_list =
typename wrap::args_list;
18597 using caller =
typename wrap::caller;
18598 if constexpr (
sizeof...(Args) > 0) {
18599 return stack::call_into_lua<checked, clean_stack>(
types<void>(),
18602 boost + (is_variable ? 3 : 2),
18604 std::forward<Fx>(fx),
18605 std::forward<Args>(args)...);
18608 using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>;
18609 #if SOL_IS_ON(SOL_SAFE_USERTYPE) 18610 auto maybeo = stack::check_get<Ta*>(L, 1);
18611 if (!maybeo || maybeo.value() ==
nullptr) {
18613 return luaL_error(L,
"sol: received nil for 'self' argument (bad '.' access?)");
18615 return luaL_error(L,
"sol: received nil for 'self' argument (pass 'self' as first argument)");
18617 object_type* po =
static_cast<object_type*
>(maybeo.value());
18618 object_type& o = *po;
18620 object_type& o =
static_cast<object_type&
>(*stack::get<non_null<Ta*>>(L, 1));
18623 return stack::call_into_lua<checked, clean_stack>(
18624 types<void>(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward<Fx>(fx), o);
18632 return alcw.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
18637 template <
typename T,
typename F,
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18641 using object_type =
typename wrap::object_type;
18644 if constexpr (!is_index) {
18646 return luaL_error(L,
"sol: cannot write to a sol::readonly variable");
18650 return lcw.call(L, std::move(rw.value()));
18655 if constexpr (!is_index) {
18657 return call(L, std::move(rw));
18661 return lcw.call(L, rw.value(), o);
18666 if constexpr (!is_index) {
18668 return luaL_error(L,
"sol: cannot write to a sol::readonly variable");
18672 return lcw.call(L, rw.value());
18677 if constexpr (!is_index) {
18679 return call(L, rw);
18683 return lcw.call(L, rw.value(), o);
18688 template <
typename T,
typename... Args,
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18694 int argcount = lua_gettop(L);
18696 argcount -=
static_cast<int>(syntax);
18698 T* obj = detail::usertype_allocate<T>(L);
18708 construct_match<T, Args...>(
18711 userdataref.push();
18716 template <
typename T,
typename... Cxs,
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18721 template <
typename Fx, std::size_t I,
typename... R,
typename... Args>
18724 T* obj = detail::usertype_allocate<T>(L);
18729 auto& func = std::get<I>(f.functions);
18734 userdataref.push();
18741 int syntaxval =
static_cast<int>(syntax);
18742 int argcount = lua_gettop(L) - syntaxval;
18743 return construct_match<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f);
18747 template <
typename T,
typename Fx,
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18750 template <
typename F>
18752 if constexpr (std::is_void_v<Fx>) {
18753 return detail::usertype_alloc_destroy<T>(L);
18756 using uFx = meta::unqualified_t<Fx>;
18758 return lcw.call(L, std::forward<F>(f).fx);
18763 template <
typename T,
typename... Fs,
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18768 template <
typename Fx, std::size_t I,
typename... R,
typename... Args>
18770 auto& f = std::get<I>(fx.functions);
18776 return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L), 1, fx);
18780 template <
typename T,
typename... Fs,
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18785 template <
typename Fx, std::size_t I,
typename... R,
typename... Args>
18787 auto& f = std::get<I>(fx.functions);
18793 return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L) - boost, 1 + boost, fx);
18797 template <
typename T,
typename R,
typename W,
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18799 typedef meta::conditional_t<is_index, R, W> P;
18800 typedef meta::unqualified_t<P> U;
18803 typedef meta::unqualified_t<typename traits_type::template arg_at<0>> object_type;
18805 template <
typename F,
typename... Args>
18806 static int call(
lua_State* L, F&& f, Args&&... args) {
18811 std::is_member_pointer<U>>::value;
18812 if constexpr (is_specialized) {
18813 if constexpr (is_index) {
18814 decltype(
auto) p = f.read();
18816 return lcw.call(L, p, std::forward<Args>(args)...);
18819 decltype(
auto) p = f.write();
18821 return lcw.call(L, p, std::forward<Args>(args)...);
18826 meta::boolean<lua_type_of<meta::unwrap_unqualified_t<object_type>>::value != type::userdata>>::value;
18827 if constexpr (non_class_object_type) {
18829 using args_list =
typename traits_type::free_args_list;
18830 using returns_list =
typename wrap::returns_list;
18832 if constexpr (is_index) {
18833 decltype(
auto) pf = f.read();
18834 return stack::call_into_lua<checked, clean_stack>(
18835 returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf);
18838 decltype(
auto) pf = f.write();
18839 return stack::call_into_lua<checked, clean_stack>(
18840 returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf);
18844 using args_list = meta::pop_front_type_t<typename traits_type::free_args_list>;
18846 using Oa = std::remove_pointer_t<object_type>;
18847 #if SOL_IS_ON(SOL_SAFE_USERTYPE) 18848 auto maybeo = stack::check_get<Ta*>(L, 1);
18849 if (!maybeo || maybeo.value() ==
nullptr) {
18851 return luaL_error(L,
"sol: 'self' argument is lua_nil (bad '.' access?)");
18853 return luaL_error(L,
"sol: 'self' argument is lua_nil (pass 'self' as first argument)");
18855 Oa* o =
static_cast<Oa*
>(maybeo.value());
18857 Oa* o =
static_cast<Oa*
>(stack::get<non_null<Ta*>>(L, 1));
18859 using returns_list =
typename wrap::returns_list;
18861 if constexpr (is_index) {
18862 decltype(
auto) pf = f.read();
18863 return stack::call_into_lua<checked, clean_stack>(
18867 decltype(
auto) pf = f.write();
18868 return stack::call_into_lua<checked, clean_stack>(
18876 template <
typename T,
typename V,
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18880 template <
typename... Args>
18881 static int call(
lua_State* L, F& fx, Args&&... args) {
18886 template <
typename T,
typename F,
typename... Policies,
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18890 template <std::size_t... In>
18891 static int call(std::index_sequence<In...>,
lua_State* L,
P& fx) {
18893 (void)detail::swallow { int(), (policy_detail::handle_policy(std::get<In>(fx.policies), L, pushed), int())... };
18898 typedef typename P::indices indices;
18899 return call(indices(), L, fx);
18903 template <
typename T,
typename Y,
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18905 template <
typename F>
18911 template <
typename T,
typename Sig,
typename P,
bool is_index,
bool is_variable,
bool checked,
int boost,
bool clean_stack,
typename C>
18915 return lcw.call(L, std::get<0>(f.arguments));
18920 return lcw.call(L, std::get<0>(f.arguments));
18925 return lcw.call(L, std::get<0>(std::move(f.arguments)));
18929 template <
typename T,
bool is_index,
bool is_variable,
int boost = 0,
bool checked = detail::default_safe_function_calls,
bool clean_stack =
true,
18930 typename Fx,
typename... Args>
18931 inline int call_wrapped(
lua_State* L, Fx&& fx, Args&&... args) {
18932 using uFx = meta::unqualified_t<Fx>;
18933 if constexpr (meta::is_specialization_of_v<uFx, yielding_t>) {
18934 using real_fx = meta::unqualified_t<decltype(std::forward<Fx>(fx).func)>;
18936 return lcw.call(L, std::forward<Fx>(fx).func, std::forward<Args>(args)...);
18940 return lcw.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
18944 template <
typename T,
bool is_index,
bool is_variable,
typename F,
int start = 1,
bool checked = detail::default_safe_function_calls,
18945 bool clean_stack =
true>
18947 auto& fx = stack::unqualified_get<user<F>>(L,
upvalue_index(start));
18948 using uFx = meta::unqualified_t<F>;
18949 int nr = call_wrapped<T, is_index, is_variable, 0, checked, clean_stack>(L, fx);
18950 if constexpr (meta::is_specialization_of_v<uFx, yielding_t>) {
18951 return lua_yield(L, nr);
18958 template <
typename T,
typename =
void>
18961 template <
typename T>
18962 struct is_var_bind<T,
std::enable_if_t<std::is_member_object_pointer<T>::value>> : std::true_type { };
18964 template <
typename T>
18965 struct is_var_bind<T, std::enable_if_t<is_lua_reference_or_proxy<T>::value>> : std::true_type { };
18970 template <
typename R,
typename W>
18973 template <
typename T>
18976 template <
typename T>
18979 template <
typename F,
typename... Policies>
18983 template <
typename T>
18986 template <
typename T>
18989 template <
typename T>
18997 namespace function_detail {
18998 template <
typename F, F fx>
18999 inline int call_wrapper_variable(std::false_type,
lua_State* L) {
19001 typedef typename traits_type::args_list args_list;
19002 typedef meta::tuple_types<typename traits_type::return_type> return_type;
19003 return stack::call_into_lua(return_type(), args_list(), L, 1, fx);
19006 template <
typename R,
typename V, V,
typename T>
19007 inline int call_set_assignable(std::false_type, T&&,
lua_State* L) {
19008 return luaL_error(L,
"cannot write to this type: copy assignment/constructor not available");
19011 template <
typename R,
typename V, V variable,
typename T>
19012 inline int call_set_assignable(std::true_type,
lua_State* L, T&& mem) {
19013 (mem.*variable) = stack::get<R>(L, 2);
19017 template <
typename R,
typename V, V,
typename T>
19018 inline int call_set_variable(std::false_type,
lua_State* L, T&&) {
19019 return luaL_error(L,
"cannot write to a const variable");
19022 template <
typename R,
typename V, V variable,
typename T>
19023 inline int call_set_variable(std::true_type,
lua_State* L, T&& mem) {
19024 return call_set_assignable<R, V, variable>(std::is_assignable<std::add_lvalue_reference_t<R>, R>(), L, std::forward<T>(mem));
19027 template <
typename V, V variable>
19028 inline int call_wrapper_variable(std::true_type,
lua_State* L) {
19030 typedef typename traits_type::object_type T;
19031 typedef typename traits_type::return_type R;
19032 auto& mem = stack::get<T>(L, 1);
19033 switch (lua_gettop(L)) {
19035 decltype(
auto) r = (mem.*variable);
19036 stack::push_reference(L, std::forward<decltype(r)>(r));
19040 return call_set_variable<R, V, variable>(meta::neg<std::is_const<R>>(), L, mem);
19042 return luaL_error(L,
"incorrect number of arguments to member variable function call");
19046 template <
typename F, F fx>
19047 inline int call_wrapper_function(std::false_type,
lua_State* L) {
19048 return call_wrapper_variable<F, fx>(std::is_member_object_pointer<F>(), L);
19051 template <
typename F, F fx>
19052 inline int call_wrapper_function(std::true_type,
lua_State* L) {
19053 return call_detail::call_wrapped<void, false, false>(L, fx);
19056 template <
typename F, F fx>
19058 return call_wrapper_function<F, fx>(std::is_member_function_pointer<meta::unqualified_t<F>>(), L);
19061 template <
typename... Fxs>
19063 template <
typename Fx, std::size_t I,
typename R,
typename... Args>
19065 typedef meta::at_in_pack_t<I, Fxs...> target;
19066 return target::call(L);
19070 template <
typename F, F fx>
19071 inline int c_call_raw(std::true_type,
lua_State* L) {
19075 template <
typename F, F fx>
19076 inline int c_call_raw(std::false_type,
lua_State* L) {
19078 return detail::trampoline(L, function_detail::call_wrapper_entry<F, fx>);
19080 return detail::typed_static_trampoline<decltype(&function_detail::call_wrapper_entry<F, fx>), (&function_detail::call_wrapper_entry<F, fx>)>(L);
19081 #endif // fuck you clang :c 19086 template <
typename F, F fx>
19088 typedef meta::unqualified_t<F> Fu;
19089 typedef std::integral_constant<bool,
19090 std::is_same<Fu, lua_CFunction>::value
19091 #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) 19092 || std::is_same<Fu, detail::lua_CFunction_noexcept>::value
19096 return function_detail::c_call_raw<F, fx>(is_raw(), L);
19099 template <
typename F, F f>
19103 static int call(
lua_State* L) noexcept(noexcept(c_call<type, f>(L))) {
19104 return c_call<type, f>(L);
19108 template <
typename... Fxs>
19110 if constexpr (
sizeof...(Fxs) < 2) {
19111 using target = meta::at_in_pack_t<0, Fxs...>;
19112 return target::call(L);
19125 namespace sol {
namespace function_detail {
19126 template <
typename Function>
19128 using function_type = std::remove_pointer_t<std::decay_t<Function>>;
19132 #if SOL_IS_ON(SOL_COMPILER_VCXX) 19135 noexcept(traits_type::is_noexcept)
19138 auto udata = stack::stack_detail::get_as_upvalues<function_type*>(L);
19139 function_type* fx = udata.first;
19140 return call_detail::call_wrapped<void, true, false>(L, fx);
19143 template <
bool is_yielding,
bool no_trampoline>
19146 if constexpr (no_trampoline) {
19150 nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L);
19153 return lua_yield(L, nr);
19161 template <
typename T,
typename Function>
19163 typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
19167 #if SOL_IS_ON(SOL_COMPILER_VCXX) 19170 noexcept(traits_type::is_noexcept)
19178 function_type& memfx = stack::get<user<function_type>>(L,
upvalue_index(2));
19179 auto& item = *
static_cast<T*
>(stack::get<void*>(L,
upvalue_index(3)));
19180 return call_detail::call_wrapped<T,
true,
false, -1>(L, memfx, item);
19183 template <
bool is_yielding,
bool no_trampoline>
19185 #if SOL_IS_ON(SOL_COMPILER_VCXX) 19188 noexcept(traits_type::is_noexcept)
19192 if constexpr (no_trampoline) {
19196 nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L);
19199 return lua_yield(L, nr);
19207 #if SOL_IS_ON(SOL_COMPILER_VCXX) 19210 noexcept(traits_type::is_noexcept)
19217 template <
typename T,
typename Function>
19219 typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
19223 #if SOL_IS_ON(SOL_COMPILER_VCXX) 19226 noexcept(traits_type::is_noexcept)
19234 auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L);
19235 auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second);
19236 auto& mem = *objdata.first;
19237 function_type& var = memberdata.first;
19238 switch (lua_gettop(L)) {
19240 return call_detail::call_wrapped<T,
true,
false, -1>(L, var, mem);
19242 return call_detail::call_wrapped<T,
false,
false, -1>(L, var, mem);
19244 return luaL_error(L,
"sol: incorrect number of arguments to member variable function");
19248 template <
bool is_yielding,
bool no_trampoline>
19250 #if SOL_IS_ON(SOL_COMPILER_VCXX) 19253 noexcept(traits_type::is_noexcept)
19257 if constexpr (no_trampoline) {
19261 nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L);
19264 return lua_yield(L, nr);
19272 #if SOL_IS_ON(SOL_COMPILER_VCXX) 19275 noexcept(traits_type::is_noexcept)
19282 template <
typename T,
typename Function>
19284 typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
19288 #if SOL_IS_ON(SOL_COMPILER_VCXX) 19291 noexcept(traits_type::is_noexcept)
19299 auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L);
19300 auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second);
19301 auto& mem = *objdata.first;
19302 function_type& var = memberdata.first;
19303 switch (lua_gettop(L)) {
19305 return call_detail::call_wrapped<T,
true,
false, -1>(L, var, mem);
19307 return luaL_error(L,
"sol: incorrect number of arguments to member variable function");
19311 template <
bool is_yielding,
bool no_trampoline>
19313 #if SOL_IS_ON(SOL_COMPILER_VCXX) 19316 noexcept(traits_type::is_noexcept)
19320 if constexpr (no_trampoline) {
19324 nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L);
19327 return lua_yield(L, nr);
19335 #if SOL_IS_ON(SOL_COMPILER_VCXX) 19338 noexcept(traits_type::is_noexcept)
19345 template <
typename T,
typename Function>
19347 typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
19351 #if SOL_IS_ON(SOL_COMPILER_VCXX) 19354 noexcept(traits_type::is_noexcept)
19359 function_type& memfx = stack::get<user<function_type>>(L,
upvalue_index(2));
19360 return call_detail::call_wrapped<T, false, false>(L, memfx);
19363 template <
bool is_yielding,
bool no_trampoline>
19365 #if SOL_IS_ON(SOL_COMPILER_VCXX) 19368 noexcept(traits_type::is_noexcept)
19372 if constexpr (no_trampoline) {
19376 nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L);
19379 return lua_yield(L, nr);
19387 #if SOL_IS_ON(SOL_COMPILER_VCXX) 19390 noexcept(traits_type::is_noexcept)
19397 template <
typename T,
typename Function>
19399 typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
19401 static int real_call(
lua_State* L) noexcept(std::is_nothrow_copy_assignable_v<T>) {
19404 auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L);
19405 function_type& var = memberdata.first;
19406 switch (lua_gettop(L)) {
19408 return call_detail::call_wrapped<T, true, false>(L, var);
19410 return call_detail::call_wrapped<T, false, false>(L, var);
19412 return luaL_error(L,
"sol: incorrect number of arguments to member variable function");
19416 template <
bool is_yielding,
bool no_trampoline>
19417 static int call(
lua_State* L) noexcept(std::is_nothrow_copy_assignable_v<T>) {
19419 if constexpr (no_trampoline) {
19423 nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L);
19426 return lua_yield(L, nr);
19433 int operator()(
lua_State* L) noexcept(std::is_nothrow_copy_assignable_v<T>) {
19438 template <
typename T,
typename Function>
19440 typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
19443 static int real_call(
lua_State* L) noexcept(std::is_nothrow_copy_assignable_v<T>) {
19446 auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L);
19447 function_type& var = memberdata.first;
19448 switch (lua_gettop(L)) {
19450 return call_detail::call_wrapped<T, true, false>(L, var);
19452 return luaL_error(L,
"sol: incorrect number of arguments to member variable function");
19456 template <
bool is_yielding,
bool no_trampoline>
19457 static int call(
lua_State* L) noexcept(std::is_nothrow_copy_assignable_v<T>) {
19459 if constexpr (no_trampoline) {
19463 nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L);
19466 return lua_yield(L, nr);
19473 int operator()(
lua_State* L) noexcept(std::is_nothrow_copy_assignable_v<T>) {
19483 namespace sol {
namespace function_detail {
19484 template <
typename Func,
bool is_yielding,
bool no_trampoline>
19486 typedef std::decay_t<meta::unwrap_unqualified_t<Func>> function_type;
19487 function_type invocation;
19489 template <
typename... Args>
19490 functor_function(function_type f, Args&&... args) noexcept(std::is_nothrow_constructible_v<function_type, function_type, Args...>)
19491 : invocation(std::move(f), std::forward<Args>(args)...) {
19494 static int call(
lua_State* L,
functor_function&
self) noexcept(noexcept(call_detail::call_wrapped<void, true, false>(L,
self.invocation))) {
19495 int nr = call_detail::call_wrapped<void, true, false>(L,
self.invocation);
19497 return lua_yield(L, nr);
19504 int operator()(
lua_State* L) noexcept(noexcept(call_detail::call_wrapped<void, true, false>(L, invocation))) {
19505 if constexpr (no_trampoline) {
19506 return call(L, *
this);
19509 return detail::trampoline(L, &call, *
this);
19514 template <
typename T,
typename Function,
bool is_yielding,
bool no_trampoline>
19516 typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
19517 typedef meta::function_return_t<function_type> return_type;
19518 typedef meta::function_args_t<function_type> args_lists;
19520 function_type invocation;
19523 template <
typename... Args>
19525 std::is_nothrow_constructible_v<function_type, function_type>&& std::is_nothrow_constructible_v<T, Args...>)
19526 : invocation(std::move(f)), member(std::forward<Args>(args)...) {
19530 #if SOL_IS_ON(SOL_COMPILER_VCXX) 19533 noexcept(traits_type::is_noexcept)
19536 int nr = call_detail::call_wrapped<T,
true,
false, -1>(L,
self.invocation, detail::unwrap(detail::deref(
self.member)));
19538 return lua_yield(L, nr);
19546 #if SOL_IS_ON(SOL_COMPILER_VCXX) 19549 noexcept(traits_type::is_noexcept)
19552 if constexpr (no_trampoline) {
19553 return call(L, *
this);
19556 return detail::trampoline(L, &call, *
this);
19561 template <
typename T,
typename Function,
bool is_yielding,
bool no_trampoline>
19563 typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
19564 typedef typename meta::bind_traits<function_type>::return_type return_type;
19568 typedef std::add_lvalue_reference_t<meta::unwrapped_t<std::remove_reference_t<decltype(detail::deref(member))>>> M;
19570 template <
typename... Args>
19572 std::is_nothrow_constructible_v<function_type, function_type>&& std::is_nothrow_constructible_v<T, Args...>)
19573 : var(std::move(v)), member(std::forward<Args>(args)...) {
19579 M mem = detail::unwrap(detail::deref(
self.member));
19580 switch (lua_gettop(L)) {
19582 nr = call_detail::call_wrapped<T,
true,
false, -1>(L,
self.var, mem);
19585 nr = call_detail::call_wrapped<T,
false,
false, -1>(L,
self.var, mem);
19588 nr = luaL_error(L,
"sol: incorrect number of arguments to member variable function");
19593 return lua_yield(L, nr);
19600 int operator()(
lua_State* L) noexcept(std::is_nothrow_copy_assignable_v<T>) {
19601 if constexpr (no_trampoline) {
19602 return call(L, *
this);
19605 return detail::trampoline(L, &call, *
this);
19615 namespace sol {
namespace function_detail {
19616 template <
int start_skew,
typename... Functions>
19618 typedef std::tuple<Functions...> overload_list;
19619 typedef std::make_index_sequence<
sizeof...(Functions)> indices;
19620 overload_list overloads;
19628 template <
typename Fx, std::size_t I,
typename... R,
typename... Args>
19630 auto& func = std::get<I>(ol);
19631 int nr = call_detail::call_wrapped<void, true, false, start_skew>(L, func);
19636 template <
typename... Args>
19637 int operator()(Args&&... args)
const {
19638 return call(std::forward<Args>(args)...);
19644 return call_detail::overload_match<Functions...>(call_obj, L, 1 + start_skew, overloads);
19659 template <
typename R,
typename... Args,
typename F,
typename = std::invoke_result_t<meta::unqualified_t<F>, Args...>>
19660 inline constexpr
auto resolve_i(
types<R(Args...)>, F&&) -> R (meta::unqualified_t<F>::*)(Args...) {
19661 using Sig = R(Args...);
19662 typedef meta::unqualified_t<F> Fu;
19663 return static_cast<Sig Fu::*
>(&Fu::operator());
19666 template <
typename F,
typename U = meta::unqualified_t<F>>
19667 inline constexpr
auto resolve_f(std::true_type, F&& f)
19668 -> decltype(resolve_i(
types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) {
19669 return resolve_i(
types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f));
19672 template <
typename F>
19673 inline constexpr
void resolve_f(std::false_type, F&&) {
19674 static_assert(meta::call_operator_deducible_v<F>,
"Cannot use no-template-parameter call with an overloaded functor: specify the signature");
19677 template <
typename F,
typename U = meta::unqualified_t<F>>
19678 inline constexpr
auto resolve_i(
types<>, F&& f) -> decltype(resolve_f(meta::call_operator_deducible<U>(), std::forward<F>(f))) {
19679 return resolve_f(meta::call_operator_deducible<U> {}, std::forward<F>(f));
19682 template <
typename... Args,
typename F,
typename R = std::invoke_result_t<F&, Args...>>
19683 inline constexpr
auto resolve_i(
types<Args...>, F&& f) -> decltype(resolve_i(
types<R(Args...)>(), std::forward<F>(f))) {
19684 return resolve_i(
types<R(Args...)>(), std::forward<F>(f));
19687 template <
typename Sig,
typename C>
19688 inline constexpr Sig C::*resolve_v(std::false_type, Sig C::*mem_func_ptr) {
19689 return mem_func_ptr;
19692 template <
typename Sig,
typename C>
19693 inline constexpr Sig C::*resolve_v(std::true_type, Sig C::*mem_variable_ptr) {
19694 return mem_variable_ptr;
19698 template <
typename... Args,
typename R>
19699 inline constexpr
auto resolve(R fun_ptr(Args...)) -> R (*)(Args...) {
19703 template <
typename Sig>
19704 inline constexpr Sig* resolve(Sig* fun_ptr) {
19708 template <
typename... Args,
typename R,
typename C>
19709 inline constexpr
auto resolve(R (C::*mem_ptr)(Args...)) -> R (C::*)(Args...) {
19713 template <
typename Sig,
typename C>
19714 inline constexpr Sig C::*resolve(Sig C::*mem_ptr) {
19715 return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr);
19718 template <
typename... Sig,
typename F, meta::disable<std::is_function<meta::unqualified_t<F>>> = meta::enabler>
19719 inline constexpr
auto resolve(F&& f) -> decltype(detail::resolve_i(
types<Sig...>(), std::forward<F>(f))) {
19720 return detail::resolve_i(
types<Sig...>(), std::forward<F>(f));
19728 template <
typename R,
typename... Args,
typename F,
typename = std::invoke_result_t<meta::unqualified_t<F>, Args...>>
19729 inline auto resolve_i(
types<R(Args...)>, F&&) -> R (meta::unqualified_t<F>::*)(Args...) {
19730 using Sig = R(Args...);
19731 typedef meta::unqualified_t<F> Fu;
19732 return static_cast<Sig Fu::*
>(&Fu::operator());
19735 template <
typename F,
typename U = meta::unqualified_t<F>>
19736 inline auto resolve_f(std::true_type, F&& f)
19737 -> decltype(resolve_i(
types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) {
19738 return resolve_i(
types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f));
19741 template <
typename F>
19742 inline void resolve_f(std::false_type, F&&) {
19743 static_assert(meta::call_operator_deducible_v<F>,
"Cannot use no-template-parameter call with an overloaded functor: specify the signature");
19746 template <
typename F,
typename U = meta::unqualified_t<F>>
19747 inline auto resolve_i(
types<>, F&& f) -> decltype(resolve_f(meta::call_operator_deducible<U>(), std::forward<F>(f))) {
19748 return resolve_f(meta::call_operator_deducible<U> {}, std::forward<F>(f));
19751 template <
typename... Args,
typename F,
typename R = std::invoke_result_t<F&, Args...>>
19752 inline auto resolve_i(
types<Args...>, F&& f) -> decltype(resolve_i(
types<R(Args...)>(), std::forward<F>(f))) {
19753 return resolve_i(
types<R(Args...)>(), std::forward<F>(f));
19756 template <
typename Sig,
typename C>
19757 inline Sig C::*resolve_v(std::false_type, Sig C::*mem_func_ptr) {
19758 return mem_func_ptr;
19761 template <
typename Sig,
typename C>
19762 inline Sig C::*resolve_v(std::true_type, Sig C::*mem_variable_ptr) {
19763 return mem_variable_ptr;
19767 template <
typename... Args,
typename R>
19768 inline auto resolve(R fun_ptr(Args...)) -> R (*)(Args...) {
19772 template <
typename Sig>
19773 inline Sig* resolve(Sig* fun_ptr) {
19777 template <
typename... Args,
typename R,
typename C>
19778 inline auto resolve(R (C::*mem_ptr)(Args...)) -> R (C::*)(Args...) {
19782 template <
typename Sig,
typename C>
19783 inline Sig C::*resolve(Sig C::*mem_ptr) {
19784 return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr);
19787 template <
typename... Sig,
typename F>
19788 inline auto resolve(F&& f) -> decltype(detail::resolve_i(
types<Sig...>(), std::forward<F>(f))) {
19789 return detail::resolve_i(
types<Sig...>(), std::forward<F>(f));
19799 namespace function_detail {
19800 template <
typename T>
19807 template <
bool yielding>
19809 lua_CFunction cf = lua_tocfunction(L, lua_upvalueindex(2));
19811 if constexpr (yielding) {
19812 return lua_yield(L, nr);
19819 template <
bool yielding>
19820 int lua_c_noexcept_wrapper(
lua_State* L) noexcept {
19821 detail::lua_CFunction_noexcept cf =
reinterpret_cast<detail::lua_CFunction_noexcept
>(lua_tocfunction(L, lua_upvalueindex(2)));
19823 if constexpr (yielding) {
19824 return lua_yield(L, nr);
19833 template <
bool is_yielding,
bool no_trampoline,
typename Fx,
typename... Args>
19834 void select(
lua_State* L, Fx&& fx, Args&&... args);
19836 template <
bool is_yielding,
bool no_trampoline,
typename Fx,
typename... Args>
19837 void select_set_fx(
lua_State* L, Args&&... args) {
19838 lua_CFunction freefunc = no_trampoline ? function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>
19839 : detail::static_trampoline<function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>>;
19842 upvalues += stack::push(L,
nullptr);
19843 upvalues += stack::push<user<Fx>>(L, std::forward<Args>(args)...);
19844 stack::push(L,
c_closure(freefunc, upvalues));
19847 template <
bool is_yielding,
bool no_trampoline,
typename R,
typename... A,
typename Fx,
typename... Args>
19848 void select_convertible(
types<R(A...)>,
lua_State* L, Fx&& fx, Args&&... args) {
19849 using dFx = std::decay_t<meta::unwrap_unqualified_t<Fx>>;
19850 using fx_ptr_t = R (*)(A...);
19851 constexpr
bool is_convertible = std::is_convertible_v<dFx, fx_ptr_t>;
19852 if constexpr (is_convertible) {
19853 fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
19854 select<is_yielding, no_trampoline>(L, std::move(fxptr), std::forward<Args>(args)...);
19858 select_set_fx<is_yielding, no_trampoline, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
19862 template <
bool is_yielding,
bool no_trampoline,
typename Fx,
typename... Args>
19864 typedef meta::function_signature_t<meta::unwrap_unqualified_t<Fx>> Sig;
19865 select_convertible<is_yielding, no_trampoline>(
types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
19868 template <
bool is_yielding,
bool no_trampoline,
typename Fx,
typename... Args>
19869 void select_member_variable(
lua_State* L, Fx&& fx, Args&&... args) {
19870 using uFx = meta::unqualified_t<Fx>;
19871 if constexpr (
sizeof...(Args) < 1) {
19872 using C =
typename meta::bind_traits<uFx>::object_type;
19876 upvalues += stack::push(L,
nullptr);
19877 upvalues += stack::stack_detail::push_as_upvalues(L, fx);
19878 stack::push(L,
c_closure(freefunc, upvalues));
19880 else if constexpr (
sizeof...(Args) < 2) {
19882 constexpr
bool is_reference = meta::is_specialization_of_v<Tu, std::reference_wrapper> || std::is_pointer_v<Tu>;
19883 if constexpr (meta::is_specialization_of_v<Tu, function_detail::class_indicator>) {
19884 lua_CFunction freefunc
19888 upvalues += stack::push(L,
nullptr);
19889 upvalues += stack::stack_detail::push_as_upvalues(L, fx);
19890 stack::push(L,
c_closure(freefunc, upvalues));
19892 else if constexpr (is_reference) {
19893 typedef std::decay_t<Fx> dFx;
19894 dFx memfxptr(std::forward<Fx>(fx));
19895 auto userptr = detail::ptr(std::forward<Args>(args)...);
19897 meta::unqualified_t<Fx>>::template call<is_yielding, no_trampoline>;
19900 upvalues += stack::push(L,
nullptr);
19901 upvalues += stack::stack_detail::push_as_upvalues(L, memfxptr);
19902 upvalues += stack::push(L, static_cast<void const*>(userptr));
19903 stack::push(L,
c_closure(freefunc, upvalues));
19906 using clean_fx = std::remove_pointer_t<std::decay_t<Fx>>;
19908 select_set_fx<is_yielding, no_trampoline, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
19912 using C =
typename meta::bind_traits<uFx>::object_type;
19913 using clean_fx = std::remove_pointer_t<std::decay_t<Fx>>;
19915 select_set_fx<is_yielding, no_trampoline, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
19919 template <
bool is_yielding,
bool no_trampoline,
typename Fx,
typename T,
typename... Args>
19920 void select_member_function_with(
lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
19921 using dFx = std::decay_t<Fx>;
19922 using Tu = meta::unqualified_t<T>;
19923 if constexpr (meta::is_specialization_of_v<Tu, function_detail::class_indicator>) {
19925 using C =
typename Tu::type;
19929 upvalues += stack::push(L,
nullptr);
19930 upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
19931 stack::push(L,
c_closure(freefunc, upvalues));
19934 constexpr
bool is_reference = meta::is_specialization_of_v<Tu, std::reference_wrapper> || std::is_pointer_v<Tu>;
19935 if constexpr (is_reference) {
19936 auto userptr = detail::ptr(std::forward<T>(obj));
19937 lua_CFunction freefunc
19941 upvalues += stack::push(L,
nullptr);
19942 upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
19944 stack::push(L,
c_closure(freefunc, upvalues));
19948 select_set_fx<is_yielding, no_trampoline, F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
19953 template <
bool is_yielding,
bool no_trampoline,
typename Fx,
typename... Args>
19954 void select_member_function(
lua_State* L, Fx&& fx, Args&&... args) {
19955 using dFx = std::decay_t<Fx>;
19956 if constexpr (
sizeof...(Args) < 1) {
19961 upvalues += stack::push(L,
nullptr);
19962 upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx));
19963 stack::push(L,
c_closure(freefunc, upvalues));
19966 select_member_function_with<is_yielding, no_trampoline>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
19970 template <
bool is_yielding,
bool no_trampoline,
typename Fx,
typename... Args>
19971 void select(
lua_State* L, Fx&& fx, Args&&... args) {
19972 using uFx = meta::unqualified_t<Fx>;
19973 if constexpr (is_lua_reference_v<uFx>) {
19975 stack::push(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
19977 else if constexpr (is_lua_c_function_v<uFx>) {
19978 if constexpr (no_trampoline) {
19981 upvalues += stack::push(L,
nullptr);
19982 upvalues += stack::push(L, std::forward<Fx>(fx));
19983 #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) 19984 if constexpr (std::is_nothrow_invocable_r_v<int, uFx, lua_State*>) {
19985 detail::lua_CFunction_noexcept cf = &lua_c_noexcept_wrapper<true>;
19986 lua_pushcclosure(L, reinterpret_cast<lua_CFunction>(cf), upvalues);
19991 lua_CFunction cf = &function_detail::lua_c_wrapper<true>;
19992 lua_pushcclosure(L, cf, upvalues);
19996 lua_pushcclosure(L, std::forward<Fx>(fx), 0);
20001 upvalues += stack::push(L,
nullptr);
20002 upvalues += stack::push(L, std::forward<Fx>(fx));
20003 #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) 20004 if constexpr (std::is_nothrow_invocable_r_v<int, uFx, lua_State*>) {
20005 detail::lua_CFunction_noexcept cf = &lua_c_noexcept_wrapper<is_yielding>;
20006 lua_pushcclosure(L, reinterpret_cast<lua_CFunction>(cf), upvalues);
20009 lua_CFunction cf = &function_detail::lua_c_wrapper<is_yielding>;
20010 lua_pushcclosure(L, cf, upvalues);
20013 lua_CFunction cf = &function_detail::lua_c_wrapper<is_yielding>;
20014 lua_pushcclosure(L, cf, upvalues);
20018 else if constexpr (std::is_function_v<std::remove_pointer_t<uFx>>) {
20019 std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...);
20023 upvalues += stack::push(L,
nullptr);
20024 upvalues += stack::stack_detail::push_as_upvalues(L, target);
20025 stack::push(L,
c_closure(freefunc, upvalues));
20027 else if constexpr (std::is_member_function_pointer_v<uFx>) {
20028 select_member_function<is_yielding, no_trampoline>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
20030 else if constexpr (meta::is_member_object_v<uFx>) {
20031 select_member_variable<is_yielding, no_trampoline>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
20034 select_convertible<is_yielding, no_trampoline>(
types<>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
20040 template <
typename... Sigs>
20042 template <
bool is_yielding,
typename Arg0,
typename... Args>
20043 static int push_yielding(
lua_State* L, Arg0&& arg0, Args&&... args) {
20044 if constexpr (meta::is_specialization_of_v<meta::unqualified_t<Arg0>, std::function>) {
20045 if constexpr (is_yielding) {
20046 return stack::push<meta::unqualified_t<Arg0>>(L, detail::yield_tag, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
20049 return stack::push(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
20053 function_detail::select<is_yielding, false>(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
20058 template <
typename Arg0,
typename... Args>
20059 static int push(
lua_State* L, Arg0&& arg0, Args&&... args) {
20061 push_yielding<true>(L, std::forward<Args>(args)...);
20063 else if constexpr (meta::is_specialization_of_v<meta::unqualified_t<Arg0>,
yielding_t>) {
20064 push_yielding<true>(L, std::forward<Arg0>(arg0).func, std::forward<Args>(args)...);
20067 push_yielding<false>(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
20073 template <
typename T>
20075 template <
typename... Args>
20077 if constexpr (meta::is_specialization_of_v<meta::unqualified_t<T>, std::function>) {
20078 return stack::push<T>(L, detail::yield_tag, f.func, std::forward<Args>(args)...);
20081 function_detail::select<true, false>(L, f.func, std::forward<Args>(args)...);
20086 template <
typename... Args>
20088 if constexpr (meta::is_specialization_of_v<meta::unqualified_t<T>, std::function>) {
20089 return stack::push<T>(L, detail::yield_tag, std::move(f.func), std::forward<Args>(args)...);
20092 function_detail::select<true, false>(L, std::move(f.func), std::forward<Args>(args)...);
20098 template <
typename T,
typename... Args>
20100 template <std::size_t... I,
typename FP>
20101 static int push_func(std::index_sequence<I...>,
lua_State* L, FP&& fp) {
20102 return stack::push<T>(L, std::get<I>(std::forward<FP>(fp).arguments)...);
20106 return push_func(std::make_index_sequence<
sizeof...(Args)>(), L, fp);
20110 return push_func(std::make_index_sequence<
sizeof...(Args)>(), L, std::move(fp));
20114 template <
typename Signature>
20120 function_detail::select_set_fx<true, false, TargetFunctor>(L, fx);
20123 return stack::push(L, lua_nil);
20128 function_detail::select_set_fx<true, false, TargetFunctor>(L, std::move(fx));
20131 return stack::push(L, lua_nil);
20134 static int push(
lua_State* L,
const std::function<Signature>& fx) {
20136 function_detail::select_set_fx<false, false, TargetFunctor>(L, fx);
20139 return stack::push(L, lua_nil);
20142 static int push(
lua_State* L, std::function<Signature>&& fx) {
20144 function_detail::select_set_fx<false, false, TargetFunctor>(L, std::move(fx));
20147 return stack::push(L, lua_nil);
20151 template <
typename Signature>
20153 template <
typename... Args>
20154 static int push(
lua_State* L, Args&&... args) {
20155 function_detail::select<false, false>(L, std::forward<Args>(args)...);
20160 template <
typename Signature>
20162 std::enable_if_t<meta::all<std::is_function<std::remove_pointer_t<Signature>>, meta::neg<std::is_same<Signature, lua_CFunction>>,
20163 meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>
20164 #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE)
20166 meta::neg<std::is_same<Signature, detail::lua_CFunction_noexcept>>,
20167 meta::neg<std::is_same<Signature, std::remove_pointer_t<detail::lua_CFunction_noexcept>>>
20170 template <
typename F>
20172 function_detail::select<false, true>(L, std::forward<F>(f));
20177 template <
typename... Functions>
20181 function_detail::select_set_fx<false, false, F>(L, std::move(
set.functions));
20187 function_detail::select_set_fx<false, false, F>(L,
set.functions);
20192 template <
typename T>
20195 lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>, 2>;
20197 upvalues += stack::push(L,
nullptr);
20198 upvalues += stack::push<user<protect_t<T>>>(L, std::move(pw.value));
20199 return stack::push(L,
c_closure(cf, upvalues));
20203 lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>, 2>;
20205 upvalues += stack::push(L,
nullptr);
20206 upvalues += stack::push<user<protect_t<T>>>(L, pw.value);
20207 return stack::push(L,
c_closure(cf, upvalues));
20211 template <
typename F,
typename G>
20214 if constexpr (std::is_void_v<F>) {
20215 return stack::push(L, std::move(pw.write()));
20217 else if constexpr (std::is_void_v<G>) {
20218 return stack::push(L, std::move(pw.read()));
20221 return stack::push(L, overload(std::move(pw.read()), std::move(pw.write())));
20226 if constexpr (std::is_void_v<F>) {
20227 return stack::push(L, pw.write);
20229 else if constexpr (std::is_void_v<G>) {
20230 return stack::push(L, pw.read);
20233 return stack::push(L, overload(pw.read, pw.write));
20238 template <
typename T>
20241 return stack::push(L, std::move(vw.value()));
20244 return stack::push(L, vw.value());
20248 template <
typename... Functions>
20252 function_detail::select_set_fx<false, false, F>(L, fw.functions);
20258 function_detail::select_set_fx<false, false, F>(L, std::move(fw.functions));
20264 function_detail::select_set_fx<false, false, F>(L, fw.functions);
20270 function_detail::select_set_fx<false, false, F>(L, std::move(fw.functions));
20278 lua_CFunction cf = &function_detail::no_construction_error;
20279 return stack::push(L, cf);
20287 template <
typename T>
20290 lua_CFunction cf = &function_detail::no_construction_error;
20291 return stack::push(L, cf);
20295 lua_CFunction cf = &function_detail::no_construction_error;
20296 return stack::push(L, cf);
20300 template <
typename T,
typename... Lists>
20303 lua_CFunction cf = call_detail::construct<T, detail::default_safe_function_calls,
true, Lists...>;
20304 return stack::push(L, cf);
20308 lua_CFunction cf = call_detail::construct<T, detail::default_safe_function_calls,
true, Lists...>;
20309 return stack::push(L, cf);
20313 template <
typename L0,
typename... Lists>
20317 typedef typename meta::bind_traits<L0>::return_type T;
20318 return stack::push<detail::tagged<T, cl_t>>(L, cl);
20322 template <
typename T,
typename... Fxs>
20325 return push(L, std::move(c.value()));
20329 return push(L, c.value());
20333 lua_CFunction cf = call_detail::call_user<T,
false,
false,
constructor_wrapper<Fxs...>, 2>;
20335 upvalues += stack::push(L,
nullptr);
20337 return stack::push(L,
c_closure(cf, upvalues));
20341 lua_CFunction cf = call_detail::call_user<T,
false,
false,
constructor_wrapper<Fxs...>, 2>;
20343 upvalues += stack::push(L,
nullptr);
20345 return stack::push(L,
c_closure(cf, upvalues));
20349 template <
typename F,
typename... Fxs>
20353 typedef meta::unqualified_t<std::remove_pointer_t<arg0>> T;
20359 typedef meta::unqualified_t<std::remove_pointer_t<arg0>> T;
20364 template <
typename T>
20367 lua_CFunction cf = detail::usertype_alloc_destroy<T>;
20368 return stack::push(L, cf);
20372 template <
typename T,
typename Fx>
20375 lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>, 2>;
20377 upvalues += stack::push(L,
nullptr);
20378 upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, std::move(c));
20379 return stack::push(L,
c_closure(cf, upvalues));
20383 lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>, 2>;
20385 upvalues += stack::push(L,
nullptr);
20386 upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, c);
20387 return stack::push(L,
c_closure(cf, upvalues));
20391 template <
typename Fx>
20394 lua_CFunction cf = call_detail::call_user<void, false, false, destructor_wrapper<Fx>, 2>;
20396 upvalues += stack::push(L,
nullptr);
20397 upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, std::move(c));
20398 return stack::push(L,
c_closure(cf, upvalues));
20402 lua_CFunction cf = call_detail::call_user<void, false, false, destructor_wrapper<Fx>, 2>;
20404 upvalues += stack::push(L,
nullptr);
20405 upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, c);
20406 return stack::push(L,
c_closure(cf, upvalues));
20410 template <
typename F,
typename... Policies>
20414 static int push(
lua_State* L,
const P& p) {
20415 lua_CFunction cf = call_detail::call_user<void, false, false, P, 2>;
20417 upvalues += stack::push(L,
nullptr);
20418 upvalues += stack::push<user<P>>(L, p);
20419 return stack::push(L,
c_closure(cf, upvalues));
20423 lua_CFunction cf = call_detail::call_user<void, false, false, P, 2>;
20425 upvalues += stack::push(L,
nullptr);
20426 upvalues += stack::push<user<P>>(L, std::move(p));
20427 return stack::push(L,
c_closure(cf, upvalues));
20431 template <
typename T,
typename F,
typename... Policies>
20437 lua_CFunction cf = call_detail::call_user<T, false, false, P, 2>;
20439 upvalues += stack::push(L,
nullptr);
20440 upvalues += stack::push<user<P>>(L, p.value());
20441 return stack::push(L,
c_closure(cf, upvalues));
20445 lua_CFunction cf = call_detail::call_user<T, false, false, P, 2>;
20447 upvalues += stack::push(L,
nullptr);
20448 upvalues += stack::push<user<P>>(L, std::move(p.value()));
20449 return stack::push(L,
c_closure(cf, upvalues));
20453 template <
typename T>
20456 if constexpr (std::is_invocable_v<std::add_rvalue_reference_t<T>,
lua_State*>) {
20457 return stack::push(L, std::move(pi.value())(L));
20460 return stack::push(L, std::move(pi.value())());
20465 if constexpr (std::is_invocable_v<const T, lua_State*>) {
20466 return stack::push(L, pi.value()(L));
20469 return stack::push(L, pi.value()());
20474 namespace stack_detail {
20475 template <
typename Function,
typename Handler>
20476 bool check_function_pointer(
lua_State* L,
int index, Handler&& handler,
record& tracking) noexcept {
20477 #if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE) 20479 bool success = lua_iscfunction(L, index) == 1;
20482 const char* upvalue_name = lua_getupvalue(L, index, 2);
20484 success = upvalue_name !=
nullptr;
20489 L, index, type::function, type_of(L, index),
"type must be a Lua C Function gotten from a function pointer serialized by sol2");
20501 template <
typename Function>
20502 Function* get_function_pointer(
lua_State* L,
int index,
record& tracking) noexcept {
20503 #if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE) 20505 auto udata = stack::stack_detail::get_as_upvalues_using_function<Function*>(L, index);
20506 Function* fx = udata.first;
20513 #
if SOL_IS_DEFAULT_OFF(SOL_GET_FUNCTION_POINTER_UNSAFE)
20514 "You are attempting to retrieve a function pointer type. " 20515 "This is inherently unsafe in sol2. In order to do this, you must turn on the " 20516 "SOL_GET_FUNCTION_POINTER_UNSAFE configuration macro, as detailed in the documentation. " 20517 "Please be careful!" 20519 "You are attempting to retrieve a function pointer type. " 20520 "You explicitly turned off the ability to do this by defining " 20521 "SOL_GET_FUNCTION_POINTER_UNSAFE or similar to be off. " 20522 "Please reconsider this!" 20537 #include <exception> 20546 dump_error(
int error_code_) :
error(
"dump returned non-zero error of " + std::to_string(error_code_)), m_ec(error_code_) {
20549 int error_code()
const {
20554 inline int dump_pass_on_error(
lua_State* L_,
int result_code, lua_Writer writer_function,
void* userdata_pointer_,
bool strip) {
20556 (void)writer_function;
20557 (void)userdata_pointer_;
20559 return result_code;
20562 inline int dump_panic_on_error(
lua_State* L_,
int result_code, lua_Writer writer_function,
void* userdata_pointer_,
bool strip) {
20564 (void)writer_function;
20565 (void)userdata_pointer_;
20567 return luaL_error(L_,
"a non-zero error code (%d) was returned by the lua_Writer for the dump function", result_code);
20570 inline int dump_throw_on_error(
lua_State* L_,
int result_code, lua_Writer writer_function,
void* userdata_pointer_,
bool strip) {
20571 #if SOL_IS_OFF(SOL_EXCEPTIONS) 20572 return dump_panic_on_error(L_, result_code, writer_function, userdata_pointer_, strip);
20575 (void)writer_function;
20576 (void)userdata_pointer_;
20579 #endif // no exceptions stuff 20589 template <
typename ref_t,
bool aligned = false>
20594 void luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount)
const {
20595 lua_call(lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount));
20598 template <std::size_t... I,
typename... Ret>
20599 auto invoke(
types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n)
const {
20600 luacall(n,
lua_size<std::tuple<Ret...>>::value);
20601 return stack::pop<std::tuple<Ret...>>(lua_state());
20604 template <std::
size_t I,
typename Ret, meta::enable<meta::neg<std::is_
void<Ret>>> = meta::enabler>
20605 Ret invoke(
types<Ret>, std::index_sequence<I>, std::ptrdiff_t n)
const {
20607 return stack::pop<Ret>(lua_state());
20610 template <std::
size_t I>
20611 void invoke(
types<void>, std::index_sequence<I>, std::ptrdiff_t n)
const {
20616 int stacksize = lua_gettop(lua_state());
20617 int firstreturn = (std::max)(1, stacksize - static_cast<int>(n));
20618 luacall(n, LUA_MULTRET);
20619 int poststacksize = lua_gettop(lua_state());
20620 int returncount = poststacksize - (firstreturn - 1);
20625 using base_t::lua_state;
20628 template <
typename T,
20629 meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>,
basic_function>>, meta::neg<std::is_same<base_t, stack_reference>>,
20631 basic_function(T&& r) noexcept : base_t(std::forward<T>(r)) {
20632 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 20633 if (!
is_function<meta::unqualified_t<T>>::value) {
20634 auto pp = stack::push_pop(*
this);
20636 stack::check<basic_function>(lua_state(), -1, handler);
20640 basic_function(
const basic_function&) =
default;
20641 basic_function& operator=(
const basic_function&) =
default;
20642 basic_function(basic_function&&) =
default;
20643 basic_function& operator=(basic_function&&) =
default;
20644 basic_function(
const stack_reference& r) : basic_function(r.lua_state(), r.stack_index()) {
20646 basic_function(
stack_reference&& r) : basic_function(r.lua_state(), r.stack_index()) {
20648 basic_function(
lua_nil_t n) : base_t(n) {
20650 template <
typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
20651 basic_function(
lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) {
20652 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 20653 auto pp = stack::push_pop(*
this);
20655 stack::check<basic_function>(lua_state(), -1, handler);
20658 basic_function(
lua_State* L,
int index = -1) : base_t(L, index) {
20659 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 20661 stack::check<basic_function>(L, index, handler);
20665 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 20666 auto pp = stack::push_pop(*
this);
20668 stack::check<basic_function>(lua_state(), -1, handler);
20672 template <
typename Fx>
20673 int dump(lua_Writer writer,
void*
userdata,
bool strip, Fx&& on_error)
const {
20676 int r = lua_dump(this->lua_state(), writer, userdata, strip ? 1 : 0);
20678 return on_error(this->lua_state(), r, writer, userdata, strip);
20683 int dump(lua_Writer writer,
void* userdata,
bool strip =
false)
const {
20684 return dump(writer, userdata, strip, &dump_throw_on_error);
20687 template <
typename Container = bytecode>
20688 Container dump()
const {
20690 (void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>),
static_cast<void*
>(&bc),
false, &dump_panic_on_error);
20694 template <
typename Container = bytecode,
typename Fx>
20695 Container dump(Fx&& on_error)
const {
20697 (void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>),
static_cast<void*
>(&bc),
false, std::forward<Fx>(on_error));
20701 template <
typename... Args>
20703 return call<>(std::forward<Args>(args)...);
20706 template <
typename... Ret,
typename... Args>
20707 decltype(
auto) operator()(
types<Ret...>, Args&&... args)
const {
20708 return call<Ret...>(std::forward<Args>(args)...);
20711 template <
typename... Ret,
typename... Args>
20712 decltype(
auto) call(Args&&... args)
const {
20716 int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
20717 return invoke(
types<Ret...>(), std::make_index_sequence<
sizeof...(Ret)>(), static_cast<std::ptrdiff_t>(pushcount));
20730 namespace sol {
namespace detail {
20731 inline const char (&default_handler_name())[9] {
20732 static const char name[9] =
"sol.\xF0\x9F\x94\xA9";
20736 template <
bool ShouldPush,
typename Target = reference>
20739 const Target& target;
20744 stack_index = lua_gettop(L_) + 1;
20751 stack_index = target.stack_index();
20758 bool valid()
const noexcept {
20763 if constexpr (!is_stack_based_v<Target>) {
20764 if (stack_index != 0) {
20765 lua_remove(m_L, stack_index);
20771 template <
typename Base,
typename T>
20776 template <
typename Reference,
bool IsMainReference = false>
20777 inline Reference get_default_handler(
lua_State* L_) {
20778 if (is_stack_based_v<Reference> || L_ ==
nullptr)
20779 return Reference(L_, lua_nil);
20780 L_ = IsMainReference ? main_thread(L_, L_) : L_;
20781 lua_getglobal(L_, default_handler_name());
20782 auto pp = stack::pop_n(L_, 1);
20783 return Reference(L_, -1);
20786 template <
typename T>
20787 inline void set_default_handler(
lua_State* L,
const T& ref) {
20788 if (L ==
nullptr) {
20791 if (!ref.valid()) {
20792 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK) 20793 luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
20794 #endif // make sure stack doesn't overflow 20796 lua_setglobal(L, default_handler_name());
20800 lua_setglobal(L, default_handler_name());
20808 #include <algorithm> 20813 template <
bool ShouldPush_,
typename Handler_>
20814 inline void handle_protected_exception(
20816 handler_.stack_index = 0;
20818 handler_.target.push(L_);
20819 detail::call_exception_handler(L_, maybe_ex, error);
20820 lua_call(L_, 1, 1);
20823 detail::call_exception_handler(L_, maybe_ex, error);
20828 template <
typename Reference,
bool Aligned = false,
typename Handler = reference>
20832 using handler_t = Handler;
20833 inline static constexpr
bool is_stack_handler_v = is_stack_based_v<handler_t>;
20836 : base_t(other_), m_error_handler(other_.m_error_handler.copy(lua_state())) {
20844 template <
typename T,
20846 meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<T>>>, meta::neg<std::is_same<base_t, stack_reference>>,
20848 basic_protected_function(T&& r) noexcept : base_t(std::forward<T>(r)), m_error_handler(get_default_handler(r.lua_state())) {
20849 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 20850 if (!
is_function<meta::unqualified_t<T>>::value) {
20851 auto pp = stack::push_pop(*
this);
20853 stack::check<basic_protected_function>(lua_state(), -1, handler);
20857 basic_protected_function(
const basic_protected_function& other_) noexcept
20858 : basic_protected_function(meta::boolean<is_stateless_lua_reference_v<Handler>>(), other_) {
20860 basic_protected_function& operator=(
const basic_protected_function& other_) {
20861 base_t::operator=(other_);
20862 if constexpr (is_stateless_lua_reference_v<Handler>) {
20863 m_error_handler.copy_assign(lua_state(), other_.m_error_handler);
20866 m_error_handler = other_.m_error_handler;
20870 basic_protected_function(basic_protected_function&&) =
default;
20871 basic_protected_function& operator=(basic_protected_function&&) =
default;
20872 basic_protected_function(
const basic_function<base_t>& b) : basic_protected_function(b, get_default_handler(b.lua_state())) {
20874 basic_protected_function(
basic_function<base_t>&& b) : basic_protected_function(std::move(b), get_default_handler(b.lua_state())) {
20876 basic_protected_function(
const basic_function<base_t>& b, handler_t eh) : base_t(b), m_error_handler(std::move(eh)) {
20878 basic_protected_function(
basic_function<base_t>&& b, handler_t eh) : base_t(std::move(b)), m_error_handler(std::move(eh)) {
20880 basic_protected_function(
const stack_reference& r) : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) {
20882 basic_protected_function(
stack_reference&& r) : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) {
20884 basic_protected_function(
const stack_reference& r, handler_t eh) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {
20886 basic_protected_function(
stack_reference&& r, handler_t eh) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {
20889 template <
typename Super>
20890 basic_protected_function(
const proxy_base<Super>& p) : basic_protected_function(p, get_default_handler(p.lua_state())) {
20892 template <
typename Super>
20893 basic_protected_function(
proxy_base<Super>&& p) : basic_protected_function(std::move(p), get_default_handler(p.lua_state())) {
20895 template <
typename Proxy,
typename HandlerReference,
20896 meta::enable<std::is_base_of<proxy_base_tag, meta::unqualified_t<Proxy>>,
20897 meta::neg<is_lua_index<meta::unqualified_t<HandlerReference>>>> = meta::enabler>
20898 basic_protected_function(Proxy&& p, HandlerReference&& eh)
20899 : basic_protected_function(detail::force_cast<base_t>(p), make_reference<handler_t>(p.lua_state(), std::forward<HandlerReference>(eh))) {
20902 template <
typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
20903 basic_protected_function(
lua_State* L_, T&& r) : basic_protected_function(L_, std::forward<T>(r), get_default_handler(L_)) {
20905 template <
typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
20906 basic_protected_function(
lua_State* L_, T&& r, handler_t eh) : base_t(L_, std::forward<T>(r)), m_error_handler(std::move(eh)) {
20907 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 20908 auto pp = stack::push_pop(*
this);
20910 stack::check<basic_protected_function>(lua_state(), -1, handler);
20914 basic_protected_function(
lua_nil_t n) : base_t(n), m_error_handler(n) {
20917 basic_protected_function(
lua_State* L_,
int index_ = -1) : basic_protected_function(L_, index_, get_default_handler(L_)) {
20919 basic_protected_function(
lua_State* L_,
int index_, handler_t eh) : base_t(L_, index_), m_error_handler(std::move(eh)) {
20920 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 20922 stack::check<basic_protected_function>(L_, index_, handler);
20925 basic_protected_function(
lua_State* L_,
absolute_index index_) : basic_protected_function(L_, index_, get_default_handler(L_)) {
20927 basic_protected_function(
lua_State* L_,
absolute_index index_, handler_t eh) : base_t(L_, index_), m_error_handler(std::move(eh)) {
20928 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 20930 stack::check<basic_protected_function>(L_, index_, handler);
20933 basic_protected_function(
lua_State* L_,
raw_index index_) : basic_protected_function(L_, index_, get_default_handler(L_)) {
20935 basic_protected_function(
lua_State* L_,
raw_index index_, handler_t eh) : base_t(L_, index_), m_error_handler(std::move(eh)) {
20936 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 20938 stack::check<basic_protected_function>(L_, index_, handler);
20941 basic_protected_function(
lua_State* L_,
ref_index index_) : basic_protected_function(L_, index_, get_default_handler(L_)) {
20943 basic_protected_function(
lua_State* L_,
ref_index index_, handler_t eh) : base_t(L_, index_), m_error_handler(std::move(eh)) {
20944 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 20945 auto pp = stack::push_pop(*
this);
20947 stack::check<basic_protected_function>(lua_state(), -1, handler);
20951 using base_t::lua_state;
20953 template <
typename Fx>
20954 int dump(lua_Writer writer,
void* userdata_pointer_,
bool strip, Fx&& on_error)
const {
20957 int r = lua_dump(this->lua_state(), writer, userdata_pointer_, strip ? 1 : 0);
20959 return on_error(this->lua_state(), r, writer, userdata_pointer_, strip);
20964 int dump(lua_Writer writer,
void* userdata_pointer_,
bool strip =
false)
const {
20965 return dump(writer, userdata_pointer_, strip, &dump_pass_on_error);
20968 template <
typename Container = bytecode>
20969 Container dump()
const {
20971 (void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>),
static_cast<void*
>(&bc),
false, &dump_throw_on_error);
20975 template <
typename Container = bytecode,
typename Fx>
20976 Container dump(Fx&& on_error)
const {
20978 (void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>),
static_cast<void*
>(&bc),
false, std::forward<Fx>(on_error));
20982 template <
typename... Args>
20984 return call<>(std::forward<Args>(args)...);
20987 template <
typename... Ret,
typename... Args>
20988 decltype(
auto) operator()(
types<Ret...>, Args&&... args)
const {
20989 return call<Ret...>(std::forward<Args>(args)...);
20992 template <
typename... Ret,
typename... Args>
20993 decltype(
auto) call(Args&&... args)
const {
20994 if constexpr (!Aligned) {
20996 if (m_error_handler.valid(lua_state())) {
20999 int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
21000 return invoke(
types<Ret...>(), std::make_index_sequence<
sizeof...(Ret)>(), pushcount, h);
21005 int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
21006 return invoke(
types<Ret...>(), std::make_index_sequence<
sizeof...(Ret)>(), pushcount, h);
21011 if (m_error_handler.valid()) {
21015 if constexpr (!is_stack_handler_v) {
21020 if constexpr (!is_stack_handler_v) {
21021 lua_replace(lua_state(), -3);
21022 h.stack_index = lua_absindex(lua_state(), -2);
21024 int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
21025 return invoke(
types<Ret...>(), std::make_index_sequence<
sizeof...(Ret)>(), pushcount, h);
21029 int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
21030 return invoke(
types<Ret...>(), std::make_index_sequence<
sizeof...(Ret)>(), pushcount, h);
21035 ~basic_protected_function() {
21036 if constexpr (is_stateless_lua_reference_v<handler_t>) {
21037 this->m_error_handler.reset(lua_state());
21041 static handler_t get_default_handler(
lua_State* L_) {
21042 return detail::get_default_handler<handler_t, is_main_threaded_v<base_t>>(L_);
21045 template <
typename T>
21046 static void set_default_handler(
const T& ref) {
21047 detail::set_default_handler(ref.lua_state(), ref);
21050 auto get_error_handler()
const noexcept {
21051 if constexpr (is_stateless_lua_reference_v<handler_t>) {
21052 if constexpr (is_stack_based_v<handler_t>) {
21060 return m_error_handler;
21064 template <
typename ErrorHandler_>
21065 void set_error_handler(ErrorHandler_&& error_handler_) noexcept {
21066 static_assert(!is_stack_based_v<handler_t> || is_stack_based_v<ErrorHandler_>,
21067 "A stack-based error handler can only be set from a parameter that is also stack-based.");
21068 if constexpr (std::is_rvalue_reference_v<ErrorHandler_>) {
21069 m_error_handler = std::forward<ErrorHandler_>(error_handler_);
21072 m_error_handler.copy_assign(lua_state(), std::forward<ErrorHandler_>(error_handler_));
21076 void abandon () noexcept {
21077 this->m_error_handler.abandon();
21082 handler_t m_error_handler;
21086 return static_cast<call_status
>(lua_pcall(lua_state(), static_cast<int>(argcount), static_cast<int>(result_count_), h.stack_index));
21089 template <std::size_t... I,
bool b,
typename... Ret>
21091 luacall(n,
sizeof...(Ret), h);
21092 return stack::pop<std::tuple<Ret...>>(lua_state());
21095 template <std::
size_t I,
bool b,
typename Ret>
21098 return stack::pop<Ret>(lua_state());
21101 template <std::
size_t I,
bool b>
21108 int stacksize = lua_gettop(lua_state());
21109 int poststacksize = stacksize;
21110 int firstreturn = 1;
21111 int returncount = 0;
21112 call_status code = call_status::ok;
21113 #if SOL_IS_ON(SOL_EXCEPTIONS) && SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS) 21115 #endif // No Exceptions 21116 firstreturn = (std::max)(1, static_cast<int>(stacksize - n - static_cast<int>(h.valid() && !is_stack_handler_v)));
21117 code = luacall(n, LUA_MULTRET, h);
21118 poststacksize = lua_gettop(lua_state()) -
static_cast<int>(h.valid() && !is_stack_handler_v);
21119 returncount = poststacksize - (firstreturn - 1);
21120 #if SOL_IS_ON(SOL_EXCEPTIONS) && SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS) 21123 catch (
const char*
error) {
21125 firstreturn = lua_gettop(lua_state());
21128 catch (
const std::string& error) {
21130 firstreturn = lua_gettop(lua_state());
21133 catch (
const std::exception& error) {
21135 firstreturn = lua_gettop(lua_state());
21138 #if SOL_IS_ON(SOL_EXCEPTIONS_CATCH_ALL) 21144 firstreturn = lua_gettop(lua_state());
21147 #endif // Always catch edge case 21150 #endif // Exceptions vs. No Exceptions 21158 #include <functional> 21161 template <
typename... Ret,
typename... Args>
21162 decltype(
auto) stack_proxy::call(Args&&... args) {
21164 return sf.template call<Ret...>(std::forward<Args>(args)...);
21168 : L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()), popcount(o.return_count()), err(o.status()) {
21177 index = o.stack_index();
21178 returncount = o.return_count();
21179 popcount = o.return_count();
21189 : L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()) {
21197 index = o.stack_index();
21198 returncount = o.return_count();
21207 template <
typename... R>
21214 template <
typename... Args>
21215 meta::return_type_t<R...> operator()(Args&&... args) {
21216 return lua_func_.call<R...>(std::forward<Args>(args)...);
21227 template <
typename... Args>
21228 void operator()(Args&&... args) {
21229 lua_func_.call<
void>(std::forward<Args>(args)...);
21235 template <
typename Signature>
21239 typedef meta::tuple_types<typename fx_t::return_type> return_types;
21241 template <
typename... R>
21247 static std::function<Signature>
get(
lua_State* L,
int index,
record& tracking) {
21249 type t = type_of(L, index);
21250 if (t == type::none || t == type::lua_nil) {
21253 return get_std_func(return_types(), L, index);
21257 template <
typename Allocator>
21262 return sf.dump(&dump_panic_on_error);
21277 #ifndef SOL_DEPRECATED 21279 #define SOL_DEPRECATED __declspec(deprecated) 21281 #define SOL_DEPRECATED __attribute__((deprecated)) 21283 #define SOL_DEPRECATED [[deprecated]] 21284 #endif // compilers 21285 #endif // SOL_DEPRECATED 21287 namespace sol {
namespace detail {
21288 template <
typename T>
21302 template <
typename T>
21305 namespace container_detail {
21307 template <
typename T>
21310 template <
typename C>
21311 static meta::sfinae_yes_t test(decltype(&C::clear));
21312 template <
typename C>
21313 static meta::sfinae_no_t test(...);
21316 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21319 template <
typename T>
21322 template <
typename C>
21323 static meta::sfinae_yes_t test(decltype(&C::empty));
21324 template <
typename C>
21325 static meta::sfinae_no_t test(...);
21328 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21331 template <
typename T>
21334 template <
typename C>
21335 static meta::sfinae_yes_t test(
21336 decltype(std::declval<C>().erase_after(std::declval<std::add_rvalue_reference_t<typename C::const_iterator>>()))*);
21337 template <
typename C>
21338 static meta::sfinae_no_t test(...);
21341 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21344 template <
typename T,
typename =
void>
21347 template <
typename C>
21348 static meta::sfinae_yes_t test(decltype(std::declval<C>().find(std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*);
21349 template <
typename C>
21350 static meta::sfinae_no_t test(...);
21353 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21356 template <
typename T>
21359 template <
typename C>
21360 static meta::sfinae_yes_t test(decltype(std::declval<C>().find(std::declval<std::add_rvalue_reference_t<typename C::key_type>>()))*);
21361 template <
typename C>
21362 static meta::sfinae_no_t test(...);
21365 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21368 template <
typename T>
21371 template <
typename C>
21372 static meta::sfinae_yes_t test(decltype(std::declval<C>().erase(std::declval<typename C::iterator>()))*);
21373 template <
typename C>
21374 static meta::sfinae_no_t test(...);
21377 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21380 template <
typename T>
21383 template <
typename C>
21384 static meta::sfinae_yes_t test(decltype(std::declval<C>().erase(std::declval<typename C::key_type>()))*);
21385 template <
typename C>
21386 static meta::sfinae_no_t test(...);
21389 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21392 template <
typename T>
21395 template <
typename C>
21396 static meta::sfinae_yes_t test(decltype(&C::find));
21397 template <
typename C>
21398 static meta::sfinae_no_t test(...);
21401 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21404 template <
typename T>
21407 template <
typename C>
21408 static meta::sfinae_yes_t test(decltype(&C::index_of));
21409 template <
typename C>
21410 static meta::sfinae_no_t test(...);
21413 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21416 template <
typename T>
21419 template <
typename C>
21420 static meta::sfinae_yes_t test(decltype(&C::insert));
21421 template <
typename C>
21422 static meta::sfinae_no_t test(...);
21425 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21428 template <
typename T>
21431 template <
typename C>
21432 static meta::sfinae_yes_t test(decltype(&C::erase));
21433 template <
typename C>
21434 static meta::sfinae_no_t test(...);
21437 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21440 template <
typename T>
21443 template <
typename C>
21444 static meta::sfinae_yes_t test(decltype(&C::index_set));
21445 template <
typename C>
21446 static meta::sfinae_no_t test(...);
21449 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21452 template <
typename T>
21455 template <
typename C>
21456 static meta::sfinae_yes_t test(decltype(&C::index_get));
21457 template <
typename C>
21458 static meta::sfinae_no_t test(...);
21461 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21464 template <
typename T>
21467 template <
typename C>
21468 static meta::sfinae_yes_t test(decltype(&C::set));
21469 template <
typename C>
21470 static meta::sfinae_no_t test(...);
21473 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21476 template <
typename T>
21479 template <
typename C>
21480 static meta::sfinae_yes_t test(decltype(&C::get));
21481 template <
typename C>
21482 static meta::sfinae_no_t test(...);
21485 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21488 template <
typename T>
21491 template <
typename C>
21492 static meta::sfinae_yes_t test(decltype(&C::at));
21493 template <
typename C>
21494 static meta::sfinae_no_t test(...);
21497 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21500 template <
typename T>
21503 template <
typename C>
21504 static meta::sfinae_yes_t test(decltype(&C::pairs));
21505 template <
typename C>
21506 static meta::sfinae_no_t test(...);
21509 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21512 template <
typename T>
21515 template <
typename C>
21516 static meta::sfinae_yes_t test(decltype(&C::ipairs));
21517 template <
typename C>
21518 static meta::sfinae_no_t test(...);
21521 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21524 template <
typename T>
21527 template <
typename C>
21528 static meta::sfinae_yes_t test(decltype(&C::next));
21529 template <
typename C>
21530 static meta::sfinae_no_t test(...);
21533 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21536 template <
typename T>
21539 template <
typename C>
21540 static meta::sfinae_yes_t test(decltype(&C::add));
21541 template <
typename C>
21542 static meta::sfinae_no_t test(...);
21545 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21548 template <
typename T>
21551 template <
typename C>
21552 static meta::sfinae_yes_t test(decltype(&C::size));
21553 template <
typename C>
21554 static meta::sfinae_no_t test(...);
21557 static constexpr
bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>;
21560 template <
typename T>
21561 using has_clear = meta::boolean<has_clear_test<T>::value>;
21563 template <
typename T>
21564 using has_empty = meta::boolean<has_empty_test<T>::value>;
21566 template <
typename T>
21567 using has_find = meta::boolean<has_find_test<T>::value>;
21569 template <
typename T>
21570 using has_erase = meta::boolean<has_erase_test<T>::value>;
21572 template <
typename T>
21573 using has_erase_key = meta::boolean<has_erase_key_test<T>::value>;
21575 template <
typename T>
21576 using has_erase_after = meta::boolean<has_erase_after_test<T>::value>;
21578 template <
typename T>
21579 using has_traits_get = meta::boolean<has_traits_get_test<T>::value>;
21581 template <
typename T>
21582 using has_traits_at = meta::boolean<has_traits_at_test<T>::value>;
21584 template <
typename T>
21585 using has_traits_set = meta::boolean<has_traits_set_test<T>::value>;
21587 template <
typename T>
21588 using has_traits_index_get = meta::boolean<has_traits_index_get_test<T>::value>;
21590 template <
typename T>
21591 using has_traits_index_set = meta::boolean<has_traits_index_set_test<T>::value>;
21593 template <
typename T>
21594 using has_traits_pairs = meta::boolean<has_traits_pairs_test<T>::value>;
21596 template <
typename T>
21597 using has_traits_ipairs = meta::boolean<has_traits_ipairs_test<T>::value>;
21599 template <
typename T>
21600 using has_traits_next = meta::boolean<has_traits_next_test<T>::value>;
21602 template <
typename T>
21603 using has_traits_add = meta::boolean<has_traits_add_test<T>::value>;
21605 template <
typename T>
21606 using has_traits_size = meta::boolean<has_traits_size_test<T>::value>;
21608 template <
typename T>
21609 using has_traits_clear = has_clear<T>;
21611 template <
typename T>
21612 using has_traits_empty = has_empty<T>;
21614 template <
typename T>
21615 using has_traits_find = meta::boolean<has_traits_find_test<T>::value>;
21617 template <
typename T>
21618 using has_traits_index_of = meta::boolean<has_traits_index_of_test<T>::value>;
21620 template <
typename T>
21621 using has_traits_insert = meta::boolean<has_traits_insert_test<T>::value>;
21623 template <
typename T>
21624 using has_traits_erase = meta::boolean<has_traits_erase_test<T>::value>;
21626 template <
typename T>
21629 template <
typename T>
21632 template <
typename T>
21637 template <
typename T>
21642 template <
typename T>
21645 template <
typename T>
21646 decltype(
auto) get_key(std::false_type, T&& t) {
21647 return std::forward<T>(t);
21650 template <
typename T>
21651 decltype(
auto) get_key(std::true_type, T&& t) {
21655 template <
typename T>
21656 decltype(
auto) get_value(std::false_type, T&& t) {
21657 return std::forward<T>(t);
21660 template <
typename T>
21661 decltype(
auto) get_value(std::true_type, T&& t) {
21665 template <
typename X,
typename =
void>
21668 typedef std::remove_pointer_t<meta::unwrap_unqualified_t<X>> T;
21675 return luaL_error(L_,
"sol: cannot call 'at(index)' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21679 return luaL_error(L_,
"sol: cannot call 'get(key)' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21683 return luaL_error(L_,
"sol: cannot call 'container[key]' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21687 return luaL_error(L_,
"sol: cannot call 'set(key, value)' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21692 L_,
"sol: cannot call 'container[key] = value' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21696 return luaL_error(L_,
"sol: cannot call 'add' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21700 return luaL_error(L_,
"sol: cannot call 'insert' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21704 return luaL_error(L_,
"sol: cannot call 'find' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21708 return luaL_error(L_,
"sol: cannot call 'index_of' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21712 return luaL_error(L_,
"sol: cannot call 'end' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21716 return luaL_error(L_,
"sol: cannot call 'clear' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21720 return luaL_error(L_,
"sol: cannot call 'empty' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21724 return luaL_error(L_,
"sol: cannot call 'erase' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21728 return luaL_error(L_,
"sol: cannot call 'next' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21732 return luaL_error(L_,
"sol: cannot call '__pairs/pairs' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21736 return luaL_error(L_,
"sol: cannot call '__ipairs' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21739 static iterator begin(
lua_State* L_, T&) {
21740 luaL_error(L_,
"sol: cannot call 'being' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21744 static iterator end(
lua_State* L_, T&) {
21745 luaL_error(L_,
"sol: cannot call 'end' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str());
21750 template <
typename X>
21752 std::enable_if_t<meta::all<is_forced_container<meta::unqualified_t<X>>, meta::has_value_type<meta::unqualified_t<container_decay_t<X>>>,
21753 meta::has_iterator<meta::unqualified_t<container_decay_t<X>>>>::value>> {
21755 using T = std::remove_pointer_t<meta::unwrap_unqualified_t<container_decay_t<X>>>;
21763 using iterator =
typename T::iterator;
21764 using value_type =
typename T::value_type;
21765 typedef meta::conditional_t<is_matched_lookup::value, std::pair<value_type, value_type>,
21766 meta::conditional_t<is_associative::value || is_lookup::value, value_type, std::pair<std::ptrdiff_t, value_type>>>
21768 typedef typename KV::first_type K;
21769 typedef typename KV::second_type V;
21770 typedef meta::conditional_t<is_matched_lookup::value, std::ptrdiff_t, K> next_K;
21771 typedef decltype(*std::declval<iterator&>()) iterator_return;
21772 typedef meta::conditional_t<is_associative::value || is_matched_lookup::value, std::add_lvalue_reference_t<V>,
21773 meta::conditional_t<is_lookup::value, V, iterator_return>>
21775 typedef typename meta::iterator_tag<iterator>::type iterator_category;
21776 typedef std::is_same<iterator_category, std::input_iterator_tag> is_input_iterator;
21777 typedef meta::conditional_t<is_input_iterator::value, V, decltype(detail::deref_move_only(std::declval<captured_type>()))> push_type;
21778 typedef std::is_copy_assignable<V> is_copyable;
21779 typedef meta::neg<meta::any<std::is_const<V>, std::is_const<std::remove_reference_t<iterator_return>>, meta::neg<is_copyable>>> is_writable;
21780 typedef meta::unqualified_t<decltype(get_key(is_associative(), std::declval<std::add_lvalue_reference_t<value_type>>()))> key_type;
21789 iter(
lua_State* L_,
int stack_index, T& source_, iterator it_) : keep_alive(sol::main_thread(L_, L_), stack_index), source(source_), it(std::move(it_)), index(0) {
21797 #if SOL_IS_ON(SOL_SAFE_USERTYPE) 21798 auto p = stack::unqualified_check_get<T*>(L_, 1);
21801 "sol: 'self' is not of type '%s' (pass 'self' as first argument with ':' or call on proper type)",
21802 detail::demangle<T>().c_str());
21804 if (p.value() ==
nullptr) {
21806 L_,
"sol: 'self' argument is nil (pass 'self' as first argument with ':' or call on a '%s' type)", detail::demangle<T>().c_str());
21810 return stack::unqualified_get<T>(L_, 1);
21811 #endif // Safe getting with error 21815 pos += deferred_uc::index_adjustment(L_,
self);
21817 return stack::push(L_, lua_nil);
21819 auto it = deferred_uc::begin(L_,
self);
21820 auto e = deferred_uc::end(L_,
self);
21822 return stack::push(L_, lua_nil);
21828 return stack::push(L_, lua_nil);
21835 std::ptrdiff_t len =
static_cast<std::ptrdiff_t
>(size_start(L_,
self));
21836 pos += deferred_uc::index_adjustment(L_,
self);
21837 if (pos < 0 || pos >= len) {
21838 return stack::push(L_, lua_nil);
21840 auto it = std::next(deferred_uc::begin(L_,
self), pos);
21845 return at_category(iterator_category(), L_,
self, pos);
21848 template <
typename Iter>
21850 decltype(
auto) v = *it;
21851 return stack::stack_detail::push_reference<push_type>(L_, detail::deref_move_only(v.second));
21854 template <
typename Iter>
21856 return stack::stack_detail::push_reference<push_type>(L_, detail::deref_move_only(*it));
21860 key =
static_cast<K
>(key + deferred_uc::index_adjustment(L_,
self));
21862 return stack::push(L_, lua_nil);
21864 auto it = deferred_uc::begin(L_,
self);
21865 auto e = deferred_uc::end(L_,
self);
21867 return stack::push(L_, lua_nil);
21873 return stack::push(L_, lua_nil);
21880 std::ptrdiff_t len =
static_cast<std::ptrdiff_t
>(size_start(L_,
self));
21881 key =
static_cast<K
>(
static_cast<std::ptrdiff_t
>(key) + deferred_uc::index_adjustment(L_,
self));
21882 if (key < 0 || key >= len) {
21883 return stack::push(L_, lua_nil);
21885 auto it = std::next(deferred_uc::begin(L_,
self), key);
21890 return get_category(iterator_category(), L_,
self, key);
21894 auto fx = [&](
const value_type& r) ->
bool {
return key == get_key(
is_associative(), r); };
21895 auto e = deferred_uc::end(L_,
self);
21896 auto it = std::find_if(deferred_uc::begin(L_,
self), e, std::ref(fx));
21898 return stack::push(L_, lua_nil);
21904 return detail::error_result(
"cannot get this key on '%s': no suitable way to increment iterator and compare to key value '%s'",
21905 detail::demangle<T>().data(),
21906 detail::demangle<K>().data());
21914 decltype(
auto) v = *it;
21915 v.second = value.as<V>();
21920 decltype(
auto) v = *it;
21931 "cannot perform a 'set': '%s's iterator reference is not writable (non-copy-assignable or const)", detail::demangle<T>().data());
21935 decltype(
auto) key = okey.as<K>();
21936 key =
static_cast<K
>(
static_cast<std::ptrdiff_t
>(key) + deferred_uc::index_adjustment(L_,
self));
21937 auto e = deferred_uc::end(L_,
self);
21938 auto it = deferred_uc::begin(L_,
self);
21940 for (; key > 0 && it != e; --key, ++it) {
21945 return add_copyable(is_copyable(), L_,
self, std::move(value), meta::has_insert_after<T>::value ? backit : it);
21947 return detail::error_result(
"out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str());
21949 return set_writable(is_writable(), L_,
self, it, std::move(value));
21953 decltype(
auto) key = okey.as<K>();
21954 key =
static_cast<K
>(
static_cast<std::ptrdiff_t
>(key) + deferred_uc::index_adjustment(L_,
self));
21956 return detail::error_result(
"sol: out of bounds (too small) for set on '%s'", detail::demangle<T>().c_str());
21958 std::ptrdiff_t len =
static_cast<std::ptrdiff_t
>(size_start(L_,
self));
21960 return add_copyable(is_copyable(), L_,
self, std::move(value));
21962 else if (key >= len) {
21963 return detail::error_result(
"sol: out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str());
21965 auto it = std::next(deferred_uc::begin(L_,
self), key);
21966 return set_writable(is_writable(), L_,
self, it, std::move(value));
21970 decltype(
auto) key = okey.as<K>();
21971 if (!is_writable::value) {
21973 "cannot perform a 'set': '%s's iterator reference is not writable (non-copy-assignable or const)", detail::demangle<T>().data());
21975 auto fx = [&](
const value_type& r) ->
bool {
return key == get_key(
is_associative(), r); };
21976 auto e = deferred_uc::end(L_,
self);
21977 auto it = std::find_if(deferred_uc::begin(L_,
self), e, std::ref(fx));
21981 return set_writable(is_writable(), L_,
self, it, std::move(value));
21985 return detail::error_result(
"cannot set this value on '%s': no suitable way to increment iterator or compare to '%s' key",
21986 detail::demangle<T>().data(),
21987 detail::demangle<K>().data());
21990 template <
typename Iter>
21992 if constexpr (meta::has_insert_with_iterator<T>::value) {
21993 self.insert(it, value_type(key, value.as<V>()));
21996 else if constexpr (meta::has_insert<T>::value) {
21997 self.insert(value_type(key, value.as<V>()));
22005 "cannot call 'set' on '%s': there is no 'insert' function on this associative type", detail::demangle<T>().c_str());
22009 template <
typename Iter>
22011 if constexpr (meta::has_insert_with_iterator<T>::value) {
22012 self.insert(it, key);
22015 else if constexpr (meta::has_insert<T>::value) {
22024 "cannot call 'set' on '%s': there is no 'insert' function on this non-associative type", detail::demangle<T>().c_str());
22029 decltype(
auto) key = okey.as<K>();
22030 auto it =
self.find(key);
22031 if (it == deferred_uc::end(L_,
self)) {
22032 return set_associative_insert(
is_associative(), L_,
self, it, key, std::move(value));
22034 return set_writable(is_writable(), L_,
self, it, std::move(value));
22042 return set_category(iterator_category(), L_,
self, std::move(key), std::move(value));
22049 template <
bool idx_of = false>
22051 if constexpr (!is_ordered::value && idx_of) {
22054 return detail::error_result(
"cannot perform an 'index_of': '%s's is not an ordered container", detail::demangle<T>().data());
22057 decltype(
auto) key = stack::unqualified_get<K>(L_, 2);
22058 auto it =
self.find(key);
22059 if (it == deferred_uc::end(L_,
self)) {
22060 return stack::push(L_, lua_nil);
22062 if constexpr (idx_of) {
22063 auto dist = std::distance(deferred_uc::begin(L_,
self), it);
22064 dist -= deferred_uc::index_adjustment(L_,
self);
22065 return stack::push(L_, dist);
22073 template <
bool idx_of = false>
22075 if constexpr (!is_ordered::value && idx_of) {
22078 return detail::error_result(
"cannot perform an 'index_of': '%s's is not an ordered container", detail::demangle<T>().data());
22081 decltype(
auto) value = stack::unqualified_get<V>(L_, 2);
22082 auto it =
self.find(value);
22083 if (it == deferred_uc::end(L_,
self)) {
22084 return stack::push(L_, lua_nil);
22086 if constexpr (idx_of) {
22087 auto dist = std::distance(deferred_uc::begin(L_,
self), it);
22088 dist -= deferred_uc::index_adjustment(L_,
self);
22089 return stack::push(L_, dist);
22097 template <
bool idx_of = false>
22102 template <
typename Iter>
22107 template <
typename Iter>
22109 idx =
static_cast<std::size_t
>(
static_cast<std::ptrdiff_t
>(idx) - deferred_uc::index_adjustment(L_,
self));
22110 return stack::push(L_, idx);
22113 template <
bool = false>
22115 return detail::error_result(
"cannot call 'find' on '%s': there is no 'find' function and the value_type is not equality comparable",
22116 detail::demangle<T>().c_str());
22119 template <
bool idx_of = false>
22121 decltype(
auto) value = stack::unqualified_get<V>(L_, 2);
22122 auto it = deferred_uc::begin(L_,
self);
22123 auto e = deferred_uc::end(L_,
self);
22124 std::size_t idx = 0;
22125 for (;; ++it, ++idx) {
22127 return stack::push(L_, lua_nil);
22136 template <
bool idx_of = false>
22141 template <
typename Iter>
22143 return add_insert_after(std::false_type(), L_,
self, value);
22147 return detail::error_result(
"cannot call 'add' on type '%s': no suitable insert/push_back C++ functions", detail::demangle<T>().data());
22150 template <
typename Iter>
22152 self.insert_after(pos, value.as<V>());
22157 auto backit =
self.before_begin();
22159 auto e = deferred_uc::end(L_,
self);
22160 for (
auto it = deferred_uc::begin(L_,
self); it != e; ++backit, ++it) { }
22162 return add_insert_after(std::true_type(), L_,
self, value, backit);
22165 template <
typename Iter>
22167 self.insert(pos, value.as<V>());
22172 auto pos = deferred_uc::end(L_,
self);
22173 return add_insert(std::true_type(), L_,
self, value, pos);
22176 template <
typename Iter>
22178 return add_insert_after(meta::has_insert_after<T>(), L_,
self, std::move(value), pos);
22182 return add_insert_after(meta::has_insert_after<T>(), L_,
self, std::move(value));
22185 template <
typename Iter>
22187 self.push_back(value.as<V>());
22192 self.push_back(value.as<V>());
22196 template <
typename Iter>
22199 std::integral_constant <
bool, meta::has_insert<T>::value || meta::has_insert_with_iterator<T>::value > (), L_,
self, value, pos);
22204 std::integral_constant <
bool, meta::has_insert<T>::value || meta::has_insert_with_iterator<T>::value > (), L_,
self, value);
22207 template <
typename Iter>
22209 if constexpr (meta::has_insert_with_iterator<T>::value) {
22210 self.insert(pos, value_type(key.as<K>(), stack::unqualified_get<V>(L_, 3)));
22213 else if constexpr (meta::has_insert<T>::value) {
22214 self.insert(value_type(key.as<K>(), stack::unqualified_get<V>(L_, 3)));
22223 "cannot call 'insert' on '%s': there is no 'insert' function on this associative type", detail::demangle<T>().c_str());
22228 auto pos = deferred_uc::end(L_,
self);
22229 return add_associative(std::true_type(), L_,
self, std::move(key), pos);
22232 template <
typename Iter>
22234 return add_push_back(meta::has_push_back<T>(), L_,
self, value, pos);
22238 return add_push_back(meta::has_push_back<T>(), L_,
self, value);
22241 template <
typename Iter>
22243 return add_associative(
is_associative(), L_,
self, std::move(value), pos);
22250 template <
typename Iter>
22252 return add_copyable(std::false_type(), L_,
self, std::move(value));
22256 return detail::error_result(
"cannot call 'add' on '%s': value_type is non-copyable", detail::demangle<T>().data());
22261 return add_copyable(std::true_type(), L_,
self, std::move(value));
22265 auto it = deferred_uc::begin(L_,
self);
22266 auto key = where.as<K>();
22267 key =
static_cast<K
>(
static_cast<std::ptrdiff_t
>(key) + deferred_uc::index_adjustment(L_,
self));
22268 std::advance(it, key);
22269 self.insert(it, value.as<V>());
22274 auto key = where.as<K>();
22275 auto backit =
self.before_begin();
22277 key =
static_cast<K
>(
static_cast<std::ptrdiff_t
>(key) + deferred_uc::index_adjustment(L_,
self));
22278 auto e = deferred_uc::end(L_,
self);
22279 for (
auto it = deferred_uc::begin(L_,
self); key > 0; ++backit, ++it, --key) {
22281 return detail::error_result(
"sol: out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str());
22285 self.insert_after(backit, value.as<V>());
22291 "cannot call 'insert' on '%s': no suitable or similar functionality detected on this container", detail::demangle<T>().data());
22299 return insert_after_has(meta::has_insert_after<T>(), L_,
self, where, value);
22303 return insert_has(std::integral_constant <
bool,
22304 meta::has_insert<T>::value || meta::has_insert_with_iterator<T>::value > (),
22312 return detail::error_result(
"cannot call 'insert' on '%s': value_type is non-copyable", detail::demangle<T>().data());
22316 auto it = deferred_uc::begin(L_,
self);
22317 key = (
static_cast<std::ptrdiff_t
>(key) + deferred_uc::index_adjustment(L_,
self));
22318 std::advance(it, key);
22325 auto fx = [&](
const value_type& r) ->
bool {
return key == r; };
22326 auto e = deferred_uc::end(L_,
self);
22327 auto it = std::find_if(deferred_uc::begin(L_,
self), e, std::ref(fx));
22342 return erase_integral(std::is_integral<K>(), L_,
self, key);
22346 auto backit =
self.before_begin();
22348 key =
static_cast<K
>(
static_cast<std::ptrdiff_t
>(key) + deferred_uc::index_adjustment(L_,
self));
22349 auto e = deferred_uc::end(L_,
self);
22350 for (
auto it = deferred_uc::begin(L_,
self); key > 0; ++backit, ++it, --key) {
22352 return detail::error_result(
"sol: out of bounds for erase on '%s'", detail::demangle<T>().c_str());
22356 self.erase_after(backit);
22369 return erase_after_has(has_erase_after<T>(), L_,
self, key);
22377 return erase_key_has(has_erase_key<T>(), L_,
self, key);
22380 static auto size_has(std::false_type,
lua_State* L_, T&
self) {
22381 return std::distance(deferred_uc::begin(L_,
self), deferred_uc::end(L_,
self));
22384 static auto size_has(std::true_type,
lua_State*, T&
self) {
22385 return self.size();
22388 static void clear_has(std::true_type,
lua_State*, T&
self) {
22392 static void clear_has(std::false_type,
lua_State* L_, T&) {
22393 luaL_error(L_,
"sol: cannot call clear on '%s'", detail::demangle<T>().c_str());
22396 static bool empty_has(std::true_type,
lua_State*, T&
self) {
22397 return self.empty();
22400 static bool empty_has(std::false_type,
lua_State* L_, T&
self) {
22401 return deferred_uc::begin(L_,
self) == deferred_uc::end(L_,
self);
22405 auto it =
self.find(key);
22406 if (it == deferred_uc::end(L_,
self)) {
22407 stack::push(L_, lua_nil);
22410 return get_associative(std::true_type(), L_, it);
22414 return get_it(is_linear_integral(), L_,
self, key);
22418 return get_associative_find(std::integral_constant <
bool, is_associative::value&& has_find<T>::value > (), L_,
self, key);
22422 return set_it(is_linear_integral(), L_,
self, std::move(key), std::move(value));
22425 static std::size_t size_start(
lua_State* L_, T&
self) {
22426 return static_cast<std::size_t
>(size_has(meta::has_size<T>(), L_,
self));
22429 static void clear_start(
lua_State* L_, T&
self) {
22430 clear_has(has_clear<T>(), L_,
self);
22433 static bool empty_start(
lua_State* L_, T&
self) {
22434 return empty_has(has_empty<T>(), L_,
self);
22438 return erase_has(has_erase<T>(), L_,
self, key);
22442 static int next_associative(std::true_type,
lua_State* L_) {
22443 iter& i = stack::unqualified_get<user<iter>>(L_, 1);
22444 auto& source = i.source;
22446 if (it == deferred_uc::end(L_, source)) {
22447 return stack::push(L_, lua_nil);
22450 if constexpr (ip) {
22452 p = stack::push_reference(L_, i.index);
22455 p = stack::push_reference(L_, it->first);
22457 p += stack::stack_detail::push_reference<push_type>(L_, detail::deref_move_only(it->second));
22458 std::advance(it, 1);
22463 static int next_associative(std::false_type,
lua_State* L_) {
22464 iter& i = stack::unqualified_get<user<iter>>(L_, 1);
22465 auto& source = i.source;
22467 next_K k = stack::unqualified_get<next_K>(L_, 2);
22468 if (it == deferred_uc::end(L_, source)) {
22469 return stack::push(L_, lua_nil);
22472 if constexpr (std::is_integral_v<next_K>) {
22473 p = stack::push_reference(L_, k + 1);
22476 p = stack::stack_detail::push_reference(L_, k + 1);
22478 p += stack::stack_detail::push_reference<push_type>(L_, detail::deref_move_only(*it));
22479 std::advance(it, 1);
22486 return next_associative<ip>(is_assoc(), L_);
22490 static int pairs_associative(std::true_type,
lua_State* L_) {
22491 auto& src = get_src(L_);
22492 stack::push(L_, next_iter<ip>);
22493 stack::push<user<iter>>(L_, L_, 1, src, deferred_uc::begin(L_, src));
22494 stack::push(L_, lua_nil);
22499 static int pairs_associative(std::false_type,
lua_State* L_) {
22500 auto& src = get_src(L_);
22501 stack::push(L_, next_iter<ip>);
22502 stack::push<user<iter>>(L_, L_, 1, src, deferred_uc::begin(L_, src));
22503 stack::push(L_, 0);
22509 auto&
self = get_src(L_);
22512 std::ptrdiff_t pos = stack::unqualified_get<std::ptrdiff_t>(L_, 2);
22513 er = at_start(L_,
self, pos);
22515 return handle_errors(L_, er);
22519 auto&
self = get_src(L_);
22522 decltype(
auto) key = stack::unqualified_get<K>(L_);
22523 er = get_start(L_,
self, key);
22525 return handle_errors(L_, er);
22534 if constexpr (is_linear_integral::value) {
22538 auto key = stack::get<K>(L_, 2);
22539 auto self_size = deferred_uc::size(L_);
22540 if (key == static_cast<K>(self_size)) {
22541 if (type_of(L_, 3) == type::lua_nil) {
22547 if (type_of(L_, 3) == type::lua_nil) {
22551 auto&
self = get_src(L_);
22553 return handle_errors(L_, er);
22561 auto&
self = get_src(L_);
22563 return handle_errors(L_, er);
22567 auto&
self = get_src(L_);
22569 return handle_errors(L_, er);
22573 auto&
self = get_src(L_);
22575 return handle_errors(L_, er);
22579 auto&
self = get_src(L_);
22581 return handle_errors(L_, er);
22584 static iterator begin(
lua_State*, T&
self) {
22585 if constexpr (meta::has_begin_end_v<T>) {
22586 return self.begin();
22590 return begin(
self);
22594 static iterator end(
lua_State*, T&
self) {
22595 if constexpr (meta::has_begin_end_v<T>) {
22605 auto&
self = get_src(L_);
22606 std::size_t r = size_start(L_,
self);
22607 return stack::push(L_, r);
22611 auto&
self = get_src(L_);
22612 clear_start(L_,
self);
22617 auto&
self = get_src(L_);
22620 decltype(
auto) key = stack::unqualified_get<K>(L_, 2);
22621 er = erase_start(L_,
self, key);
22623 return handle_errors(L_, er);
22627 auto&
self = get_src(L_);
22628 return stack::push(L_, empty_start(L_,
self));
22631 static std::ptrdiff_t index_adjustment(
lua_State*, T&) {
22632 return static_cast<std::ptrdiff_t
>((SOL_CONTAINER_START_INDEX_I_) == 0 ? 0 : -(SOL_CONTAINER_START_INDEX_I_));
22637 return pairs_associative<false>(is_assoc(), L_);
22642 return pairs_associative<true>(is_assoc(), L_);
22646 return stack::push(L_, next_iter<false>);
22650 template <
typename X>
22653 typedef std::remove_pointer_t<meta::unwrap_unqualified_t<X>> T;
22657 typedef std::remove_extent_t<T> value_type;
22658 typedef value_type* iterator;
22666 iter(
lua_State* L_,
int stack_index, T& source, iterator it) noexcept
22667 : keep_alive(sol::main_thread(L_, L_), stack_index), source(source), it(std::move(it)) {
22676 auto p = stack::unqualified_check_get<T*>(L_, 1);
22677 #if SOL_IS_ON(SOL_SAFE_USERTYPE) 22680 "sol: 'self' is not of type '%s' (pass 'self' as first argument with ':' or call on proper type)",
22681 detail::demangle<T>().c_str());
22683 if (p.value() ==
nullptr) {
22685 L_,
"sol: 'self' argument is nil (pass 'self' as first argument with ':' or call on a '%s' type)", detail::demangle<T>().c_str());
22687 #endif // Safe getting with error 22691 static int find(std::true_type,
lua_State* L_) {
22692 T&
self = get_src(L_);
22693 decltype(
auto) value = stack::unqualified_get<value_type>(L_, 2);
22694 std::size_t N = std::extent<T>::value;
22695 for (std::size_t idx = 0; idx < N; ++idx) {
22696 using v_t = std::add_const_t<decltype(self[idx])>;
22699 idx =
static_cast<std::size_t
>(
static_cast<std::ptrdiff_t
>(idx) - deferred_uc::index_adjustment(L_,
self));
22700 return stack::push(L_, idx);
22703 return stack::push(L_, lua_nil);
22706 static int find(std::false_type,
lua_State* L_) {
22707 return luaL_error(L_,
"sol: cannot call 'find' on '%s': no supported comparison operator for the value type", detail::demangle<T>().c_str());
22711 iter& i = stack::unqualified_get<user<iter>>(L_, 1);
22712 auto& source = i.source;
22714 std::size_t k = stack::unqualified_get<std::size_t>(L_, 2);
22715 if (it == deferred_uc::end(L_, source)) {
22719 p = stack::push(L_, k + 1);
22720 p += stack::push_reference(L_, detail::deref_move_only(*it));
22721 std::advance(it, 1);
22727 return luaL_error(L_,
"sol: cannot call 'clear' on type '%s': cannot remove all items from a fixed array", detail::demangle<T>().c_str());
22731 return luaL_error(L_,
"sol: cannot call 'erase' on type '%s': cannot remove an item from fixed arrays", detail::demangle<T>().c_str());
22735 return luaL_error(L_,
"sol: cannot call 'add' on type '%s': cannot add to fixed arrays", detail::demangle<T>().c_str());
22739 return luaL_error(L_,
"sol: cannot call 'insert' on type '%s': cannot insert new entries into fixed arrays", detail::demangle<T>().c_str());
22747 T&
self = get_src(L_);
22748 std::ptrdiff_t idx = stack::unqualified_get<std::ptrdiff_t>(L_, 2);
22749 idx += deferred_uc::index_adjustment(L_,
self);
22750 if (idx >= static_cast<std::ptrdiff_t>(std::extent<T>::value) || idx < 0) {
22751 return stack::push(L_, lua_nil);
22753 return stack::push_reference(L_, detail::deref_move_only(
self[idx]));
22761 T&
self = get_src(L_);
22762 std::ptrdiff_t idx = stack::unqualified_get<std::ptrdiff_t>(L_, 2);
22763 idx += deferred_uc::index_adjustment(L_,
self);
22764 if (idx >= static_cast<std::ptrdiff_t>(std::extent<T>::value)) {
22765 return luaL_error(L_,
"sol: index out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str());
22768 return luaL_error(L_,
"sol: index out of bounds (too small) for set on '%s'", detail::demangle<T>().c_str());
22770 self[idx] = stack::unqualified_get<value_type>(L_, 3);
22787 return stack::push(L_, std::extent<T>::value);
22791 return stack::push(L_, std::extent<T>::value > 0);
22795 auto& src = get_src(L_);
22796 stack::push(L_, next_iter);
22797 stack::push<user<iter>>(L_, L_, 1, src, deferred_uc::begin(L_, src));
22798 stack::push(L_, 0);
22807 return stack::push(L_, next_iter);
22810 static std::ptrdiff_t index_adjustment(
lua_State*, T&) {
22811 return (SOL_CONTAINER_START_INDEX_I_) == 0 ? 0 : -(SOL_CONTAINER_START_INDEX_I_);
22814 static iterator begin(
lua_State*, T&
self) {
22815 return std::addressof(
self[0]);
22818 static iterator end(
lua_State*, T&
self) {
22819 return std::addressof(
self[0]) + std::extent<T>::value;
22823 template <
typename X>
22827 template <
typename T>
22834 #include <unordered_map> 22838 namespace container_detail {
22839 template <
typename X>
22841 using T = std::remove_pointer_t<meta::unqualified_t<X>>;
22845 static inline int real_index_get_traits(std::true_type,
lua_State* L) {
22846 return uc::index_get(L);
22849 static inline int real_index_get_traits(std::false_type,
lua_State* L) {
22850 return default_uc::index_get(L);
22853 static inline int real_index_call(
lua_State* L) {
22854 static const std::unordered_map<string_view, lua_CFunction> calls {
22855 {
"at", &real_at_call },
22856 {
"get", &real_get_call },
22857 {
"set", &real_set_call },
22858 {
"size", &real_length_call },
22859 {
"add", &real_add_call },
22860 {
"empty", &real_empty_call },
22861 {
"insert", &real_insert_call },
22862 {
"clear", &real_clear_call },
22863 {
"find", &real_find_call },
22864 {
"index_of", &real_index_of_call },
22865 {
"erase", &real_erase_call },
22866 {
"pairs", &pairs_call },
22867 {
"next", &next_call },
22869 auto maybenameview = stack::unqualified_check_get<string_view>(L, 2);
22870 if (maybenameview) {
22871 const string_view& name = *maybenameview;
22872 auto it = calls.find(name);
22873 if (it != calls.cend()) {
22874 return stack::push(L, it->second);
22877 return real_index_get_traits(container_detail::has_traits_index_get<uc>(), L);
22880 static inline int real_at_traits(std::true_type,
lua_State* L) {
22884 static inline int real_at_traits(std::false_type,
lua_State* L) {
22885 return default_uc::at(L);
22888 static inline int real_at_call(
lua_State* L) {
22889 return real_at_traits(container_detail::has_traits_at<uc>(), L);
22892 static inline int real_get_traits(std::true_type,
lua_State* L) {
22896 static inline int real_get_traits(std::false_type,
lua_State* L) {
22897 return default_uc::get(L);
22900 static inline int real_get_call(
lua_State* L) {
22901 return real_get_traits(container_detail::has_traits_get<uc>(), L);
22904 static inline int real_set_traits(std::true_type,
lua_State* L) {
22908 static inline int real_set_traits(std::false_type,
lua_State* L) {
22909 return default_uc::set(L);
22912 static inline int real_set_call(
lua_State* L) {
22913 return real_set_traits(container_detail::has_traits_set<uc>(), L);
22916 static inline int real_index_set_traits(std::true_type,
lua_State* L) {
22917 return uc::index_set(L);
22920 static inline int real_index_set_traits(std::false_type,
lua_State* L) {
22921 return default_uc::index_set(L);
22924 static inline int real_new_index_call(
lua_State* L) {
22925 return real_index_set_traits(container_detail::has_traits_index_set<uc>(), L);
22928 static inline int real_pairs_traits(std::true_type,
lua_State* L) {
22929 return uc::pairs(L);
22932 static inline int real_pairs_traits(std::false_type,
lua_State* L) {
22933 return default_uc::pairs(L);
22936 static inline int real_pairs_call(
lua_State* L) {
22937 return real_pairs_traits(container_detail::has_traits_pairs<uc>(), L);
22940 static inline int real_ipairs_traits(std::true_type,
lua_State* L) {
22941 return uc::ipairs(L);
22944 static inline int real_ipairs_traits(std::false_type,
lua_State* L) {
22945 return default_uc::ipairs(L);
22948 static inline int real_ipairs_call(
lua_State* L) {
22949 return real_ipairs_traits(container_detail::has_traits_ipairs<uc>(), L);
22952 static inline int real_next_traits(std::true_type,
lua_State* L) {
22953 return uc::next(L);
22956 static inline int real_next_traits(std::false_type,
lua_State* L) {
22957 return default_uc::next(L);
22960 static inline int real_next_call(
lua_State* L) {
22961 return real_next_traits(container_detail::has_traits_next<uc>(), L);
22964 static inline int real_size_traits(std::true_type,
lua_State* L) {
22965 return uc::size(L);
22968 static inline int real_size_traits(std::false_type,
lua_State* L) {
22969 return default_uc::size(L);
22972 static inline int real_length_call(
lua_State* L) {
22973 return real_size_traits(container_detail::has_traits_size<uc>(), L);
22976 static inline int real_add_traits(std::true_type,
lua_State* L) {
22980 static inline int real_add_traits(std::false_type,
lua_State* L) {
22981 return default_uc::add(L);
22984 static inline int real_add_call(
lua_State* L) {
22985 return real_add_traits(container_detail::has_traits_add<uc>(), L);
22988 static inline int real_insert_traits(std::true_type,
lua_State* L) {
22989 return uc::insert(L);
22992 static inline int real_insert_traits(std::false_type,
lua_State* L) {
22993 return default_uc::insert(L);
22996 static inline int real_insert_call(
lua_State* L) {
22997 return real_insert_traits(container_detail::has_traits_insert<uc>(), L);
23000 static inline int real_clear_traits(std::true_type,
lua_State* L) {
23001 return uc::clear(L);
23004 static inline int real_clear_traits(std::false_type,
lua_State* L) {
23005 return default_uc::clear(L);
23008 static inline int real_clear_call(
lua_State* L) {
23009 return real_clear_traits(container_detail::has_traits_clear<uc>(), L);
23012 static inline int real_empty_traits(std::true_type,
lua_State* L) {
23013 return uc::empty(L);
23016 static inline int real_empty_traits(std::false_type,
lua_State* L) {
23017 return default_uc::empty(L);
23020 static inline int real_empty_call(
lua_State* L) {
23021 return real_empty_traits(container_detail::has_traits_empty<uc>(), L);
23024 static inline int real_erase_traits(std::true_type,
lua_State* L) {
23025 return uc::erase(L);
23028 static inline int real_erase_traits(std::false_type,
lua_State* L) {
23029 return default_uc::erase(L);
23032 static inline int real_erase_call(
lua_State* L) {
23033 return real_erase_traits(container_detail::has_traits_erase<uc>(), L);
23036 static inline int real_find_traits(std::true_type,
lua_State* L) {
23037 return uc::find(L);
23040 static inline int real_find_traits(std::false_type,
lua_State* L) {
23041 return default_uc::find(L);
23044 static inline int real_find_call(
lua_State* L) {
23045 return real_find_traits(container_detail::has_traits_find<uc>(), L);
23048 static inline int real_index_of_call(
lua_State* L) {
23049 if constexpr (container_detail::has_traits_index_of<uc>()) {
23050 return uc::index_of(L);
23053 return default_uc::index_of(L);
23057 static inline int add_call(
lua_State* L) {
23058 return detail::typed_static_trampoline<decltype(&real_add_call), (&real_add_call)>(L);
23061 static inline int erase_call(
lua_State* L) {
23062 return detail::typed_static_trampoline<decltype(&real_erase_call), (&real_erase_call)>(L);
23065 static inline int insert_call(
lua_State* L) {
23066 return detail::typed_static_trampoline<decltype(&real_insert_call), (&real_insert_call)>(L);
23069 static inline int clear_call(
lua_State* L) {
23070 return detail::typed_static_trampoline<decltype(&real_clear_call), (&real_clear_call)>(L);
23073 static inline int empty_call(
lua_State* L) {
23074 return detail::typed_static_trampoline<decltype(&real_empty_call), (&real_empty_call)>(L);
23077 static inline int find_call(
lua_State* L) {
23078 return detail::typed_static_trampoline<decltype(&real_find_call), (&real_find_call)>(L);
23081 static inline int index_of_call(
lua_State* L) {
23082 return detail::typed_static_trampoline<decltype(&real_index_of_call), (&real_index_of_call)>(L);
23085 static inline int length_call(
lua_State* L) {
23086 return detail::typed_static_trampoline<decltype(&real_length_call), (&real_length_call)>(L);
23089 static inline int pairs_call(
lua_State* L) {
23090 return detail::typed_static_trampoline<decltype(&real_pairs_call), (&real_pairs_call)>(L);
23093 static inline int ipairs_call(
lua_State* L) {
23094 return detail::typed_static_trampoline<decltype(&real_ipairs_call), (&real_ipairs_call)>(L);
23097 static inline int next_call(
lua_State* L) {
23098 return detail::typed_static_trampoline<decltype(&real_next_call), (&real_next_call)>(L);
23101 static inline int at_call(
lua_State* L) {
23102 return detail::typed_static_trampoline<decltype(&real_at_call), (&real_at_call)>(L);
23105 static inline int get_call(
lua_State* L) {
23106 return detail::typed_static_trampoline<decltype(&real_get_call), (&real_get_call)>(L);
23109 static inline int set_call(
lua_State* L) {
23110 return detail::typed_static_trampoline<decltype(&real_set_call), (&real_set_call)>(L);
23113 static inline int index_call(
lua_State* L) {
23114 return detail::typed_static_trampoline<decltype(&real_index_call), (&real_index_call)>(L);
23117 static inline int new_index_call(
lua_State* L) {
23118 return detail::typed_static_trampoline<decltype(&real_new_index_call), (&real_new_index_call)>(L);
23124 namespace stack_detail {
23125 template <
typename T,
bool is_shim = false>
23132 void operator()() {
23133 using meta_usertype_container
23135 static const char* metakey
23137 static const std::array<luaL_Reg, 20> reg = { {
23139 {
"__pairs", &meta_usertype_container::pairs_call },
23140 {
"__ipairs", &meta_usertype_container::ipairs_call },
23141 {
"__len", &meta_usertype_container::length_call },
23142 {
"__index", &meta_usertype_container::index_call },
23143 {
"__newindex", &meta_usertype_container::new_index_call },
23144 {
"pairs", &meta_usertype_container::pairs_call },
23145 {
"next", &meta_usertype_container::next_call },
23146 {
"at", &meta_usertype_container::at_call },
23147 {
"get", &meta_usertype_container::get_call },
23148 {
"set", &meta_usertype_container::set_call },
23149 {
"size", &meta_usertype_container::length_call },
23150 {
"empty", &meta_usertype_container::empty_call },
23151 {
"clear", &meta_usertype_container::clear_call },
23152 {
"insert", &meta_usertype_container::insert_call },
23153 {
"add", &meta_usertype_container::add_call },
23154 {
"find", &meta_usertype_container::find_call },
23155 {
"index_of", &meta_usertype_container::index_of_call },
23156 {
"erase", &meta_usertype_container::erase_call },
23157 std::is_pointer<T>::value ?
luaL_Reg{
nullptr,
nullptr } :
luaL_Reg{
"__gc", &detail::usertype_alloc_destroy<T> },
23158 {
nullptr,
nullptr }
23162 if (luaL_newmetatable(L, metakey) == 1) {
23163 luaL_setfuncs(L, reg.data(), 0);
23165 lua_setmetatable(L, -2);
23170 template <
typename T>
23172 using C = meta::unqualified_t<T>;
23174 static int push_lvalue(std::true_type,
lua_State* L,
const C& cont) {
23179 static int push_lvalue(std::false_type,
lua_State* L,
const C& cont) {
23184 static int push_rvalue(std::true_type,
lua_State* L, C&& cont) {
23189 static int push_rvalue(std::false_type,
lua_State* L,
const C& cont) {
23190 return push_lvalue(std::is_lvalue_reference<T>(), L, cont);
23194 return push_lvalue(std::is_lvalue_reference<T>(), L, as_cont.value());
23198 return push_rvalue(
meta::all<std::is_rvalue_reference<T>, meta::neg<std::is_lvalue_reference<T>>>(), L, std::forward<T>(as_cont.value()));
23202 template <
typename T>
23204 using C = std::add_pointer_t<meta::unqualified_t<std::remove_pointer_t<T>>>;
23206 static int push(
lua_State* L, T* cont) {
23212 template <
typename T>
23216 template <
typename... Args>
23217 static int push(
lua_State* L, Args&&... args) {
23223 template <
typename T>
23225 using C = std::add_pointer_t<meta::unqualified_t<std::remove_pointer_t<T>>>;
23227 static int push(
lua_State* L, T* cont) {
23239 #include <type_traits> 23242 namespace u_detail {
23243 constexpr
const lua_Integer toplevel_magic =
static_cast<lua_Integer
>(0xCCC2CCC1);
23245 constexpr
const int environment_index = 1;
23246 constexpr
const int usertype_storage_index = 2;
23247 constexpr
const int usertype_storage_base_index = 3;
23248 constexpr
const int exact_function_index = 4;
23249 constexpr
const int magic_index = 5;
23251 constexpr
const int simple_usertype_storage_index = 2;
23252 constexpr
const int index_function_index = 3;
23253 constexpr
const int new_index_function_index = 4;
23255 constexpr
const int base_walking_failed_index = -32467;
23256 constexpr
const int lookup_failed_index = -42469;
23258 enum class submetatable_type {
23269 inline auto make_string_view(string_view s) {
23273 #if SOL_IS_ON(SOL_CHAR8_T) 23274 inline auto make_string_view(
const char8_t* s) {
23275 return string_view(reinterpret_cast<const char*>(s));
23280 return string_view(to_string(meta_function::call_function));
23283 inline auto make_string_view(meta_function mf) {
23284 return string_view(to_string(mf));
23288 return string_view(detail::base_class_cast_key());
23291 template <
typename Arg>
23292 inline std::string make_string(Arg&& arg) {
23293 string_view s = make_string_view(arg);
23294 return std::string(s.data(), s.size());
23297 inline int is_indexer(string_view s) {
23298 if (s == to_string(meta_function::index)) {
23301 else if (s == to_string(meta_function::new_index)) {
23307 inline int is_indexer(meta_function mf) {
23308 if (mf == meta_function::index) {
23311 else if (mf == meta_function::new_index) {
23324 template <
typename T,
typename IFx,
typename Fx>
23325 inline void insert_default_registrations(IFx&& ifx, Fx&& fx) {
23329 if (fx(meta_function::less_than)) {
23331 lua_CFunction f = &comparsion_operator_wrap<T, std::less<>>;
23332 ifx(meta_function::less_than, f);
23335 if (fx(meta_function::less_than_or_equal_to)) {
23337 lua_CFunction f = &comparsion_operator_wrap<T, std::less_equal<>>;
23338 ifx(meta_function::less_than_or_equal_to, f);
23341 if (fx(meta_function::equal_to)) {
23343 lua_CFunction f = &comparsion_operator_wrap<T, std::equal_to<>>;
23344 ifx(meta_function::equal_to, f);
23347 lua_CFunction f = &comparsion_operator_wrap<T, no_comp>;
23348 ifx(meta_function::equal_to, f);
23351 if (fx(meta_function::pairs)) {
23354 if (fx(meta_function::length)) {
23355 if constexpr (meta::has_size<const T>::value || meta::has_size<T>::value) {
23356 auto f = &default_size<T>;
23357 ifx(meta_function::length, f);
23360 if (fx(meta_function::to_string)) {
23361 if constexpr (is_to_stringable_v<T>) {
23362 if constexpr (!meta::is_probably_stateless_lambda_v<T> && !std::is_member_pointer_v<T>) {
23363 auto f = &detail::static_trampoline<&default_to_string<T>>;
23364 ifx(meta_function::to_string, f);
23368 if (fx(meta_function::call_function)) {
23369 if constexpr (is_callable_v<T>) {
23370 if constexpr (meta::call_operator_deducible_v<T>) {
23371 auto f = &c_call<decltype(&T::operator()), &T::operator()>;
23372 ifx(meta_function::call_function, f);
23380 namespace stack {
namespace stack_detail {
23381 template <
typename X>
23383 using T = std::remove_pointer_t<X>;
23389 detail::lua_reg_table l {};
23392 detail::insert_default_registrations<T>(insert_fx, detail::property_always_true);
23393 if constexpr (!std::is_pointer_v<X>) {
23394 l[index] =
luaL_Reg { to_string(meta_function::garbage_collect).c_str(), detail::make_destructor<T>() };
23396 luaL_setfuncs(L, l, 0);
23399 lua_createtable(L, 0, 2);
23400 const std::string& name = detail::demangle<T>();
23401 lua_pushlstring(L, name.c_str(), name.size());
23402 lua_setfield(L, -2,
"name");
23403 lua_CFunction is_func = &detail::is_check<T>;
23404 lua_pushcclosure(L, is_func, 0);
23405 lua_setfield(L, -2,
"is");
23406 lua_setfield(L, t.stack_index(), to_string(meta_function::type).c_str());
23418 #include <unordered_map> 23421 namespace sol {
namespace u_detail {
23423 struct usertype_storage_base;
23424 template <
typename T>
23429 template <
typename T>
23431 template <
typename T>
23434 using index_call_function = int(
lua_State*,
void*);
23439 index_call_function* index;
23440 index_call_function* new_index;
23441 void* binding_data;
23445 void* new_binding_data;
23449 virtual void* data() = 0;
23454 template <
typename K,
typename Fq,
typename T =
void>
23456 using uF = meta::unqualified_t<Fq>;
23457 using F = meta::conditional_t<meta::is_c_str_of_v<uF, char>
23458 #if SOL_IS_ON(SOL_CHAR8_T) 23459 || meta::is_c_str_of_v<uF, char8_t>
23461 || meta::is_c_str_of_v<uF, char16_t> || meta::is_c_str_of_v<uF, char32_t> || meta::is_c_str_of_v<uF, wchar_t>,
23462 std::add_pointer_t<std::add_const_t<std::remove_all_extents_t<Fq>>>, std::decay_t<Fq>>;
23465 template <
typename... Args>
23466 binding(Args&&... args) : data_(std::forward<Args>(args)...) {
23469 virtual void* data()
override {
23470 return static_cast<void*
>(std::addressof(data_));
23473 template <
bool is_index = true,
bool is_variable = false>
23474 static inline int call_with_(
lua_State* L_,
void* target) {
23476 auto& f = *
static_cast<F*
>(target);
23477 return call_detail::call_wrapped<T, is_index, is_variable, boost>(L_, f);
23480 template <
bool is_index = true,
bool is_variable = false>
23481 static inline int call_(
lua_State* L_) {
23482 void* f = stack::get<void*>(L_,
upvalue_index(usertype_storage_index));
23483 return call_with_<is_index, is_variable>(L_, f);
23486 template <
bool is_index = true,
bool is_variable = false>
23487 static inline int call(
lua_State* L_) {
23488 int r = detail::typed_static_trampoline<decltype(&call_<is_index, is_variable>), (&call_<is_index, is_variable>)>(L_);
23489 if constexpr (meta::is_specialization_of_v<uF, yielding_t>) {
23490 return lua_yield(L_, r);
23497 template <
bool is_index = true,
bool is_variable = false>
23498 static inline int index_call_with_(
lua_State* L_,
void* target) {
23499 if constexpr (!is_variable) {
23500 if constexpr (is_lua_c_function_v<std::decay_t<F>>) {
23501 auto& f = *
static_cast<std::decay_t<F>*
>(target);
23502 return stack::push(L_, f);
23508 upvalues += stack::push(L_,
nullptr);
23509 upvalues += stack::push(L_, target);
23510 auto cfunc = &call<is_index, is_variable>;
23511 return stack::push(L_,
c_closure(cfunc, upvalues));
23516 auto& f = *
static_cast<F*
>(target);
23517 return call_detail::call_wrapped<T, is_index, is_variable, boost>(L_, f);
23521 template <
bool is_index = true,
bool is_variable = false>
23522 static inline int index_call_(
lua_State* L_) {
23523 void* f = stack::get<void*>(L_,
upvalue_index(usertype_storage_index));
23524 return index_call_with_<is_index, is_variable>(L_, f);
23527 template <
bool is_index = true,
bool is_variable = false>
23528 static inline int index_call(
lua_State* L_) {
23529 int r = detail::typed_static_trampoline<decltype(&index_call_<is_index, is_variable>), (&index_call_<is_index, is_variable>)>(L_);
23530 if constexpr (meta::is_specialization_of_v<uF, yielding_t>) {
23531 return lua_yield(L_, r);
23540 if (lua_getmetatable(L_, 1) == 1) {
23541 int metatarget = lua_gettop(L_);
23548 return stack::push(L_, lua_nil);
23551 inline int index_target_fail(
lua_State* L_,
void*) {
23552 return index_fail(L_);
23555 inline int new_index_fail(
lua_State* L_) {
23556 return luaL_error(L_,
"sol: cannot set (new_index) into this object: no defined new_index operation on usertype");
23559 inline int new_index_target_fail(
lua_State* L_,
void*) {
23560 return new_index_fail(L_);
23564 bool is_destruction =
false;
23565 bool is_index =
false;
23566 bool is_new_index =
false;
23567 bool is_static_index =
false;
23568 bool is_static_new_index =
false;
23569 bool poison_indexing =
false;
23570 bool is_unqualified_lua_CFunction =
false;
23571 bool is_unqualified_lua_reference =
false;
23572 std::string* p_key =
nullptr;
23574 lua_CFunction call_func =
nullptr;
23577 void* p_derived_usb =
nullptr;
23578 lua_CFunction idx_call =
nullptr, new_idx_call =
nullptr, meta_idx_call =
nullptr, meta_new_idx_call =
nullptr;
23579 change_indexing_mem_func change_indexing;
23582 std::string& key = *p_key;
23586 if (smt_ == submetatable_type::named) {
23593 int fast_index_table_push = fast_index_table_.push(L_);
23594 stateless_stack_reference t(L_, -fast_index_table_push);
23595 if (poison_indexing) {
23596 (usb.*change_indexing)(L_, smt_, p_derived_usb, t, idx_call, new_idx_call, meta_idx_call, meta_new_idx_call);
23599 && (smt_ == submetatable_type::reference || smt_ == submetatable_type::const_reference || smt_ == submetatable_type::named
23600 || smt_ == submetatable_type::unique)) {
23608 if (is_index || is_new_index || is_static_index || is_static_new_index) {
23614 if (is_unqualified_lua_CFunction) {
23615 stack::set_field<false, true>(L_, key, call_func, t.stack_index());
23617 else if (is_unqualified_lua_reference) {
23618 reference& binding_ref = *p_binding_ref;
23619 stack::set_field<false, true>(L_, key, binding_ref, t.stack_index());
23622 stack::set_field<false, true>(L_, key, make_closure(call_func,
nullptr, ics.binding_data), t.stack_index());
23633 if (smt_ == submetatable_type::named) {
23636 int fast_index_table_push = fast_index_table_.push(L_);
23637 stateless_stack_reference t(L_, -fast_index_table_push);
23638 stack::set_field<false, true>(L_, key, value, t.stack_index());
23644 detail::inheritance_check_function base_class_check_func;
23645 detail::inheritance_cast_function base_class_cast_func;
23646 lua_CFunction idx_call, new_idx_call, meta_idx_call, meta_new_idx_call;
23648 void* p_derived_usb;
23649 change_indexing_mem_func change_indexing;
23652 int fast_index_table_push = fast_index_table_.push(L_);
23653 stateless_stack_reference t(L_, -fast_index_table_push);
23654 stack::set_field(L_, detail::base_class_check_key(), reinterpret_cast<void*>(base_class_check_func), t.stack_index());
23655 stack::set_field(L_, detail::base_class_cast_key(), reinterpret_cast<void*>(base_class_cast_func), t.stack_index());
23657 (p_usb->*change_indexing)(L_, smt_, p_derived_usb, t, idx_call, new_idx_call, meta_idx_call, meta_new_idx_call);
23663 void* binding_data;
23668 bool operator()(
const std::unique_ptr<binding_base>& ptr)
const {
23669 return binding_data == ptr->data();
23676 std::vector<std::unique_ptr<binding_base>> storage;
23677 std::vector<std::unique_ptr<char[]>> string_keys_storage;
23678 std::unordered_map<string_view, index_call_storage> string_keys;
23679 std::unordered_map<stateless_reference, stateless_reference, stateless_reference_hash, stateless_reference_equals> auxiliary_keys;
23691 bool is_using_index;
23692 bool is_using_new_index;
23693 std::bitset<64> properties;
23698 , string_keys_storage()
23701 , value_index_table()
23702 , reference_index_table()
23703 , unique_index_table()
23704 , const_reference_index_table()
23705 , const_value_index_table()
23706 , named_index_table()
23707 , type_table(make_reference<stateless_reference>(L_, create))
23708 , gc_names_table(make_reference<stateless_reference>(L_, create))
23709 , named_metatable(make_reference<stateless_reference>(L_, create))
23711 , static_base_index()
23712 , is_using_index(
false)
23713 , is_using_new_index(
false)
23715 base_index.binding_data =
nullptr;
23716 base_index.index = index_target_fail;
23717 base_index.new_index = new_index_target_fail;
23718 base_index.new_binding_data =
nullptr;
23719 static_base_index.binding_data =
nullptr;
23720 static_base_index.index = index_target_fail;
23721 static_base_index.new_binding_data =
this;
23722 static_base_index.new_index = new_index_target_set;
23725 template <
typename Fx>
23726 void for_each_table(
lua_State* L_, Fx&& fx) {
23727 for (
int i = 0; i < 6; ++i) {
23728 submetatable_type smt =
static_cast<submetatable_type
>(i);
23731 case submetatable_type::const_value:
23732 p_fast_index_table = &this->const_value_index_table;
23734 case submetatable_type::reference:
23735 p_fast_index_table = &this->reference_index_table;
23737 case submetatable_type::unique:
23738 p_fast_index_table = &this->unique_index_table;
23740 case submetatable_type::const_reference:
23741 p_fast_index_table = &this->const_reference_index_table;
23743 case submetatable_type::named:
23744 p_fast_index_table = &this->named_index_table;
23746 case submetatable_type::value:
23748 p_fast_index_table = &this->value_index_table;
23751 fx(L_, smt, *p_fast_index_table);
23756 string_keys_storage.emplace_back(
new char[sv.size()]);
23757 std::unique_ptr<char[]>& sv_storage = string_keys_storage.back();
23758 std::memcpy(sv_storage.get(), sv.data(), sv.size());
23759 string_view stored_sv(sv_storage.get(), sv.size());
23760 string_keys.insert_or_assign(std::move(stored_sv), std::move(ics));
23763 template <
typename T,
typename... Bases>
23765 static_assert(
sizeof(
void*) <=
sizeof(detail::inheritance_check_function),
23766 "The size of this data pointer is too small to fit the inheritance checking function: Please file " 23768 static_assert(
sizeof(
void*) <=
sizeof(detail::inheritance_cast_function),
23769 "The size of this data pointer is too small to fit the inheritance checking function: Please file " 23772 if constexpr (
sizeof...(Bases) > 0) {
23784 for_each_fx.p_usb =
this;
23785 for_each_fx.p_derived_usb = derived_this;
23786 for_each_fx.change_indexing = &usertype_storage_base::change_indexing;
23787 for_each_fx.p_derived_usb = derived_this;
23788 this->for_each_table(L_, for_each_fx);
23796 if (value_index_table.valid(m_L)) {
23797 stack::clear(m_L, value_index_table);
23799 if (reference_index_table.valid(m_L)) {
23800 stack::clear(m_L, reference_index_table);
23802 if (unique_index_table.valid(m_L)) {
23803 stack::clear(m_L, unique_index_table);
23805 if (const_reference_index_table.valid(m_L)) {
23806 stack::clear(m_L, const_reference_index_table);
23808 if (const_value_index_table.valid(m_L)) {
23809 stack::clear(m_L, const_value_index_table);
23811 if (named_index_table.valid(m_L)) {
23812 stack::clear(m_L, named_index_table);
23814 if (type_table.valid(m_L)) {
23815 stack::clear(m_L, type_table);
23817 if (gc_names_table.valid(m_L)) {
23818 stack::clear(m_L, gc_names_table);
23820 if (named_metatable.valid(m_L)) {
23821 auto pp = stack::push_pop(m_L, named_metatable);
23822 int named_metatable_index = pp.index_of(named_metatable);
23823 if (lua_getmetatable(m_L, named_metatable_index) == 1) {
23826 stack::clear(m_L, named_metatable);
23829 value_index_table.reset(m_L);
23830 reference_index_table.reset(m_L);
23831 unique_index_table.reset(m_L);
23832 const_reference_index_table.reset(m_L);
23833 const_value_index_table.reset(m_L);
23834 named_index_table.reset(m_L);
23835 type_table.reset(m_L);
23836 gc_names_table.reset(m_L);
23837 named_metatable.reset(m_L);
23840 string_keys.clear();
23841 auxiliary_keys.clear();
23842 string_keys_storage.clear();
23845 template <
bool is_new_index,
typename Base>
23853 #if SOL_IS_ON(SOL_USE_UNSAFE_BASE_LOOKUP) 23855 base_result = self_index_call<is_new_index, true>(
bases(), L_, base_storage);
23858 if (static_cast<bool>(maybe_base_storage)) {
23859 base_result = self_index_call<is_new_index, true>(
bases(), L_, *maybe_base_storage);
23860 keep_going = base_result == base_walking_failed_index;
23862 #endif // Fast versus slow, safe base lookup 23865 template <
bool is_new_index =
false,
bool base_walking =
false,
bool from_named_metatable =
false,
typename... Bases>
23867 if constexpr (!from_named_metatable || !is_new_index) {
23868 type k_type = stack::get<type>(L, 2);
23869 if (k_type == type::string) {
23871 string_view k = stack::get<string_view>(L, 2);
23873 auto it =
self.string_keys.find(k);
23874 if (it !=
self.string_keys.cend()) {
23875 target = &it->second;
23878 if (target !=
nullptr) {
23880 if constexpr (is_new_index) {
23881 return (target->new_index)(L, target->binding_data);
23884 return (target->index)(L, target->binding_data);
23888 else if (k_type != type::lua_nil && k_type != type::none) {
23892 auto it =
self.auxiliary_keys.find(k);
23893 if (it !=
self.auxiliary_keys.cend()) {
23894 target = &it->second;
23897 if (target !=
nullptr) {
23898 if constexpr (is_new_index) {
23900 target->reset(L, 3);
23906 return stack::push(L, *target);
23913 bool keep_going =
true;
23917 (void)detail::swallow { 1, (base_walk_index<is_new_index, Bases>(L,
self, keep_going, base_result), 1)... };
23918 if constexpr (
sizeof...(Bases) > 0) {
23920 return base_result;
23923 if constexpr (base_walking) {
23926 return base_walking_failed_index;
23928 else if constexpr (from_named_metatable) {
23929 if constexpr (is_new_index) {
23930 return self.static_base_index.new_index(L,
self.static_base_index.new_binding_data);
23933 return self.static_base_index.index(L,
self.static_base_index.binding_data);
23937 if constexpr (is_new_index) {
23938 return self.base_index.new_index(L,
self.base_index.new_binding_data);
23941 return self.base_index.index(L,
self.base_index.binding_data);
23946 void change_indexing(
lua_State* L_, submetatable_type submetatable_,
void* derived_this_, stateless_stack_reference& t_, lua_CFunction index_,
23947 lua_CFunction new_index_, lua_CFunction meta_index_, lua_CFunction meta_new_index_) {
23949 void* base_this =
static_cast<void*
>(&this_base);
23951 this->is_using_index |=
true;
23952 this->is_using_new_index |=
true;
23953 if (submetatable_ == submetatable_type::named) {
23954 stack::set_field(L_, metatable_key, named_index_table, t_.stack_index());
23955 stateless_stack_reference stack_metametatable(L_, -named_metatable.push(L_));
23956 stack::set_field<false, true>(L_,
23957 meta_function::index,
23958 make_closure(meta_index_,
nullptr, derived_this_, base_this,
nullptr, toplevel_magic),
23959 stack_metametatable.stack_index());
23960 stack::set_field<false, true>(L_,
23961 meta_function::new_index,
23962 make_closure(meta_new_index_,
nullptr, derived_this_, base_this,
nullptr, toplevel_magic),
23963 stack_metametatable.stack_index());
23964 stack_metametatable.pop(L_);
23967 stack::set_field<false, true>(
23968 L_, meta_function::index, make_closure(index_,
nullptr, derived_this_, base_this,
nullptr, toplevel_magic), t_.stack_index());
23969 stack::set_field<false, true>(
23970 L_, meta_function::new_index, make_closure(new_index_,
nullptr, derived_this_, base_this,
nullptr, toplevel_magic), t_.stack_index());
23974 template <
typename T =
void,
typename Key,
typename Value>
23977 static int new_index_target_set(
lua_State* L,
void* target) {
23984 value_index_table.reset(m_L);
23985 reference_index_table.reset(m_L);
23986 unique_index_table.reset(m_L);
23987 const_reference_index_table.reset(m_L);
23988 const_value_index_table.reset(m_L);
23989 named_index_table.reset(m_L);
23990 type_table.reset(m_L);
23991 gc_names_table.reset(m_L);
23992 named_metatable.reset(m_L);
23994 auto auxiliary_first = auxiliary_keys.cbegin();
23995 auto auxiliary_last = auxiliary_keys.cend();
23996 while (auxiliary_first != auxiliary_last) {
23998 auto auxiliary_target = auxiliary_first;
24002 auto extracted_node = auxiliary_keys.extract(auxiliary_target);
24003 extracted_node.key().reset(m_L);
24004 extracted_node.mapped().reset(m_L);
24010 template <
typename T>
24013 using usertype_storage_base::usertype_storage_base;
24015 template <
bool is_new_index,
bool from_named_metatable>
24016 static inline int index_call_(
lua_State* L) {
24019 return self_index_call<is_new_index, false, from_named_metatable>(
bases(), L,
self);
24022 template <
bool is_new_index,
bool from_named_metatable,
typename... Bases>
24023 static inline int index_call_with_bases_(
lua_State* L) {
24026 return self_index_call<is_new_index, false, from_named_metatable>(
bases(), L,
self);
24029 template <
bool is_new_index>
24030 static inline int index_call(
lua_State* L) {
24031 return detail::static_trampoline<&index_call_<is_new_index, false>>(L);
24034 template <
bool is_new_index,
typename... Bases>
24035 static inline int index_call_with_bases(
lua_State* L) {
24036 return detail::static_trampoline<&index_call_with_bases_<is_new_index,
false, Bases...>>(L);
24039 template <
bool is_new_index>
24040 static inline int meta_index_call(
lua_State* L) {
24041 return detail::static_trampoline<&index_call_<is_new_index, true>>(L);
24044 template <
bool is_new_index,
typename... Bases>
24045 static inline int meta_index_call_with_bases(
lua_State* L) {
24046 return detail::static_trampoline<&index_call_with_bases_<is_new_index,
true, Bases...>>(L);
24049 template <
typename Key,
typename Value>
24053 template <
typename T,
typename Key,
typename Value>
24054 void usertype_storage_base::set(
lua_State* L, Key&& key,
Value&& value) {
24055 using ValueU = meta::unwrap_unqualified_t<Value>;
24056 using KeyU = meta::unwrap_unqualified_t<Key>;
24059 if constexpr (std::is_same_v<KeyU, call_construction>) {
24061 std::unique_ptr<Binding> p_binding = std::make_unique<Binding>(std::forward<Value>(value));
24062 Binding& b = *p_binding;
24063 this->storage.push_back(std::move(p_binding));
24065 this->named_index_table.push(L);
24067 std::string_view call_metamethod_name = to_string(meta_function::call);
24068 lua_pushlstring(L, call_metamethod_name.data(), call_metamethod_name.size());
24069 stack::push(L,
nullptr);
24070 stack::push(L, b.data());
24071 lua_CFunction target_func = &b.template call<false, false>;
24072 lua_pushcclosure(L, target_func, 2);
24073 lua_rawset(L, metametatable_index);
24074 this->named_index_table.pop(L);
24076 else if constexpr (std::is_same_v<KeyU, base_classes_tag>) {
24078 this->update_bases<T>(L, std::forward<Value>(value));
24080 else if constexpr ((meta::is_string_like_or_constructible<KeyU>::value || std::is_same_v<KeyU, meta_function>)) {
24081 std::string s = u_detail::make_string(std::forward<Key>(key));
24082 auto storage_it = this->storage.end();
24083 auto string_it = this->string_keys.find(s);
24084 if (string_it != this->string_keys.cend()) {
24085 const auto& binding_data = string_it->second.binding_data;
24086 storage_it = std::find_if(this->storage.begin(), this->storage.end(),
binding_data_equals(binding_data));
24087 this->string_keys.erase(string_it);
24090 std::unique_ptr<Binding> p_binding = std::make_unique<Binding>(std::forward<Value>(value));
24091 Binding& b = *p_binding;
24092 if (storage_it != this->storage.cend()) {
24093 *storage_it = std::move(p_binding);
24096 this->storage.push_back(std::move(p_binding));
24099 bool is_index = (s == to_string(meta_function::index));
24100 bool is_new_index = (s == to_string(meta_function::new_index));
24101 bool is_static_index = (s == to_string(meta_function::static_index));
24102 bool is_static_new_index = (s == to_string(meta_function::static_new_index));
24103 bool is_destruction = s == to_string(meta_function::garbage_collect);
24104 bool poison_indexing = (!is_using_index || !is_using_new_index) && (is_var_bind::value || is_index || is_new_index);
24107 ics.binding_data = b.data();
24108 ics.index = is_index || is_static_index ? &Binding::template call_with_<true, is_var_bind::value>
24109 : &Binding::template index_call_with_<true, is_var_bind::value>;
24110 ics.new_index = is_new_index || is_static_new_index ? &Binding::template call_with_<false, is_var_bind::value>
24111 : &Binding::template index_call_with_<false, is_var_bind::value>;
24114 for_each_fx.is_destruction = is_destruction;
24115 for_each_fx.is_index = is_index;
24116 for_each_fx.is_new_index = is_new_index;
24117 for_each_fx.is_static_index = is_static_index;
24118 for_each_fx.is_static_new_index = is_static_new_index;
24119 for_each_fx.poison_indexing = poison_indexing;
24120 for_each_fx.p_key = &s;
24121 for_each_fx.p_ics = &ics;
24122 if constexpr (is_lua_c_function_v<ValueU>) {
24123 for_each_fx.is_unqualified_lua_CFunction =
true;
24124 for_each_fx.call_func = *
static_cast<lua_CFunction*
>(ics.binding_data);
24126 else if constexpr (is_lua_reference_or_proxy_v<ValueU>) {
24127 for_each_fx.is_unqualified_lua_reference =
true;
24128 for_each_fx.p_binding_ref =
static_cast<reference*
>(ics.binding_data);
24131 for_each_fx.call_func = &b.template call<false, is_var_bind::value>;
24133 for_each_fx.p_usb =
this;
24134 for_each_fx.p_derived_usb = derived_this;
24139 for_each_fx.change_indexing = &usertype_storage_base::change_indexing;
24143 this->base_index.index = ics.index;
24144 this->base_index.binding_data = ics.binding_data;
24146 if (is_new_index) {
24147 this->base_index.new_index = ics.new_index;
24148 this->base_index.new_binding_data = ics.binding_data;
24150 if (is_static_index) {
24151 this->static_base_index.index = ics.index;
24152 this->static_base_index.binding_data = ics.binding_data;
24154 if (is_static_new_index) {
24155 this->static_base_index.new_index = ics.new_index;
24156 this->static_base_index.new_binding_data = ics.binding_data;
24158 this->for_each_table(L, for_each_fx);
24159 this->add_entry(s, std::move(ics));
24164 if constexpr (is_lua_reference_v<KeyU> && is_lua_reference_v<ValueU>) {
24165 if (key.get_type() == type::string) {
24166 stack::push(L, key);
24167 std::string string_key = stack::pop<std::string>(L);
24168 this->set<T>(L, string_key, std::forward<Value>(value));
24173 this->for_each_table(L, ref_additions_fx);
24174 this->auxiliary_keys.insert_or_assign(std::forward<Key>(key), std::forward<Value>(value));
24178 reference ref_key = make_reference(L, std::forward<Key>(key));
24179 reference ref_value = make_reference(L, std::forward<Value>(value));
24182 this->for_each_table(L, ref_additions_fx);
24183 this->auxiliary_keys.insert_or_assign(std::move(ref_key), std::move(ref_value));
24188 template <
typename T>
24189 template <
typename Key,
typename Value>
24191 static_cast<usertype_storage_base&
>(*this).set<T>(L, std::forward<Key>(key), std::forward<Value>(value));
24194 template <
typename T>
24195 inline void clear_usertype_registry_names(
lua_State* L) {
24208 stack::set_field(L, &u_traits::metatable()[0], lua_nil, registry.stack_index());
24209 stack::set_field(L, &u_const_traits::metatable()[0], lua_nil, registry.stack_index());
24210 stack::set_field(L, &u_const_ref_traits::metatable()[0], lua_nil, registry.stack_index());
24211 stack::set_field(L, &u_ref_traits::metatable()[0], lua_nil, registry.stack_index());
24212 stack::set_field(L, &u_unique_traits::metatable()[0], lua_nil, registry.stack_index());
24216 template <
typename T>
24217 inline int destroy_usertype_storage(
lua_State* L) noexcept {
24218 clear_usertype_registry_names<T>(L);
24219 return detail::user_alloc_destroy<usertype_storage<T>>(L);
24222 template <
typename T>
24228 int usertype_storage_push_count = stack::push<user<usertype_storage<T>>>(L, no_metatable, L);
24229 stack_reference usertype_storage_ref(L, -usertype_storage_push_count);
24234 int usertype_storage_metatabe_count = stack::push(L,
new_table(0, 1));
24235 stack_reference usertype_storage_metatable(L, -usertype_storage_metatabe_count);
24237 stack::set_field(L, meta_function::garbage_collect, &destroy_usertype_storage<T>, usertype_storage_metatable.stack_index());
24239 stack::set_field(L, metatable_key, usertype_storage_metatable, usertype_storage_ref.stack_index());
24240 usertype_storage_metatable.pop();
24244 stack::set_field<true>(L, gcmetakey, usertype_storage_ref);
24245 usertype_storage_ref.pop();
24249 stack::get_field<true>(L, gcmetakey);
24255 if (type_of(L, index) != type::lightuserdata) {
24259 return base_storage;
24264 if (type_of(L, index) != type::table) {
24267 stack::get_field(L, meta_function::storage, index);
24268 auto maybe_storage_base = maybe_as_usertype_storage_base(L, -1);
24270 return maybe_storage_base;
24275 auto maybe_already_is_usertype_storage_base = maybe_as_usertype_storage_base(L, index);
24276 if (maybe_already_is_usertype_storage_base) {
24277 return maybe_already_is_usertype_storage_base;
24279 return maybe_get_usertype_storage_base_inside(L, index);
24283 stack::get_field<true>(L, gcmetakey);
24284 auto maybe_storage = maybe_as_usertype_storage_base(L, lua_gettop(L));
24286 return maybe_storage;
24290 stack::get_field<true>(L, gcmetakey);
24292 usertype_storage_base& target_umt = stack::stack_detail::unchecked_unqualified_get<user<usertype_storage_base>>(L, -1, tracking);
24297 template <
typename T>
24300 stack::get_field<true>(L, gcmetakey);
24301 int target = lua_gettop(L);
24309 template <
typename T>
24312 stack::get_field<true>(L, gcmetakey);
24317 template <
typename T>
24318 inline void clear_usertype_storage(
lua_State* L) {
24321 const char* gcmetakey = &u_traits::gc_table()[0];
24322 stack::get_field<true>(L, gcmetakey);
24328 target_umt.clear();
24330 clear_usertype_registry_names<T>(L);
24332 stack::set_field<true>(L, gcmetakey, lua_nil);
24335 template <
typename T, automagic_flags enrollment_flags>
24378 clear_usertype_storage<T>(L_);
24386 void* light_storage =
static_cast<void*
>(&storage);
24387 void* light_base_storage =
static_cast<void*
>(&base_storage);
24390 storage.gc_names_table.push(L_);
24391 stateless_stack_reference gnt(L_, -1);
24392 stack::set_field(L_, submetatable_type::named, &u_traits::gc_table()[0], gnt.stack_index());
24393 stack::set_field(L_, submetatable_type::const_value, &u_const_traits::metatable()[0], gnt.stack_index());
24394 stack::set_field(L_, submetatable_type::const_reference, &u_const_ref_traits::metatable()[0], gnt.stack_index());
24395 stack::set_field(L_, submetatable_type::reference, &u_ref_traits::metatable()[0], gnt.stack_index());
24396 stack::set_field(L_, submetatable_type::unique, &u_unique_traits::metatable()[0], gnt.stack_index());
24397 stack::set_field(L_, submetatable_type::value, &u_traits::metatable()[0], gnt.stack_index());
24401 stateless_stack_reference stacked_type_table(L_, -storage.type_table.push(L_));
24402 stack::set_field(L_,
"name", detail::demangle<T>(), stacked_type_table.stack_index());
24403 stack::set_field(L_,
"is", &detail::is_check<T>, stacked_type_table.stack_index());
24404 stacked_type_table.pop(L_);
24410 int for_each_backing_metatable_calls = 0;
24413 const char* metakey =
nullptr;
24415 case submetatable_type::const_value:
24416 metakey = &u_const_traits::metatable()[0];
24418 case submetatable_type::reference:
24419 metakey = &u_ref_traits::metatable()[0];
24421 case submetatable_type::unique:
24422 metakey = &u_unique_traits::metatable()[0];
24424 case submetatable_type::const_reference:
24425 metakey = &u_const_ref_traits::metatable()[0];
24427 case submetatable_type::named:
24428 metakey = &u_traits::user_metatable()[0];
24430 case submetatable_type::value:
24432 metakey = &u_traits::metatable()[0];
24436 luaL_newmetatable(L_, metakey);
24437 if (smt_ == submetatable_type::named) {
24440 storage.named_metatable.reset(L_, -1);
24445 lua_createtable(L_, 0, 6);
24447 stateless_stack_reference t(L_, -1);
24448 fast_index_table_.reset(L_, t.stack_index());
24449 stack::set_field<false, true>(L_, meta_function::type, storage.type_table, t.stack_index());
24453 case submetatable_type::const_reference:
24454 case submetatable_type::reference:
24455 case submetatable_type::named:
24457 case submetatable_type::unique:
24458 if constexpr (std::is_destructible_v<T>) {
24459 stack::set_field<false, true>(L_, meta_function::garbage_collect, &detail::unique_destroy<T>, t.stack_index());
24462 stack::set_field<false, true>(L_, meta_function::garbage_collect, &detail::cannot_destroy<T>, t.stack_index());
24465 case submetatable_type::value:
24466 case submetatable_type::const_value:
24468 if constexpr (std::is_destructible_v<T>) {
24469 stack::set_field<false, true>(L_, meta_function::garbage_collect, detail::make_destructor<T>(), t.stack_index());
24472 stack::set_field<false, true>(L_, meta_function::garbage_collect, &detail::cannot_destroy<T>, t.stack_index());
24477 static_assert(
sizeof(
void*) <=
sizeof(detail::inheritance_check_function),
24478 "The size of this data pointer is too small to fit the inheritance checking function: file a bug " 24480 static_assert(
sizeof(
void*) <=
sizeof(detail::inheritance_cast_function),
24481 "The size of this data pointer is too small to fit the inheritance checking function: file a bug " 24487 auto insert_fx = [&L_, &t, &storage](meta_function mf, lua_CFunction reg) {
24488 stack::set_field<false, true>(L_, mf, reg, t.stack_index());
24489 storage.properties[
static_cast<std::size_t
>(mf)] =
true;
24491 detail::insert_default_registrations<T>(insert_fx, prop_fx);
24496 if (smt_ == submetatable_type::named) {
24498 stack::set_field<false, true>(L_, meta_function::storage, light_base_storage, t.stack_index());
24499 stack::set_field<false, true>(L_, meta_function::gc_names, storage.gc_names_table, t.stack_index());
24503 absolute_index named_metatable_index(L_, -storage.named_metatable.push(L_));
24504 stack::set_field<false, true>(L_, metatable_key, t, named_metatable_index);
24505 storage.named_metatable.pop(L_);
24507 stack_reference stack_metametatable(L_, -storage.named_index_table.push(L_));
24508 stack::set_field<false, true>(L_,
24509 meta_function::index,
24510 make_closure(uts::template meta_index_call<false>,
nullptr, light_storage, light_base_storage,
nullptr, toplevel_magic),
24511 stack_metametatable.stack_index());
24512 stack::set_field<false, true>(L_,
24513 meta_function::new_index,
24514 make_closure(uts::template meta_index_call<true>,
nullptr, light_storage, light_base_storage,
nullptr, toplevel_magic),
24515 stack_metametatable.stack_index());
24516 stack_metametatable.pop();
24521 stack::set_field<false, true>(L_, meta_function::index, t, t.stack_index());
24522 stack::set_field<false, true>(L_,
24523 meta_function::new_index,
24524 make_closure(uts::template index_call<true>,
nullptr, light_storage, light_base_storage,
nullptr, toplevel_magic),
24526 storage.is_using_new_index =
true;
24529 ++for_each_backing_metatable_calls;
24530 fast_index_table_.reset(L_, t.stack_index());
24534 storage.for_each_table(L_, for_each_backing_metatable);
24537 if constexpr (std::is_default_constructible_v<T> && has_flag(enrollment_flags, automagic_flags::default_constructor)) {
24538 if (enrollments_.default_constructor) {
24539 storage.set(L_, meta_function::construct,
constructors<T()>());
24544 storage.named_metatable.push(L_);
24554 template <
typename Table,
typename Key>
24557 using key_type = detail::proxy_key_t<Key>;
24559 template <
typename T, std::size_t... I>
24560 decltype(
auto) tuple_get(std::index_sequence<I...>)
const& {
24561 return tbl.template traverse_get<T>(std::get<I>(key)...);
24564 template <
typename T, std::size_t... I>
24565 decltype(
auto) tuple_get(std::index_sequence<I...>) && {
24566 return tbl.template traverse_get<T>(std::get<I>(std::move(key))...);
24569 template <std::size_t... I,
typename T>
24570 void tuple_set(std::index_sequence<I...>, T&& value) & {
24571 if constexpr (
sizeof...(I) > 1) {
24572 tbl.traverse_set(std::get<I>(key)..., std::forward<T>(value));
24575 tbl.set(std::get<I>(key)..., std::forward<T>(value));
24579 template <std::size_t... I,
typename T>
24580 void tuple_set(std::index_sequence<I...>, T&& value) && {
24581 if constexpr (
sizeof...(I) > 1) {
24582 tbl.traverse_set(std::get<I>(std::move(key))..., std::forward<T>(value));
24585 tbl.set(std::get<I>(std::move(key))..., std::forward<T>(value));
24593 template <
typename T>
24597 template <
typename T>
24599 using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>;
24600 tuple_set(idx_seq(), std::forward<T>(item));
24604 template <
typename T>
24606 using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>;
24607 std::move(*this).tuple_set(idx_seq(), std::forward<T>(item));
24608 return std::move(*
this);
24611 template <
typename T>
24613 return set(std::forward<T>(other));
24616 template <
typename T>
24618 return std::move(*this).set(std::forward<T>(other));
24621 template <
typename T>
24623 return set(std::move(other));
24626 template <
typename T>
24628 return std::move(*this).set(std::move(other));
24631 template <
typename T>
24632 decltype(
auto)
get()
const& {
24633 using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>;
24634 return tuple_get<T>(idx_seq());
24637 template <
typename T>
24638 decltype(
auto)
get() && {
24639 using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>;
24640 return std::move(*this).template tuple_get<T>(idx_seq());
24643 template <
typename K>
24644 decltype(
auto) operator[](K&& k)
const& {
24645 auto keys = meta::tuplefy(key, std::forward<K>(k));
24649 template <
typename K>
24650 decltype(
auto) operator[](K&& k) & {
24651 auto keys = meta::tuplefy(key, std::forward<K>(k));
24655 template <
typename K>
24656 decltype(
auto) operator[](K&& k) && {
24657 auto keys = meta::tuplefy(std::move(key), std::forward<K>(k));
24661 template <
typename... Ret,
typename... Args>
24662 decltype(
auto) call(Args&&... args) {
24663 #if !defined(__clang__) && defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 191200000 24665 return get<function>().call<Ret...>(std::forward<Args>(args)...);
24667 return get<function>().
template call<Ret...>(std::forward<Args>(args)...);
24671 template <
typename... Args>
24672 decltype(
auto) operator()(Args&&... args) {
24673 return call<>(std::forward<Args>(args)...);
24676 bool valid()
const {
24677 auto pp = stack::push_pop(tbl);
24678 auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>,
global_table>::value>(lua_state(), key, lua_gettop(lua_state()));
24679 lua_pop(lua_state(), p.levels);
24683 int push()
const noexcept {
24684 return push(this->lua_state());
24687 int push(
lua_State* L)
const noexcept {
24688 return get<reference>().push(L);
24691 type get_type()
const {
24692 type t = type::none;
24693 auto pp = stack::push_pop(tbl);
24694 auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>,
global_table>::value>(lua_state(), key, lua_gettop(lua_state()));
24696 t = type_of(lua_state(), -1);
24698 lua_pop(lua_state(), p.levels);
24703 return tbl.lua_state();
24718 template <
typename Table,
typename Key>
24721 using key_type = detail::proxy_key_t<Key>;
24723 template <
typename T, std::size_t... I>
24724 decltype(
auto) tuple_get(std::index_sequence<I...>)
const& {
24725 return tbl.template traverse_get<T>(std::get<I>(key)...);
24728 template <
typename T, std::size_t... I>
24729 decltype(
auto) tuple_get(std::index_sequence<I...>) && {
24730 return tbl.template traverse_get<T>(std::get<I>(std::move(key))...);
24733 template <std::size_t... I,
typename T>
24734 void tuple_set(std::index_sequence<I...>, T&& value) & {
24735 tbl.traverse_set(std::get<I>(key)..., std::forward<T>(value));
24738 template <std::size_t... I,
typename T>
24739 void tuple_set(std::index_sequence<I...>, T&& value) && {
24740 tbl.traverse_set(std::get<I>(std::move(key))..., std::forward<T>(value));
24743 auto setup_table(std::true_type) {
24744 auto p = stack::probe_get_field<std::is_same_v<meta::unqualified_t<Table>,
global_table>>(lua_state(), key, tbl.stack_index());
24745 lua_pop(lua_state(), p.levels);
24749 bool is_valid(std::false_type) {
24750 auto pp = stack::push_pop(tbl);
24751 auto p = stack::probe_get_field<std::is_same_v<meta::unqualified_t<Table>,
global_table>>(lua_state(), key, lua_gettop(lua_state()));
24752 lua_pop(lua_state(), p.levels);
24760 template <
typename T>
24764 template <
typename T>
24766 tuple_set(std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>(), std::forward<T>(item));
24770 template <
typename T>
24772 std::move(*this).tuple_set(std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>(), std::forward<T>(item));
24773 return std::move(*
this);
24776 template <
typename... Args>
24778 tbl.set_function(key, std::forward<Args>(args)...);
24782 template <
typename... Args>
24784 tbl.set_function(std::move(key), std::forward<Args>(args)...);
24785 return std::move(*
this);
24788 template <
typename T>
24790 using Tu = meta::unwrap_unqualified_t<T>;
24791 if constexpr (!is_lua_reference_or_proxy_v<Tu> && meta::is_invocable_v<Tu>) {
24792 return set_function(std::forward<T>(other));
24795 return set(std::forward<T>(other));
24799 template <
typename T>
24801 using Tu = meta::unwrap_unqualified_t<T>;
24802 if constexpr (!is_lua_reference_or_proxy_v<Tu> && meta::is_invocable_v<Tu> && !detail::is_msvc_callable_rigged_v<T>) {
24803 return std::move(*this).set_function(std::forward<T>(other));
24806 return std::move(*this).set(std::forward<T>(other));
24810 template <
typename T>
24811 table_proxy& operator=(std::initializer_list<T> other) & {
24812 return set(std::move(other));
24815 template <
typename T>
24816 table_proxy&& operator=(std::initializer_list<T> other) && {
24817 return std::move(*this).set(std::move(other));
24820 template <
typename T>
24822 typedef decltype(get<T>()) U;
24827 template <
typename T>
24828 decltype(
auto)
get()
const& {
24829 using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>;
24830 return tuple_get<T>(idx_seq());
24833 template <
typename T>
24834 decltype(
auto)
get() && {
24835 using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>;
24836 return std::move(*this).template tuple_get<T>(idx_seq());
24839 template <
typename T>
24840 decltype(
auto) get_or(T&& otherwise)
const {
24841 typedef decltype(get<T>()) U;
24844 return static_cast<U
>(option.
value());
24846 return static_cast<U
>(std::forward<T>(otherwise));
24849 template <
typename T,
typename D>
24850 decltype(
auto) get_or(D&& otherwise)
const {
24853 return static_cast<T
>(option.
value());
24855 return static_cast<T
>(std::forward<D>(otherwise));
24858 template <
typename T>
24859 decltype(
auto) get_or_create() {
24863 template <
typename T,
typename Otherwise>
24864 decltype(
auto) get_or_create(Otherwise&& other) {
24865 if (!this->valid()) {
24866 this->
set(std::forward<Otherwise>(other));
24871 template <
typename K>
24872 decltype(
auto) operator[](K&& k)
const& {
24873 auto keys = meta::tuplefy(key, std::forward<K>(k));
24877 template <
typename K>
24878 decltype(
auto) operator[](K&& k) & {
24879 auto keys = meta::tuplefy(key, std::forward<K>(k));
24883 template <
typename K>
24884 decltype(
auto) operator[](K&& k) && {
24885 auto keys = meta::tuplefy(std::move(key), std::forward<K>(k));
24889 template <
typename... Ret,
typename... Args>
24890 decltype(
auto) call(Args&&... args) {
24893 int idx = lua_gettop(L);
24895 return func.call<Ret...>(std::forward<Args>(args)...);
24898 template <
typename... Args>
24899 decltype(
auto) operator()(Args&&... args) {
24900 return call<>(std::forward<Args>(args)...);
24903 bool valid()
const {
24904 auto pp = stack::push_pop(tbl);
24905 auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>,
global_table>::value>(lua_state(), key, lua_gettop(lua_state()));
24906 lua_pop(lua_state(), p.levels);
24910 int push()
const noexcept {
24911 return push(this->lua_state());
24914 int push(
lua_State* L)
const noexcept {
24915 if constexpr (std::is_same_v<meta::unqualified_t<Table>,
global_table> || is_stack_table_v<meta::unqualified_t<Table>>) {
24916 auto pp = stack::push_pop<true>(tbl);
24917 int tableindex = pp.index_of(tbl);
24918 int top_index = lua_gettop(L);
24919 stack::get_field<true>(lua_state(), key, tableindex);
24920 lua_replace(L, top_index + 1);
24921 lua_settop(L, top_index + 1);
24924 auto pp = stack::push_pop<false>(tbl);
24925 int tableindex = pp.index_of(tbl);
24926 int aftertableindex = lua_gettop(L);
24927 stack::get_field<false>(lua_state(), key, tableindex);
24928 lua_replace(L, tableindex);
24929 lua_settop(L, aftertableindex + 1);
24934 type get_type()
const {
24935 type t = type::none;
24936 auto pp = stack::push_pop(tbl);
24937 auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>,
global_table>::value>(lua_state(), key, lua_gettop(lua_state()));
24939 t = type_of(lua_state(), -1);
24941 lua_pop(lua_state(), p.levels);
24946 return tbl.lua_state();
24950 if (!this->valid()) {
24957 template <
typename Table,
typename Key,
typename T>
24959 using G = decltype(stack::get<T>(
nullptr, 0));
24960 return right.template get<optional<G>>() == left;
24963 template <
typename Table,
typename Key,
typename T>
24965 using G = decltype(stack::get<T>(
nullptr, 0));
24966 return right.template get<optional<G>>() == left;
24969 template <
typename Table,
typename Key,
typename T>
24971 using G = decltype(stack::get<T>(
nullptr, 0));
24972 return right.template get<optional<G>>() != left;
24975 template <
typename Table,
typename Key,
typename T>
24977 using G = decltype(stack::get<T>(
nullptr, 0));
24978 return right.template get<optional<G>>() != left;
24981 template <
typename Table,
typename Key>
24983 return !right.valid();
24986 template <
typename Table,
typename Key>
24988 return !right.valid();
24991 template <
typename Table,
typename Key>
24993 return right.valid();
24996 template <
typename Table,
typename Key>
24998 return right.valid();
25002 template <
typename Super>
25005 this->operator=(std::move(v));
25010 template <
typename Super>
25013 this->operator=(std::move(v));
25018 template <
typename Table,
typename Key>
25031 #include <iterator> 25035 template <
typename reference_type>
25040 typedef std::pair<object, object> value_type;
25041 typedef std::input_iterator_tag iterator_category;
25042 typedef std::ptrdiff_t difference_type;
25043 typedef value_type* pointer;
25044 typedef value_type& reference;
25045 typedef const value_type& const_reference;
25048 std::pair<object, object> kvp;
25049 reference_type ref;
25052 std::ptrdiff_t idx = 0;
25060 tableidx = lua_gettop(ref.lua_state());
25061 stack::push(ref.lua_state(), lua_nil);
25062 this->operator++();
25073 if (lua_next(ref.lua_state(), tableidx) == 0) {
25079 kvp.first =
object(ref.lua_state(), -2);
25080 kvp.second =
object(ref.lua_state(), -1);
25081 lua_pop(ref.lua_state(), 1);
25083 keyidx = lua_gettop(ref.lua_state());
25088 auto saved = *
this;
25089 this->operator++();
25093 reference operator*()
const noexcept {
25094 return const_cast<reference
>(kvp);
25098 return idx == right.idx;
25102 return idx != right.idx;
25106 if (keyidx != -1) {
25107 stack::remove(ref.lua_state(), keyidx, 1);
25109 if (ref.lua_state() !=
nullptr && ref.valid()) {
25110 stack::remove(ref.lua_state(), tableidx, 1);
25123 #include <optional> 25125 namespace sol {
namespace stack {
namespace stack_detail {
25127 inline bool maybe_push_lua_next_function(
lua_State* L_) {
25128 stack::get_field<true, false>(L_,
"next");
25129 bool is_next = stack::check<protected_function>(L_);
25133 stack::get_field<true, false>(L_,
"table");
25135 if (!stack::loose_table_check(L_, -1, &no_panic, tracking)) {
25138 lua_getfield(L_, -1,
"next");
25139 bool is_table_next_func = stack::check<protected_function>(L_, -1);
25140 if (is_table_next_func) {
25147 inline std::optional<protected_function> find_lua_next_function(
lua_State* L_) {
25148 if (maybe_push_lua_next_function(L_)) {
25149 return stack::pop<protected_function>(L_);
25151 return std::nullopt;
25154 inline int c_lua_next(
lua_State* L_) noexcept {
25157 int result = lua_next(table_stack_ref.lua_state(), table_stack_ref.stack_index());
25159 stack::push(L_, lua_nil);
25165 inline int readonly_pairs(
lua_State* L_) noexcept {
25167 if (!maybe_push_lua_next_function(L_)) {
25170 pushed += stack::push(L_, &c_lua_next);
25175 int metatable_exists = lua_getmetatable(L_, 1);
25176 sol_c_assert(metatable_exists == 1);
25177 const auto& index_key = to_string(sol::meta_function::index);
25178 lua_getfield(L_, lua_gettop(L_), index_key.c_str());
25179 lua_remove(L_, -2);
25181 pushed += stack::push(L_, lua_nil);
25195 inline static constexpr
int empty_key_index = -1;
25200 using value_type = std::pair<object, object>;
25201 using iterator_category = std::input_iterator_tag;
25202 using difference_type = std::ptrdiff_t;
25203 using pointer = value_type*;
25204 using const_pointer = value_type
const*;
25205 using reference = value_type&;
25206 using const_reference =
const value_type&;
25210 , m_next_function_ref(lua_nil)
25211 , m_table_ref(lua_nil)
25212 , m_cached_key_value_pair({ lua_nil, lua_nil })
25213 , m_key_index(empty_key_index)
25214 , m_iteration_index(0) {
25222 , m_next_function_ref(std::move(right.m_next_function_ref))
25223 , m_table_ref(std::move(right.m_table_ref))
25224 , m_cached_key_value_pair(std::move(right.m_cached_key_value_pair))
25225 , m_key_index(right.m_key_index)
25226 , m_iteration_index(right.m_iteration_index) {
25227 right.m_key_index = empty_key_index;
25232 m_next_function_ref = std::move(right.m_next_function_ref);
25233 m_table_ref = std::move(right.m_table_ref);
25234 m_cached_key_value_pair = std::move(right.m_cached_key_value_pair);
25235 m_key_index = right.m_key_index;
25236 m_iteration_index = right.m_iteration_index;
25237 right.m_key_index = empty_key_index;
25241 template <
typename Source>
25242 pairs_iterator(
const Source& source_) noexcept : m_L(source_.lua_state()), m_key_index(empty_key_index), m_iteration_index(0) {
25243 if (m_L ==
nullptr || !source_.valid()) {
25244 m_key_index = empty_key_index;
25247 int source_index = -source_.push(m_L);
25248 int abs_source_index = lua_absindex(m_L, source_index);
25249 int metatable_exists = lua_getmetatable(m_L, abs_source_index);
25250 lua_remove(m_L, abs_source_index);
25251 if (metatable_exists == 1) {
25254 stack::get_field<is_global_table_v<Source>,
true>(m_L, meta_function::pairs, metatable.stack_index());
25256 if (maybe_pairs_function.has_value()) {
25259 if (next_fn_and_table_and_first_key.valid()) {
25261 m_table_ref = next_fn_and_table_and_first_key.get<
sol::reference>(1);
25262 m_key_index = next_fn_and_table_and_first_key.stack_index() - 1;
25264 lua_remove(m_L, m_key_index);
25265 lua_remove(m_L, m_key_index);
25266 next_fn_and_table_and_first_key.abandon();
25267 lua_remove(m_L, abs_source_index);
25268 this->operator++();
25269 m_iteration_index = 0;
25276 auto maybe_next = stack::stack_detail::find_lua_next_function(m_L);
25277 if (maybe_next.has_value()) {
25278 m_next_function_ref = std::move(*maybe_next);
25279 m_table_ref = source_;
25281 stack::push(m_L, lua_nil);
25282 m_key_index = lua_gettop(m_L);
25283 this->operator++();
25284 m_iteration_index = 0;
25291 stack::push(m_L, &stack::stack_detail::c_lua_next);
25292 m_next_function_ref = stack::pop<protected_function>(m_L);
25293 m_table_ref = source_;
25294 stack::push(m_L, lua_nil);
25295 m_key_index = lua_gettop(m_L);
25296 this->operator++();
25297 m_iteration_index = 0;
25301 if (m_key_index == empty_key_index) {
25306 if (!next_results.valid()) {
25309 m_key_index = empty_key_index;
25312 int next_results_count = next_results.return_count();
25313 if (next_results_count < 2) {
25315 next_results.abandon();
25316 lua_settop(m_L, m_key_index - 1);
25317 m_key_index = empty_key_index;
25318 ++m_iteration_index;
25322 lua_remove(m_L, m_key_index);
25323 m_key_index = next_results.stack_index() - 1;
25324 m_cached_key_value_pair.first = stack::get<object>(m_L, m_key_index);
25325 m_cached_key_value_pair.second = stack::get<object>(m_L, m_key_index + 1);
25326 lua_settop(m_L, m_key_index);
25327 next_results.abandon();
25330 ++m_iteration_index;
25334 std::ptrdiff_t index()
const {
25335 return static_cast<std::ptrdiff_t
>(m_iteration_index);
25338 const_reference operator*()
const noexcept {
25339 return m_cached_key_value_pair;
25342 reference operator*() noexcept {
25343 return m_cached_key_value_pair;
25347 return left.m_table_ref == right.m_table_ref && left.m_iteration_index == right.m_iteration_index;
25351 return left.m_table_ref != right.m_table_ref || left.m_iteration_index != right.m_iteration_index;
25355 return left.m_key_index == empty_key_index;
25359 return left.m_key_index != empty_key_index;
25363 return left.m_key_index == empty_key_index;
25367 return left.m_key_index != empty_key_index;
25371 if (m_key_index != empty_key_index) {
25377 void m_clear() noexcept {
25378 lua_remove(m_L, m_key_index);
25384 std::pair<object, object> m_cached_key_value_pair;
25386 int m_iteration_index;
25389 template <
typename Source>
25392 using source_t = std::add_lvalue_reference_t<Source>;
25432 template <std::
size_t n>
25438 lua_pop(L, static_cast<int>(n));
25449 lua_pop(L, static_cast<int>(pop_count));
25453 inline int fail_on_newindex(
lua_State* L_) {
25454 return luaL_error(L_,
"sol: cannot modify the elements of an enumeration table");
25459 template <
bool top_level,
typename ref_t>
25464 friend class state;
25466 template <
typename,
typename>
25468 template <
typename>
25471 template <
typename T>
25472 using is_get_direct_tableless = meta::boolean<stack::stack_detail::is_get_direct_tableless_v<T, top_level, false>>;
25474 template <
typename T>
25475 using is_raw_get_direct_tableless = std::false_type;
25477 template <
typename T>
25478 using is_set_direct_tableless = meta::boolean<stack::stack_detail::is_set_direct_tableless_v<T, top_level, false>>;
25480 template <
typename T>
25481 using is_raw_set_direct_tableless = std::false_type;
25483 template <
bool raw,
typename... Ret,
typename... Keys>
25484 decltype(
auto) tuple_get(
int table_index, Keys&&... keys)
const {
25485 if constexpr (
sizeof...(Ret) < 2) {
25486 return traverse_get_single_maybe_tuple<raw, Ret...>(table_index, std::forward<Keys>(keys)...);
25489 using multi_ret = decltype(stack::pop<std::tuple<Ret...>>(
nullptr));
25490 return multi_ret(traverse_get_single_maybe_tuple<raw, Ret>(table_index, std::forward<Keys>(keys))...);
25494 template <
bool raw,
typename Ret,
size_t... I,
typename Key>
25495 decltype(
auto) traverse_get_single_tuple(
int table_index, std::index_sequence<I...>, Key&& key)
const {
25496 return traverse_get_single<raw, Ret>(table_index, std::get<I>(std::forward<Key>(key))...);
25499 template <
bool raw,
typename Ret,
typename Key>
25500 decltype(
auto) traverse_get_single_maybe_tuple(
int table_index, Key&& key)
const {
25501 if constexpr (meta::is_tuple_v<meta::unqualified_t<Key>>) {
25502 return traverse_get_single_tuple<raw, Ret>(
25503 table_index, std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<Key>>>(), std::forward<Key>(key));
25506 return traverse_get_single<raw, Ret>(table_index, std::forward<Key>(key));
25510 template <
bool raw,
typename Ret,
typename... Keys>
25511 decltype(
auto) traverse_get_single(
int table_index, Keys&&... keys)
const {
25512 constexpr
static bool global = (meta::count_for_to_pack_v < 1, is_get_direct_tableless, meta::unqualified_t<Keys>... >> 0);
25513 if constexpr (meta::is_optional_v<meta::unqualified_t<Ret>>) {
25516 return traverse_get_deep_optional<global, raw, detail::insert_mode::none, Ret>(popcount, table_index, std::forward<Keys>(keys)...);
25519 detail::clean<
sizeof...(Keys) - meta::count_for_pack_v<detail::is_insert_mode, meta::unqualified_t<Keys>...>> c(base_t::lua_state());
25520 return traverse_get_deep<global, raw, detail::insert_mode::none, Ret>(table_index, std::forward<Keys>(keys)...);
25524 template <
bool raw,
typename Pairs, std::size_t... I>
25525 void tuple_set(std::index_sequence<I...>, Pairs&& pairs) {
25526 constexpr
static bool global = (meta::count_even_for_pack_v < is_set_direct_tableless,
25527 meta::unqualified_t<decltype(std::get<I * 2>(std::forward<Pairs>(pairs)))>... >> 0);
25528 auto pp = stack::push_pop<global>(*this);
25529 int table_index = pp.index_of(*
this);
25533 void(detail::swallow { (stack::set_field<(top_level), raw>(
25534 L, std::get<I * 2>(std::forward<Pairs>(pairs)), std::get<I * 2 + 1>(std::forward<Pairs>(pairs)), table_index),
25538 template <
bool global,
bool raw, detail::insert_mode mode,
typename T,
typename Key,
typename... Keys>
25539 decltype(
auto) traverse_get_deep(
int table_index, Key&& key, Keys&&... keys)
const {
25540 if constexpr (std::is_same_v<meta::unqualified_t<Key>,
create_if_nil_t>) {
25542 return traverse_get_deep<false, raw, static_cast<detail::insert_mode>(mode | detail::insert_mode::create_if_nil), T>(
25543 table_index, std::forward<Keys>(keys)...);
25547 stack::get_field<global, raw>(L, std::forward<Key>(key), table_index);
25548 if constexpr (
sizeof...(Keys) > 0) {
25549 if constexpr ((mode & detail::insert_mode::create_if_nil) == detail::insert_mode::create_if_nil) {
25550 type t = type_of(L, -1);
25551 if (t == type::lua_nil || t == type::none) {
25556 return traverse_get_deep<false, raw, mode, T>(lua_gettop(L), std::forward<Keys>(keys)...);
25559 if constexpr ((mode & detail::insert_mode::create_if_nil) == detail::insert_mode::create_if_nil) {
25560 type t = type_of(L, -1);
25561 if ((t == type::lua_nil || t == type::none) && (is_table_like_v<T>)) {
25566 return stack::get<T>(L);
25571 template <
bool global,
bool raw, detail::insert_mode mode,
typename T,
typename Key,
typename... Keys>
25572 decltype(
auto) traverse_get_deep_optional(
int& popcount,
int table_index, Key&& key, Keys&&... keys)
const {
25573 if constexpr (std::is_same_v<meta::unqualified_t<Key>,
create_if_nil_t>) {
25574 constexpr detail::insert_mode new_mode =
static_cast<detail::insert_mode
>(mode | detail::insert_mode::create_if_nil);
25576 return traverse_get_deep_optional<global, raw, new_mode, T>(popcount, table_index, std::forward<Keys>(keys)...);
25578 else if constexpr (std::is_same_v<meta::unqualified_t<Key>,
update_if_empty_t>) {
25579 constexpr detail::insert_mode new_mode =
static_cast<detail::insert_mode
>(mode | detail::insert_mode::update_if_empty);
25581 return traverse_get_deep_optional<global, raw, new_mode, T>(popcount, table_index, std::forward<Keys>(keys)...);
25583 else if constexpr (std::is_same_v<meta::unqualified_t<Key>,
override_value_t>) {
25584 constexpr detail::insert_mode new_mode =
static_cast<detail::insert_mode
>(mode | detail::insert_mode::override_value);
25586 return traverse_get_deep_optional<global, raw, new_mode, T>(popcount, table_index, std::forward<Keys>(keys)...);
25589 if constexpr (
sizeof...(Keys) > 0) {
25591 auto p = stack::probe_get_field<global, raw>(L, std::forward<Key>(key), table_index);
25592 popcount += p.levels;
25594 if constexpr ((mode & detail::insert_mode::create_if_nil) == detail::insert_mode::create_if_nil) {
25596 constexpr
bool is_seq = meta::count_for_to_pack_v < 1, std::is_integral, Keys... >> 0;
25597 stack::push(L,
new_table(static_cast<int>(is_seq), static_cast<int>(!is_seq)));
25598 stack::set_field<global, raw>(L, std::forward<Key>(key),
stack_reference(L, -1), table_index);
25604 return traverse_get_deep_optional<false, raw, mode, T>(popcount, lua_gettop(L), std::forward<Keys>(keys)...);
25607 using R = decltype(stack::get<T>(
nullptr));
25608 using value_type =
typename meta::unqualified_t<R>::value_type;
25610 auto p = stack::probe_get_field<global, raw, value_type>(L, key, table_index);
25611 popcount += p.levels;
25613 if constexpr ((mode & detail::insert_mode::create_if_nil) == detail::insert_mode::create_if_nil) {
25616 stack::set_field<global, raw>(L, std::forward<Key>(key),
stack_reference(L, -1), table_index);
25617 if (stack::check<value_type>(L, lua_gettop(L), &no_panic)) {
25618 return stack::get<T>(L);
25623 return stack::get<T>(L);
25628 template <
bool global,
bool raw, detail::insert_mode mode,
typename Key,
typename... Keys>
25629 void traverse_set_deep(
int table_index, Key&& key, Keys&&... keys)
const {
25630 using KeyU = meta::unqualified_t<Key>;
25631 if constexpr (std::is_same_v<KeyU, update_if_empty_t>) {
25633 traverse_set_deep<global, raw, static_cast<detail::insert_mode>(mode | detail::insert_mode::update_if_empty)>(
25634 table_index, std::forward<Keys>(keys)...);
25636 else if constexpr (std::is_same_v<KeyU, create_if_nil_t>) {
25638 traverse_set_deep<global, raw, static_cast<detail::insert_mode>(mode | detail::insert_mode::create_if_nil)>(
25639 table_index, std::forward<Keys>(keys)...);
25641 else if constexpr (std::is_same_v<KeyU, override_value_t>) {
25643 traverse_set_deep<global, raw, static_cast<detail::insert_mode>(mode | detail::insert_mode::override_value)>(
25644 table_index, std::forward<Keys>(keys)...);
25648 if constexpr (
sizeof...(Keys) == 1) {
25649 if constexpr ((mode & detail::insert_mode::update_if_empty) == detail::insert_mode::update_if_empty) {
25650 auto p = stack::probe_get_field<global, raw>(L, key, table_index);
25651 lua_pop(L, p.levels);
25653 stack::set_field<global, raw>(L, std::forward<Key>(key), std::forward<Keys>(keys)..., table_index);
25657 stack::set_field<global, raw>(L, std::forward<Key>(key), std::forward<Keys>(keys)..., table_index);
25661 if constexpr (mode != detail::insert_mode::none) {
25662 stack::get_field<global, raw>(L, key, table_index);
25663 type vt = type_of(L, -1);
25664 if constexpr ((mode & detail::insert_mode::update_if_empty) == detail::insert_mode::update_if_empty
25665 || (mode & detail::insert_mode::create_if_nil) == detail::insert_mode::create_if_nil) {
25666 if (vt == type::lua_nil || vt == type::none) {
25667 constexpr
bool is_seq = meta::count_for_to_pack_v < 1, std::is_integral, Keys... >> 0;
25669 stack::push(L,
new_table(static_cast<int>(is_seq), static_cast<int>(!is_seq)));
25670 stack::set_field<global, raw>(L, std::forward<Key>(key),
stack_reference(L, -1), table_index);
25674 if (vt != type::table) {
25675 constexpr
bool is_seq = meta::count_for_to_pack_v < 1, std::is_integral, Keys... >> 0;
25677 stack::push(L,
new_table(static_cast<int>(is_seq), static_cast<int>(!is_seq)));
25678 stack::set_field<global, raw>(L, std::forward<Key>(key),
stack_reference(L, -1), table_index);
25683 stack::get_field<global, raw>(L, std::forward<Key>(key), table_index);
25685 traverse_set_deep<false, raw, mode>(lua_gettop(L), std::forward<Keys>(keys)...);
25697 template <
typename T,
25698 meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>,
basic_table_core>>, meta::neg<std::is_same<ref_t, stack_reference>>,
25702 template <
typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
25708 using const_iterator = iterator;
25710 using base_t::lua_state;
25712 basic_table_core() noexcept =
default;
25713 basic_table_core(
const basic_table_core&) =
default;
25714 basic_table_core(basic_table_core&&) =
default;
25715 basic_table_core& operator=(
const basic_table_core&) =
default;
25716 basic_table_core& operator=(basic_table_core&&) =
default;
25718 basic_table_core(
const stack_reference& r) : basic_table_core(r.lua_state(), r.stack_index()) {
25721 basic_table_core(
stack_reference&& r) : basic_table_core(r.lua_state(), r.stack_index()) {
25724 template <
typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
25725 basic_table_core(
lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) {
25726 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 25727 auto pp = stack::push_pop(*
this);
25728 int table_index = pp.index_of(*
this);
25730 stack::check<basic_table_core>(lua_state(), table_index, handler);
25734 basic_table_core(
lua_State* L,
const new_table& nt) : base_t(L, -stack::push(L, nt)) {
25740 basic_table_core(
lua_State* L,
int index = -1) : basic_table_core(detail::no_safety, L, index) {
25741 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 25743 stack::check<basic_table_core>(L, index, handler);
25747 basic_table_core(
lua_State* L,
ref_index index) : basic_table_core(detail::no_safety, L, index) {
25748 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 25749 auto pp = stack::push_pop(*
this);
25750 int table_index = pp.index_of(*
this);
25752 stack::check<basic_table_core>(lua_state(), table_index, handler);
25756 template <
typename T,
25757 meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<ref_t, stack_reference>>,
25758 meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
25759 basic_table_core(T&& r) noexcept : basic_table_core(detail::no_safety, std::forward<T>(r)) {
25760 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 25761 if (!
is_table<meta::unqualified_t<T>>::value) {
25762 auto pp = stack::push_pop(*
this);
25763 int table_index = pp.index_of(*
this);
25765 stack::check<basic_table_core>(lua_state(), table_index, handler);
25770 basic_table_core(
lua_nil_t r) noexcept : basic_table_core(detail::no_safety, r) {
25776 iterator begin()
const {
25777 if (this->get_type() == type::table) {
25778 return iterator(*
this);
25783 iterator end()
const {
25787 const_iterator cbegin()
const {
25791 const_iterator cend()
const {
25804 auto pp = stack::push_pop<false>(*this);
25805 int table_index = pp.index_of(*
this);
25806 stack::clear(lua_state(), table_index);
25809 template <
typename... Ret,
typename... Keys>
25810 decltype(
auto)
get(Keys&&... keys)
const {
25811 static_assert(
sizeof...(Keys) ==
sizeof...(Ret),
"number of keys and number of return types do not match");
25813 auto pp = stack::push_pop<global>(*this);
25814 int table_index = pp.index_of(*
this);
25815 return tuple_get<
false, Ret...>(table_index, std::forward<Keys>(keys)...);
25818 template <
typename T,
typename Key>
25819 decltype(
auto) get_or(Key&& key, T&& otherwise)
const {
25820 typedef decltype(get<T>(
"")) U;
25821 optional<U> option = get<optional<U>>(std::forward<Key>(key));
25823 return static_cast<U
>(option.
value());
25825 return static_cast<U
>(std::forward<T>(otherwise));
25828 template <
typename T,
typename Key,
typename D>
25829 decltype(
auto) get_or(Key&& key, D&& otherwise)
const {
25830 optional<T> option = get<optional<T>>(std::forward<Key>(key));
25832 return static_cast<T
>(option.
value());
25834 return static_cast<T
>(std::forward<D>(otherwise));
25837 template <
typename T,
typename... Keys>
25838 decltype(
auto) traverse_get(Keys&&... keys)
const {
25839 static_assert(
sizeof...(Keys) > 0,
"must pass at least 1 key to get");
25840 constexpr
static bool global = (meta::count_for_to_pack_v < 1, is_get_direct_tableless, meta::unqualified_t<Keys>... >> 0);
25841 auto pp = stack::push_pop<global>(*this);
25842 int table_index = pp.index_of(*
this);
25843 return traverse_get_single<false, T>(table_index, std::forward<Keys>(keys)...);
25846 template <
typename... Keys>
25847 basic_table_core& traverse_set(Keys&&... keys) {
25848 static_assert(
sizeof...(Keys) > 1,
"must pass at least 1 key and 1 value to set");
25849 constexpr
static bool global
25850 = (meta::count_when_for_to_pack_v < detail::is_not_insert_mode, 1, is_set_direct_tableless, meta::unqualified_t<Keys>... >> 0);
25851 auto pp = stack::push_pop<global>(*this);
25852 int table_index = pp.index_of(*
this);
25854 auto pn = stack::pop_n(L, static_cast<int>(
sizeof...(Keys) - 2 - meta::count_for_pack_v<detail::is_insert_mode, meta::unqualified_t<Keys>...>));
25855 traverse_set_deep<top_level, false, detail::insert_mode::none>(table_index, std::forward<Keys>(keys)...);
25859 template <
typename... Args>
25860 basic_table_core&
set(Args&&... args) {
25861 if constexpr (
sizeof...(Args) == 2) {
25862 traverse_set(std::forward<Args>(args)...);
25865 tuple_set<false>(std::make_index_sequence<
sizeof...(Args) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...));
25870 template <
typename... Ret,
typename... Keys>
25871 decltype(
auto) raw_get(Keys&&... keys)
const {
25872 static_assert(
sizeof...(Keys) ==
sizeof...(Ret),
"number of keys and number of return types do not match");
25873 constexpr
static bool global = (meta::count_for_to_pack_v < 1, is_raw_get_direct_tableless, meta::unqualified_t<Keys>... >> 0);
25874 auto pp = stack::push_pop<global>(*this);
25875 int table_index = pp.index_of(*
this);
25876 return tuple_get<
true, Ret...>(table_index, std::forward<Keys>(keys)...);
25879 template <
typename T,
typename Key>
25880 decltype(
auto) raw_get_or(Key&& key, T&& otherwise)
const {
25881 typedef decltype(raw_get<T>(
"")) U;
25882 optional<U> option = raw_get<optional<U>>(std::forward<Key>(key));
25884 return static_cast<U
>(option.
value());
25886 return static_cast<U
>(std::forward<T>(otherwise));
25889 template <
typename T,
typename Key,
typename D>
25890 decltype(
auto) raw_get_or(Key&& key, D&& otherwise)
const {
25891 optional<T> option = raw_get<optional<T>>(std::forward<Key>(key));
25893 return static_cast<T
>(option.
value());
25895 return static_cast<T
>(std::forward<D>(otherwise));
25898 template <
typename T,
typename... Keys>
25899 decltype(
auto) traverse_raw_get(Keys&&... keys)
const {
25900 constexpr
static bool global = (meta::count_for_to_pack_v < 1, is_raw_get_direct_tableless, meta::unqualified_t<Keys>... >> 0);
25901 auto pp = stack::push_pop<global>(*this);
25902 int table_index = pp.index_of(*
this);
25903 return traverse_get_single<true, T>(table_index, std::forward<Keys>(keys)...);
25906 template <
typename... Keys>
25907 basic_table_core& traverse_raw_set(Keys&&... keys) {
25908 constexpr
static bool global = (meta::count_for_to_pack_v < 1, is_raw_set_direct_tableless, meta::unqualified_t<Keys>... >> 0);
25909 auto pp = stack::push_pop<global>(*this);
25911 auto pn = stack::pop_n(L, static_cast<int>(
sizeof...(Keys) - 2 - meta::count_for_pack_v<detail::is_insert_mode, meta::unqualified_t<Keys>...>));
25912 traverse_set_deep<top_level, true, false>(std::forward<Keys>(keys)...);
25916 template <
typename... Args>
25917 basic_table_core& raw_set(Args&&... args) {
25918 tuple_set<true>(std::make_index_sequence<
sizeof...(Args) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...));
25922 template <
typename Class,
typename Key>
25925 template <
typename Class,
typename Key, automagic_flags enrollment_flags>
25928 template <
typename Class,
typename Key>
25931 template <
typename Class,
typename Key,
typename Arg,
typename... Args,
25932 typename = std::enable_if_t<!std::is_base_of_v<automagic_enrollments, meta::unqualified_t<Arg>>>>
25935 template <
bool read_only =
true,
typename... Args>
25936 table new_enum(
const string_view& name, Args&&... args) {
25937 table target = create_with(std::forward<Args>(args)...);
25938 if constexpr (read_only) {
25941 = create_with(meta_function::new_index, detail::fail_on_newindex, meta_function::index, target, meta_function::pairs, stack::stack_detail::readonly_pairs);
25942 table shim = create_named(name, metatable_key, x);
25951 template <
typename T,
bool read_only = true>
25952 table new_enum(
const string_view& name, std::initializer_list<std::pair<string_view, T>> items) {
25953 table target = create(static_cast<int>(items.size()), static_cast<int>(0));
25954 for (
const auto& kvp : items) {
25955 target.set(kvp.first, kvp.second);
25957 if constexpr (read_only) {
25958 table x = create_with(meta_function::new_index, detail::fail_on_newindex, meta_function::index, target);
25959 table shim = create_named(name, metatable_key, x);
25968 template <
typename Key =
object,
typename Value =
object,
typename Fx>
25969 void for_each(Fx&& fx)
const {
25971 if constexpr (std::is_invocable_v<Fx, Key, Value>) {
25972 auto pp = stack::push_pop(*
this);
25973 int table_index = pp.index_of(*
this);
25974 stack::push(L, lua_nil);
25975 while (lua_next(L, table_index)) {
25977 Value value(L, -1);
25978 auto pn = stack::pop_n(L, 1);
25983 auto pp = stack::push_pop(*
this);
25984 int table_index = pp.index_of(*
this);
25985 stack::push(L, lua_nil);
25986 while (lua_next(L, table_index)) {
25988 Value value(L, -1);
25989 auto pn = stack::pop_n(L, 1);
25990 std::pair<Key&, Value&> keyvalue(key, value);
25996 size_t size()
const {
25997 auto pp = stack::push_pop(*
this);
25998 int table_index = pp.index_of(*
this);
26000 lua_len(L, table_index);
26001 return stack::pop<size_t>(L);
26004 bool empty()
const {
26005 return cbegin() == cend();
26008 template <
typename T>
26009 auto operator[](T&& key) & {
26013 template <
typename T>
26014 auto operator[](T&& key)
const& {
26018 template <
typename T>
26019 auto operator[](T&& key) && {
26023 template <
typename Sig,
typename Key,
typename... Args>
26024 basic_table_core& set_function(Key&& key, Args&&... args) {
26025 set_fx(
types<Sig>(), std::forward<Key>(key), std::forward<Args>(args)...);
26029 template <
typename Key,
typename... Args>
26030 basic_table_core& set_function(Key&& key, Args&&... args) {
26031 set_fx(
types<>(), std::forward<Key>(key), std::forward<Args>(args)...);
26035 template <
typename... Args>
26036 basic_table_core& add(Args&&... args) {
26037 auto pp = stack::push_pop(*
this);
26038 int table_index = pp.index_of(*
this);
26040 (void)detail::swallow { 0, (stack::stack_detail::raw_table_set(L, std::forward<Args>(args), table_index), 0)... };
26045 template <
typename R,
typename... Args,
typename Fx,
typename Key,
typename = std::invoke_result_t<Fx, Args...>>
26046 void set_fx(
types<R(Args...)>, Key&& key, Fx&& fx) {
26047 set_resolved_function<R(Args...)>(std::forward<Key>(key), std::forward<Fx>(fx));
26050 template <
typename Fx,
typename Key, meta::enable<meta::is_specialization_of<meta::unqualified_t<Fx>, overload_set>> = meta::enabler>
26051 void set_fx(
types<>, Key&& key, Fx&& fx) {
26052 set(std::forward<Key>(key), std::forward<Fx>(fx));
26055 template <
typename Fx,
typename Key,
typename... Args,
26056 meta::disable<meta::is_specialization_of<meta::unqualified_t<Fx>,
overload_set>> = meta::enabler>
26057 void set_fx(
types<>, Key&& key, Fx&& fx, Args&&... args) {
26058 set(std::forward<Key>(key), as_function_reference(std::forward<Fx>(fx), std::forward<Args>(args)...));
26061 template <
typename... Sig,
typename... Args,
typename Key>
26062 void set_resolved_function(Key&& key, Args&&... args) {
26063 set(std::forward<Key>(key), as_function_reference<
function_sig<Sig...>>(std::forward<Args>(args)...));
26067 static inline table create(
lua_State* L,
int narr = 0,
int nrec = 0) {
26068 lua_createtable(L, narr, nrec);
26074 template <
typename Key,
typename Value,
typename... Args>
26075 static inline table create(
lua_State* L,
int narr,
int nrec, Key&& key, Value&& value, Args&&... args) {
26076 lua_createtable(L, narr, nrec);
26078 result.set(std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
26083 template <
typename... Args>
26085 static_assert(
sizeof...(Args) % 2 == 0,
"You must have an even number of arguments for a key, value ... list.");
26086 constexpr
int narr =
static_cast<int>(meta::count_odd_for_pack_v<std::is_integral, Args...>);
26087 return create(L, narr, static_cast<int>((
sizeof...(Args) / 2) - narr), std::forward<Args>(args)...);
26090 table create(
int narr = 0,
int nrec = 0) {
26091 return create(base_t::lua_state(), narr, nrec);
26094 template <
typename Key,
typename Value,
typename... Args>
26095 table create(
int narr,
int nrec, Key&& key, Value&& value, Args&&... args) {
26096 return create(base_t::lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
26099 template <
typename Name>
26100 table create(Name&& name,
int narr = 0,
int nrec = 0) {
26101 table x = create(base_t::lua_state(), narr, nrec);
26102 this->
set(std::forward<Name>(name), x);
26106 template <
typename Name,
typename Key,
typename Value,
typename... Args>
26107 table create(Name&& name,
int narr,
int nrec, Key&& key, Value&& value, Args&&... args) {
26108 table x = create(base_t::lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
26109 this->
set(std::forward<Name>(name), x);
26113 template <
typename... Args>
26114 table create_with(Args&&... args) {
26115 return create_with(base_t::lua_state(), std::forward<Args>(args)...);
26118 template <
typename Name,
typename... Args>
26119 table create_named(Name&& name, Args&&... args) {
26120 static const int narr =
static_cast<int>(meta::count_even_for_pack_v<std::is_integral, Args...>);
26121 return create(std::forward<Name>(name), narr, (
sizeof...(Args) / 2) - narr, std::forward<Args>(args)...);
26130 template <
typename base_type>
26133 friend class state;
26143 template <
typename T,
26144 meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>,
basic_metatable>>, meta::neg<std::is_same<base_type, stack_reference>>,
26148 template <
typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
26152 template <
typename R,
typename... Args,
typename Fx,
typename Key,
typename = std::invoke_result_t<Fx, Args...>>
26153 void set_fx(
types<R(Args...)>, Key&& key, Fx&& fx) {
26154 set_resolved_function<R(Args...)>(std::forward<Key>(key), std::forward<Fx>(fx));
26157 template <
typename Fx,
typename Key, meta::enable<meta::is_specialization_of<meta::unqualified_t<Fx>, overload_set>> = meta::enabler>
26158 void set_fx(
types<>, Key&& key, Fx&& fx) {
26159 set(std::forward<Key>(key), std::forward<Fx>(fx));
26162 template <
typename Fx,
typename Key,
typename... Args,
26163 meta::disable<meta::is_specialization_of<meta::unqualified_t<Fx>,
overload_set>> = meta::enabler>
26164 void set_fx(
types<>, Key&& key, Fx&& fx, Args&&... args) {
26165 set(std::forward<Key>(key), as_function_reference(std::forward<Fx>(fx), std::forward<Args>(args)...));
26168 template <
typename... Sig,
typename... Args,
typename Key>
26169 void set_resolved_function(Key&& key, Args&&... args) {
26170 set(std::forward<Key>(key), as_function_reference<
function_sig<Sig...>>(std::forward<Args>(args)...));
26174 using base_t::lua_state;
26176 basic_metatable() noexcept =
default;
26177 basic_metatable(
const basic_metatable&) =
default;
26178 basic_metatable(basic_metatable&&) =
default;
26179 basic_metatable& operator=(
const basic_metatable&) =
default;
26180 basic_metatable& operator=(basic_metatable&&) =
default;
26181 basic_metatable(
const stack_reference& r) : basic_metatable(r.lua_state(), r.stack_index()) {
26183 basic_metatable(
stack_reference&& r) : basic_metatable(r.lua_state(), r.stack_index()) {
26185 template <
typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
26186 basic_metatable(
lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) {
26187 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 26188 auto pp = stack::push_pop(*
this);
26190 stack::check<basic_metatable>(lua_state(), -1, handler);
26193 basic_metatable(
lua_State* L,
int index = -1) : basic_metatable(detail::no_safety, L, index) {
26194 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 26196 stack::check<basic_metatable>(L, index, handler);
26199 basic_metatable(
lua_State* L,
ref_index index) : basic_metatable(detail::no_safety, L, index) {
26200 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 26201 auto pp = stack::push_pop(*
this);
26203 stack::check<basic_metatable>(lua_state(), -1, handler);
26206 template <
typename T,
26207 meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_metatable>>, meta::neg<std::is_same<base_type, stack_reference>>,
26208 meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
26209 basic_metatable(T&& r) noexcept : basic_metatable(detail::no_safety, std::forward<T>(r)) {
26210 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 26211 if (!
is_table<meta::unqualified_t<T>>::value) {
26212 auto pp = stack::push_pop(*
this);
26214 stack::check<basic_metatable>(base_t::lua_state(), -1, handler);
26218 basic_metatable(
lua_nil_t r) noexcept : basic_metatable(detail::no_safety, r) {
26221 template <
typename Key,
typename Value>
26224 template <
typename Sig,
typename Key,
typename... Args>
26225 basic_metatable& set_function(Key&& key, Args&&... args) {
26226 set_fx(
types<Sig>(), std::forward<Key>(key), std::forward<Args>(args)...);
26230 template <
typename Key,
typename... Args>
26231 basic_metatable& set_function(Key&& key, Args&&... args) {
26232 set_fx(
types<>(), std::forward<Key>(key), std::forward<Args>(args)...);
26236 void unregister() {
26241 auto pp = stack::push_pop(*
this);
26242 int top = lua_gettop(L);
26245 stack::get_field(L, meta_function::gc_names, mt.stack_index());
26246 if (type_of(L, -1) != type::table) {
26247 lua_settop(L, top);
26251 stack::get_field(L, meta_function::storage, mt.stack_index());
26252 if (type_of(L, -1) != type::lightuserdata) {
26253 lua_settop(L, top);
26256 ustorage_base& base_storage = *
static_cast<ustorage_base*
>(stack::get<void*>(L, -1));
26257 std::array<string_view, 6> registry_traits;
26258 for (std::size_t i = 0; i < registry_traits.size(); ++i) {
26259 u_detail::submetatable_type smt =
static_cast<u_detail::submetatable_type
>(i);
26260 stack::get_field<false, true>(L, smt, gc_names_table.stack_index());
26261 registry_traits[i] = stack::get<string_view>(L, -1);
26271 for (std::size_t i = 0; i < registry_traits.size(); ++i) {
26272 u_detail::submetatable_type smt =
static_cast<u_detail::submetatable_type
>(i);
26273 const string_view& gcmetakey = registry_traits[i];
26274 if (smt == u_detail::submetatable_type::named) {
26277 stack::set_field<true>(L, gcmetakey.data(), lua_nil);
26287 base_storage.clear();
26295 lua_settop(L, top);
26305 template <
typename T,
typename base_type>
26311 template <
typename>
26314 template <
bool,
typename>
26317 template <std::size_t... I,
typename... Args>
26318 void tuple_set(std::index_sequence<I...>, std::tuple<Args...>&& args) {
26320 (void)detail::swallow { 0, (this->
set(std::get<I * 2>(std::move(args)), std::get<I * 2 + 1>(std::move(args))), 0)... };
26323 template <
typename R,
typename... Args,
typename Fx,
typename Key,
typename = std::invoke_result_t<Fx, Args...>>
26324 void set_fx(
types<R(Args...)>, Key&& key, Fx&& fx) {
26325 set_resolved_function<R(Args...)>(std::forward<Key>(key), std::forward<Fx>(fx));
26328 template <
typename Fx,
typename Key, meta::enable<meta::is_specialization_of<meta::unqualified_t<Fx>, overload_set>> = meta::enabler>
26329 void set_fx(
types<>, Key&& key, Fx&& fx) {
26330 set(std::forward<Key>(key), std::forward<Fx>(fx));
26333 template <
typename Fx,
typename Key,
typename... Args,
26334 meta::disable<meta::is_specialization_of<meta::unqualified_t<Fx>,
overload_set>> = meta::enabler>
26335 void set_fx(
types<>, Key&& key, Fx&& fx, Args&&... args) {
26336 set(std::forward<Key>(key), as_function_reference(std::forward<Fx>(fx), std::forward<Args>(args)...));
26339 template <
typename... Sig,
typename... Args,
typename Key>
26340 void set_resolved_function(Key&& key, Args&&... args) {
26341 set(std::forward<Key>(key), as_function_reference<
function_sig<Sig...>>(std::forward<Args>(args)...));
26345 using base_t::base_t;
26348 using base_t::lua_state;
26350 using base_t::push;
26351 using base_t::traverse_get;
26352 using base_t::traverse_set;
26353 using base_t::unregister;
26355 template <
typename Key,
typename Value>
26360 uts.set(this->lua_state(), std::forward<Key>(key), std::forward<Value>(value));
26363 using ValueU = meta::unqualified_t<Value>;
26365 if constexpr (detail::is_non_factory_constructor_v<ValueU> || detail::is_policy_v<ValueU>) {
26370 table_base_t::set(std::forward<Key>(key), std::forward<Value>(value));
26376 template <
typename Sig,
typename Key,
typename... Args>
26378 set_fx(
types<Sig>(), std::forward<Key>(key), std::forward<Args>(args)...);
26382 template <
typename Key,
typename... Args>
26384 set_fx(
types<>(), std::forward<Key>(key), std::forward<Args>(args)...);
26388 template <
typename Key>
26393 template <
typename Key>
26409 template <
typename ref_t>
26414 friend class state;
26418 using base_t::lua_state;
26429 template <
typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
26431 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 26432 auto pp = stack::push_pop(*
this);
26434 stack::check<basic_lua_table>(lua_state(), -1, handler);
26442 basic_lua_table(
lua_State* L,
int index = -1) : base_t(detail::no_safety, L, index) {
26443 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 26445 stack::check<basic_lua_table>(L, index, handler);
26448 basic_lua_table(
lua_State* L,
ref_index index) : base_t(detail::no_safety, L, index) {
26449 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 26450 auto pp = stack::push_pop(*
this);
26452 stack::check<basic_lua_table>(lua_state(), -1, handler);
26455 template <
typename T,
26456 meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_lua_table>>, meta::neg<std::is_same<ref_t, stack_reference>>,
26458 basic_lua_table(T&& r) noexcept : basic_lua_table(detail::no_safety, std::forward<T>(r)) {
26459 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 26460 if (!
is_table<meta::unqualified_t<T>>::value) {
26461 auto pp = stack::push_pop(*
this);
26463 stack::check<basic_lua_table>(lua_state(), -1, handler);
26467 basic_lua_table(
lua_nil_t r) noexcept : basic_lua_table(detail::no_safety, r) {
26478 template <
bool is_global,
typename base_type>
26479 template <
typename Class,
typename Key>
26482 return this->new_usertype<Class>(std::forward<Key>(key), std::move(enrollments));
26485 template <
bool is_global,
typename base_type>
26486 template <
typename Class,
typename Key, automagic_flags enrollment_flags>
26488 int mt_index = u_detail::register_usertype<Class, enrollment_flags>(this->lua_state(), std::move(enrollments));
26490 lua_pop(this->lua_state(), 1);
26491 set(std::forward<Key>(key), mt);
26495 template <
bool is_global,
typename base_type>
26496 template <
typename Class,
typename Key>
26498 int mt_index = u_detail::register_usertype<Class, automagic_flags::all>(this->lua_state(), std::move(enrollments));
26500 lua_pop(this->lua_state(), 1);
26501 set(std::forward<Key>(key), mt);
26505 template <
bool is_global,
typename base_type>
26506 template <
typename Class,
typename Key,
typename Arg,
typename... Args,
typename>
26508 constexpr automagic_flags enrollment_flags = meta::any_same_v<no_construction, meta::unqualified_t<Arg>, meta::unqualified_t<Args>...>
26509 ? clear_flags(automagic_flags::all, automagic_flags::default_constructor)
26510 : automagic_flags::all;
26512 enrollments.default_constructor = !detail::any_is_constructor_v<Arg, Args...>;
26513 enrollments.destructor = !detail::any_is_destructor_v<Arg, Args...>;
26514 usertype<Class> ut = this->new_usertype<Class>(std::forward<Key>(key), std::move(enrollments));
26515 static_assert(
sizeof...(Args) % 2 == static_cast<std::size_t>(!detail::any_is_constructor_v<Arg>),
26516 "you must pass an even number of arguments to new_usertype after first passing a constructor");
26517 if constexpr (detail::any_is_constructor_v<Arg>) {
26518 ut.set(meta_function::construct, std::forward<Arg>(arg));
26519 ut.tuple_set(std::make_index_sequence<(
sizeof...(Args)) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...));
26522 ut.tuple_set(std::make_index_sequence<(
sizeof...(Args) + 1) / 2>(), std::forward_as_tuple(std::forward<Arg>(arg), std::forward<Args>(args)...));
26527 template <
typename base_type>
26528 template <
typename Key,
typename Value>
26532 int target = lua_gettop(L);
26534 maybe_uts = u_detail::maybe_get_usertype_storage_base(L, target);
26537 uts.set(L, std::forward<Key>(key), std::forward<Value>(value));
26541 base_t::set(std::forward<Key>(key), std::forward<Value>(value));
26551 if (lua_getmetatable(L, index) == 0) {
26570 template <
typename base_type>
26576 using base_t::lua_state;
26593 mt.set(meta_function::index, fallback);
26594 this->
set(metatable_key, mt);
26599 : base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) {
26600 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 26602 stack::check<env_key_t>(this->lua_state(), -1, handler);
26604 lua_pop(this->lua_state(), 1);
26608 : base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) {
26609 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 26611 stack::check<env_key_t>(this->lua_state(), -1, handler);
26613 lua_pop(this->lua_state(), 1);
26615 basic_environment(
lua_State* L,
int index = -1) : base_t(detail::no_safety, L, index) {
26616 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 26618 stack::check<basic_environment>(L, index, handler);
26621 basic_environment(
lua_State* L,
ref_index index) : base_t(detail::no_safety, L, index) {
26622 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 26623 auto pp = stack::push_pop(*
this);
26625 stack::check<basic_environment>(L, -1, handler);
26628 template <
typename T,
26629 meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_environment>>, meta::neg<std::is_same<base_type, stack_reference>>,
26631 basic_environment(T&& r) noexcept : base_t(detail::no_safety, std::forward<T>(r)) {
26632 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 26633 if (!is_environment<meta::unqualified_t<T>>::value) {
26634 auto pp = stack::push_pop(*
this);
26636 stack::check<basic_environment>(lua_state(), -1, handler);
26640 basic_environment(
lua_nil_t r) noexcept : base_t(detail::no_safety, r) {
26643 template <
typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
26644 basic_environment(
lua_State* L, T&& r) noexcept : base_t(detail::no_safety, L, std::forward<T>(r)) {
26645 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 26646 if (!is_environment<meta::unqualified_t<T>>::value) {
26647 auto pp = stack::push_pop(*
this);
26649 stack::check<basic_environment>(lua_state(), -1, handler);
26654 template <
typename T>
26655 bool set_on(
const T& target)
const {
26657 auto pp = stack::push_pop(target);
26658 int target_index = pp.index_of(target);
26659 #if SOL_LUA_VERSION_I_ < 502 26662 int success_result = lua_setfenv(L, target_index);
26663 return success_result != 0;
26667 if (lua_iscfunction(L, target_index) != 0) {
26668 const char* maybe_upvalue_name = lua_getupvalue(L, target_index, 1);
26669 if (maybe_upvalue_name ==
nullptr) {
26672 string_view upvalue_name(maybe_upvalue_name);
26673 if (upvalue_name ==
"") {
26675 const char* success = lua_setupvalue(L, target_index, 1);
26676 if (success ==
nullptr) {
26690 const char* maybe_upvalue_name = lua_getupvalue(L, target_index,
upvalue_index);
26691 if (maybe_upvalue_name ==
nullptr) {
26694 string_view upvalue_name(maybe_upvalue_name);
26695 if (upvalue_name ==
"_ENV") {
26698 const char* success = lua_setupvalue(L, target_index,
upvalue_index);
26699 if (success ==
nullptr) {
26718 template <
typename T,
typename E>
26720 return env.set_on(target);
26723 template <
typename E = reference,
typename T>
26726 auto pp = stack::pop_n(L, stack::push_environment_of(target));
26742 explicit operator bool()
const {
26743 return static_cast<bool>(env);
26755 return env.
value();
26759 return env.
value();
26779 int pre_stack_size = lua_gettop(L);
26780 if (lua_getstack(L, 1, &info) != 1) {
26781 if (lua_getstack(L, 0, &info) != 1) {
26782 lua_settop(L, pre_stack_size);
26786 if (lua_getinfo(L,
"f", &info) == 0) {
26787 lua_settop(L, pre_stack_size);
26793 if (!env.valid()) {
26794 lua_settop(L, pre_stack_size);
26820 load_result(
lua_State* Ls,
int stackindex = -1,
int retnum = 0,
int popnum = 0, load_status lerr = load_status::ok) noexcept
26821 : L(Ls), index(stackindex), returncount(retnum), popcount(popnum), err(lerr) {
26831 load_result(
load_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) {
26839 o.err = load_status::syntax;
26844 returncount = o.returncount;
26845 popcount = o.popcount;
26854 o.err = load_status::syntax;
26858 load_status status()
const noexcept {
26862 bool valid()
const noexcept {
26863 return status() == load_status::ok;
26866 template <
typename T>
26868 using UT = meta::unqualified_t<T>;
26869 if constexpr (meta::is_optional_v<UT>) {
26870 using ValueType =
typename UT::value_type;
26871 if constexpr (std::is_same_v<ValueType, error>) {
26873 return UT(nullopt);
26875 return error(detail::direct_error, stack::get<std::string>(L, index));
26879 return UT(nullopt);
26881 return stack::get<UT>(L, index);
26885 if constexpr (std::is_same_v<T, error>) {
26886 #if SOL_IS_ON(SOL_SAFE_PROXIES) 26888 type_panic_c_str(L, index, type_of(L, index), type::none,
"expecting an error type (a string, from Lua)");
26890 #endif // Check proxy type's safety 26891 return error(detail::direct_error, stack::get<std::string>(L, index));
26894 #if SOL_IS_ON(SOL_SAFE_PROXIES) 26896 type_panic_c_str(L, index, type_of(L, index), type::none);
26898 #endif // Check proxy type's safety 26899 return stack::get<T>(L, index);
26904 template <
typename... Ret,
typename... Args>
26905 decltype(
auto) call(Args&&... args) {
26906 return get<protected_function>().
template call<Ret...>(std::forward<Args>(args)...);
26909 template <
typename... Args>
26910 decltype(
auto) operator()(Args&&... args) {
26911 return call<>(std::forward<Args>(args)...);
26914 lua_State* lua_state()
const noexcept {
26917 int stack_index()
const noexcept {
26922 if (L !=
nullptr) {
26923 stack::remove(L, index, popcount);
26943 using base_t::base_t;
26947 template <
typename T>
26951 template <
typename T>
26954 static lua_State*& thread_local_lua_state() {
26955 #if SOL_IS_ON(SOL_USE_THREAD_LOCAL) 26956 static thread_local
lua_State* L =
nullptr;
26966 static void set_lua_state(
lua_State* L) {
26967 thread_local_lua_state() = L;
26970 template <
typename T, meta::disable<is_reference_or_lua_value_init_list<meta::unqualified_t<T>>> = meta::enabler>
26974 template <
typename T, meta::disable<is_lua_value_single_constructible<meta::unqualified_t<T>>> = meta::enabler>
26975 lua_value(T&& value) : ref_value(make_reference(thread_local_lua_state(), std::forward<T>(value))) {
26981 return std::move(il);
26985 lua_value(std::initializer_list<std::pair<lua_value, lua_value>> il) : ref_value(make_reference(thread_local_lua_state(), std::move(il))) {
26991 return std::move(il);
26995 lua_value(
arr il) : ref_value(make_reference(thread_local_lua_state(), std::move(il.value()))) {
27001 return std::move(r);
27022 return std::move(ref_value);
27025 template <
typename T>
27026 decltype(
auto) as()
const {
27028 return stack::pop<T>(ref_value.lua_state());
27031 template <
typename T>
27033 int r = ref_value.registry_index();
27034 if (r == LUA_REFNIL)
27036 if (r == LUA_NOREF)
27038 auto pp = stack::push_pop(ref_value);
27039 return stack::check<T>(ref_value.lua_state(), -1, &no_panic);
27049 return stack::push(L, lv.value());
27053 return stack::push(L, std::move(lv).value());
27060 return lua_value(L, stack::get<reference>(L, index, tracking));
27068 #if SOL_IS_ON(SOL_PRINT_ERRORS) 27069 #include <iostream> 27073 inline void register_main_thread(
lua_State* L) {
27074 #if SOL_LUA_VERSION_I_ < 502 27075 if (L ==
nullptr) {
27077 lua_setglobal(L, detail::default_main_thread_name());
27081 lua_setglobal(L, detail::default_main_thread_name());
27087 inline int default_at_panic(
lua_State* L) {
27088 #if SOL_IS_OFF(SOL_EXCEPTIONS) 27092 size_t messagesize;
27093 const char* message = lua_tolstring(L, -1, &messagesize);
27095 std::string err(message, messagesize);
27097 #if SOL_IS_ON(SOL_PRINT_ERRORS) 27098 std::cerr <<
"[sol2] An error occurred and panic has been invoked: ";
27100 std::cerr << std::endl;
27105 throw error(std::string(
"An unexpected error occurred and panic has been invoked"));
27106 #endif // Printing Errors 27109 inline int default_traceback_error_handler(
lua_State* L) {
27110 std::string msg =
"An unknown error has triggered the default error handler";
27113 const string_view& topmsg = maybetopmsg.
value();
27114 msg.assign(topmsg.data(), topmsg.size());
27116 luaL_traceback(L, L, msg.c_str(), 1);
27117 optional<string_view> maybetraceback = stack::unqualified_check_get<string_view>(L, -1, &no_panic);
27118 if (maybetraceback) {
27119 const string_view& traceback = maybetraceback.
value();
27120 msg.assign(traceback.data(), traceback.size());
27122 #if SOL_IS_ON(SOL_PRINT_ERRORS) 27127 return stack::push(L, msg);
27130 inline void set_default_state(
lua_State* L, lua_CFunction panic_function = &default_at_panic,
27131 lua_CFunction traceback_function = c_call<decltype(&default_traceback_error_handler), &default_traceback_error_handler>,
27132 exception_handler_function exf = detail::default_exception_handler) {
27133 lua_atpanic(L, panic_function);
27134 protected_function::set_default_handler(
object(L, in_place, traceback_function));
27135 set_default_exception_handler(L, exf);
27136 register_main_thread(L);
27137 stack::luajit_exception_handler(L);
27138 lua_value::set_lua_state(L);
27141 inline std::size_t total_memory_used(
lua_State* L) {
27142 std::size_t kb =
static_cast<std::size_t
>(lua_gc(L, LUA_GCCOUNT, 0));
27144 kb +=
static_cast<std::size_t
>(lua_gc(L, LUA_GCCOUNTB, 0));
27153 type t = type_of(L, result.stack_index());
27154 std::string err =
"sol: ";
27155 err += to_string(result.status());
27157 #if SOL_IS_ON(SOL_EXCEPTIONS) 27158 std::exception_ptr eptr = std::current_exception();
27162 std::rethrow_exception(eptr);
27164 catch (
const std::exception& ex) {
27165 err +=
"std::exception -- ";
27166 err.append(ex.what());
27168 catch (
const std::string& message) {
27169 err +=
"thrown message -- ";
27170 err.append(message);
27172 catch (
const char* message) {
27173 err +=
"thrown message -- ";
27174 err.append(message);
27177 err.append(
"thrown but unknown type, cannot serialize into error message");
27180 #endif // serialize exception information if possible 27181 if (t == type::string) {
27183 string_view serr = stack::unqualified_get<string_view>(L, result.stack_index());
27184 err.append(serr.data(), serr.size());
27186 #if SOL_IS_ON(SOL_PRINT_ERRORS) 27187 std::cerr <<
"[sol2] An error occurred and has been passed to an error handler: ";
27189 std::cerr << std::endl;
27192 int target = result.stack_index();
27193 if (result.pop_count() > 0) {
27194 stack::remove(L, target, result.pop_count());
27196 stack::push(L, err);
27197 int top = lua_gettop(L);
27198 int towards = top - target;
27199 if (towards != 0) {
27200 lua_rotate(L, top, towards);
27202 #if SOL_IS_OFF(SOL_EXCEPTIONS) 27206 throw error(detail::direct_error, err);
27207 #endif // If exceptions are allowed 27211 #if SOL_IS_ON(SOL_DEFAULT_PASS_ON_ERROR) 27212 return script_pass_on_error(L, std::move(pfr));
27214 return script_throw_on_error(L, std::move(pfr));
27220 int p = default_traceback_error_handler(L);
27221 sol::error err = stack::get<sol::error>(L, -p);
27243 bool is53mod = loaded && !(loaded->is<
bool>() && !loaded->as<
bool>());
27246 #if SOL_LUA_VERSION_I_ <= 501 27247 auto loaded51 = global.traverse_get<
optional<object>>(
"package",
"loaded", key);
27248 bool is51mod = loaded51 && !(loaded51->is<
bool>() && !loaded51->as<
bool>());
27255 template <
typename T>
27256 void ensure_package(
const std::string& key, T&& sr) {
27257 #if SOL_LUA_VERSION_I_ <= 501 27258 auto pkg = global[
"package"];
27259 if (!pkg.valid()) {
27260 pkg = create_table_with(
"loaded", create_table_with(key, sr));
27263 auto ld = pkg[
"loaded"];
27265 ld = create_table_with(key, sr);
27272 auto loaded = reg[
"_LOADED"];
27273 if (!loaded.valid()) {
27274 loaded = create_table_with(key, sr);
27281 template <
typename Fx>
27282 object require_core(
const std::string& key, Fx&& action,
bool create_global =
true) {
27284 if (loaded && loaded->valid())
27285 return std::move(*loaded);
27286 int before = lua_gettop(L);
27288 int after = lua_gettop(L);
27289 if (before == after) {
27293 ensure_package(key, static_cast<void*>(L));
27294 return object(L, lua_nil);
27299 ensure_package(key, sr);
27300 return stack::pop<object>(L);
27317 template <
typename... Args>
27318 void open_libraries(Args&&... args) {
27319 static_assert(
meta::all_same<lib, meta::unqualified_t<Args>...>::value,
"all types must be libraries");
27320 if constexpr (
sizeof...(args) == 0) {
27325 lib libraries[1 +
sizeof...(args)] = { lib::count, std::forward<Args>(args)... };
27327 for (
auto&& library : libraries) {
27329 #if SOL_LUA_VERSION_I_ <= 501 && SOL_IS_ON(SOL_USE_LUAJIT) 27330 case lib::coroutine:
27331 #endif // luajit opens coroutine base stuff 27333 luaL_requiref(L,
"base", luaopen_base, 1);
27337 luaL_requiref(L,
"package", luaopen_package, 1);
27340 #if SOL_IS_OFF(SOL_USE_LUAJIT) 27341 case lib::coroutine:
27342 #if SOL_LUA_VERSION_I_ > 501 27343 luaL_requiref(L,
"coroutine", luaopen_coroutine, 1);
27345 #endif // Lua 5.2+ only 27347 #endif // Not LuaJIT - comes builtin 27349 luaL_requiref(L,
"string", luaopen_string, 1);
27353 luaL_requiref(L,
"table", luaopen_table, 1);
27357 luaL_requiref(L,
"math", luaopen_math, 1);
27361 #if SOL_IS_ON(SOL_USE_LUAJIT) 27362 luaL_requiref(L,
"bit32", luaopen_bit, 1);
27364 #elif SOL_IS_ON(SOL_LUA_BIT32_LIB) 27365 luaL_requiref(L,
"bit32", luaopen_bit32, 1);
27371 luaL_requiref(L,
"io", luaopen_io, 1);
27375 luaL_requiref(L,
"os", luaopen_os, 1);
27379 luaL_requiref(L,
"debug", luaopen_debug, 1);
27383 #if SOL_LUA_VERSION_I_ > 502 && SOL_IS_OFF(SOL_USE_LUAJIT) 27384 luaL_requiref(L,
"utf8", luaopen_utf8, 1);
27386 #endif // Lua 5.3+ only 27389 #if SOL_IS_ON(SOL_USE_LUAJIT) && SOL_IS_OFF(SOL_LUAJIT_FFI_DISABLED) 27390 luaL_requiref(L,
"ffi", luaopen_ffi, 1);
27392 #endif // LuaJIT only 27395 #if SOL_IS_ON(SOL_USE_LUAJIT) 27396 luaL_requiref(L,
"jit", luaopen_jit, 0);
27398 #endif // LuaJIT Only 27408 object require(
const std::string& key, lua_CFunction open_function,
bool create_global =
true) {
27409 luaL_requiref(L, key.c_str(), open_function, create_global ? 1 : 0);
27410 return stack::pop<object>(L);
27413 object require_script(
const std::string& key,
const string_view& code,
bool create_global =
true,
27414 const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27415 auto action = [
this, &code, &chunkname, &mode]() { stack::script(L, code, chunkname, mode); };
27416 return require_core(key, action, create_global);
27419 object require_file(
const std::string& key,
const std::string& filename,
bool create_global =
true, load_mode mode = load_mode::any) {
27420 auto action = [
this, &filename, &mode]() { stack::script_file(L, filename, mode); };
27421 return require_core(key, action, create_global);
27424 void clear_package_loaders() {
27426 if (!maybe_package) {
27431 table&
package = *maybe_package;
27435 auto loaders_proxy =
package 27436 #if SOL_LUA_VERSION_I_ < 502
27442 if (!loaders_proxy.valid()) {
27451 template <
typename Fx>
27452 void add_package_loader(Fx&& fx,
bool clear_all_package_loaders =
false) {
27454 if (!maybe_package) {
27459 table&
package = *maybe_package;
27463 auto loaders_proxy =
package 27464 #if SOL_LUA_VERSION_I_ < 502
27470 bool make_new_table = clear_all_package_loaders || !loaders_proxy.valid();
27471 if (make_new_table) {
27477 if (!maybe_loaders) {
27483 table loaders = loaders_proxy;
27484 loaders.add(std::forward<Fx>(fx));
27487 template <
typename E>
27489 const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27490 detail::typical_chunk_name_t basechunkname = {};
27491 const char* chunknametarget = detail::make_chunk_name(
"lua_Reader", chunkname, basechunkname);
27492 load_status x =
static_cast<load_status
>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()));
27493 if (x != load_status::ok) {
27497 set_environment(env, pf);
27502 lua_Reader reader,
void* data,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27503 detail::typical_chunk_name_t basechunkname = {};
27504 const char* chunknametarget = detail::make_chunk_name(
"lua_Reader", chunkname, basechunkname);
27505 load_status x =
static_cast<load_status
>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()));
27506 if (x != load_status::ok) {
27513 template <
typename E>
27515 const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27516 detail::typical_chunk_name_t basechunkname = {};
27517 const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
27518 load_status x =
static_cast<load_status
>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()));
27519 if (x != load_status::ok) {
27523 set_environment(env, pf);
27528 const string_view& code,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27529 detail::typical_chunk_name_t basechunkname = {};
27530 const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
27531 load_status x =
static_cast<load_status
>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()));
27532 if (x != load_status::ok) {
27539 template <
typename E>
27541 load_status x =
static_cast<load_status
>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()));
27542 if (x != load_status::ok) {
27546 set_environment(env, pf);
27551 load_status x =
static_cast<load_status
>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()));
27552 if (x != load_status::ok) {
27559 template <
typename Fx,
27560 meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>,
27563 lua_Reader reader,
void* data, Fx&& on_error,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27565 if (!pfr.valid()) {
27566 return on_error(L, std::move(pfr));
27572 lua_Reader reader,
void* data,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27573 return safe_script(reader, data, script_default_on_error, chunkname, mode);
27576 template <
typename Fx,
27577 meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>,
27578 meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler>
27580 const string_view& code, Fx&& on_error,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27582 if (!pfr.valid()) {
27583 return on_error(L, std::move(pfr));
27588 template <
typename Fx,
typename E>
27590 const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27592 if (!pfr.valid()) {
27593 return on_error(L, std::move(pfr));
27598 template <
typename E>
27600 const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27601 return safe_script(code, env, script_default_on_error, chunkname, mode);
27605 const string_view& code,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27606 return safe_script(code, script_default_on_error, chunkname, mode);
27609 template <
typename Fx,
27610 meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>,
27611 meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler>
27612 protected_function_result safe_script_file(
const std::string& filename, Fx&& on_error, load_mode mode = load_mode::any) {
27614 if (!pfr.valid()) {
27615 return on_error(L, std::move(pfr));
27620 template <
typename Fx,
typename E>
27622 const std::string& filename,
const basic_environment<E>& env, Fx&& on_error, load_mode mode = load_mode::any) {
27624 if (!pfr.valid()) {
27625 return on_error(L, std::move(pfr));
27630 template <
typename E>
27632 return safe_script_file(filename, env, script_default_on_error, mode);
27636 return safe_script_file(filename, script_default_on_error, mode);
27639 template <
typename E>
27641 const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27642 detail::typical_chunk_name_t basechunkname = {};
27643 const char* chunknametarget = detail::make_chunk_name(
"lua_Reader", chunkname, basechunkname);
27644 int index = lua_gettop(L);
27645 if (lua_load(L, reader, data, chunknametarget, to_string(mode).c_str())) {
27649 if (lua_pcall(L, 0, LUA_MULTRET, 0)) {
27652 int postindex = lua_gettop(L);
27653 int returns = postindex - index;
27658 lua_Reader reader,
void* data,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27659 int index = lua_gettop(L);
27660 stack::script(L, reader, data, chunkname, mode);
27661 int postindex = lua_gettop(L);
27662 int returns = postindex - index;
27666 template <
typename E>
27668 const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27669 detail::typical_chunk_name_t basechunkname = {};
27670 const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
27671 int index = lua_gettop(L);
27672 if (luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str())) {
27676 if (lua_pcall(L, 0, LUA_MULTRET, 0)) {
27679 int postindex = lua_gettop(L);
27680 int returns = postindex - index;
27685 const string_view& code,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27686 int index = lua_gettop(L);
27687 stack::script(L, code, chunkname, mode);
27688 int postindex = lua_gettop(L);
27689 int returns = postindex - index;
27693 template <
typename E>
27695 int index = lua_gettop(L);
27696 if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())) {
27700 if (lua_pcall(L, 0, LUA_MULTRET, 0)) {
27703 int postindex = lua_gettop(L);
27704 int returns = postindex - index;
27708 unsafe_function_result unsafe_script_file(
const std::string& filename, load_mode mode = load_mode::any) {
27709 int index = lua_gettop(L);
27710 stack::script_file(L, filename, mode);
27711 int postindex = lua_gettop(L);
27712 int returns = postindex - index;
27716 template <
typename Fx,
27717 meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>,
27718 meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler>
27720 const string_view& code, Fx&& on_error,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27721 return safe_script(code, std::forward<Fx>(on_error), chunkname, mode);
27724 template <
typename Fx,
27725 meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>,
27726 meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler>
27728 return safe_script_file(filename, std::forward<Fx>(on_error), mode);
27731 template <
typename Fx,
typename E>
27733 const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27734 return safe_script(code, env, std::forward<Fx>(on_error), chunkname, mode);
27737 template <
typename Fx,
typename E>
27739 return safe_script_file(filename, env, std::forward<Fx>(on_error), mode);
27743 const string_view& code,
const environment& env,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27744 return safe_script(code, env, script_default_on_error, chunkname, mode);
27748 return safe_script_file(filename, env, script_default_on_error, mode);
27751 #if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS) 27753 lua_Reader reader,
void* data,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27754 return safe_script(reader, data, chunkname, mode);
27758 const string_view& code,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27759 return safe_script(code, chunkname, mode);
27763 return safe_script_file(filename, mode);
27766 unsafe_function_result script(
const string_view& code,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27767 return unsafe_script(code, chunkname, mode);
27771 return unsafe_script_file(filename, mode);
27774 load_result load(
const string_view& code,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27775 detail::typical_chunk_name_t basechunkname = {};
27776 const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
27777 load_status x =
static_cast<load_status
>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()));
27781 load_result load_buffer(
const char* buff,
size_t size,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27782 return load(string_view(buff, size), chunkname, mode);
27786 const std::byte* buff,
size_t size,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27787 return load(string_view(reinterpret_cast<const char*>(buff), size), chunkname, mode);
27790 load_result load_file(
const std::string& filename, load_mode mode = load_mode::any) {
27791 load_status x =
static_cast<load_status
>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()));
27795 load_result load(lua_Reader reader,
void* data,
const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
27796 detail::typical_chunk_name_t basechunkname = {};
27797 const char* chunknametarget = detail::make_chunk_name(
"lua_Reader", chunkname, basechunkname);
27798 load_status x =
static_cast<load_status
>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()));
27802 iterator begin()
const {
27803 return global.begin();
27806 iterator end()
const {
27807 return global.end();
27810 const_iterator cbegin()
const {
27811 return global.cbegin();
27814 const_iterator cend()
const {
27815 return global.cend();
27828 table registry()
const {
27832 std::size_t memory_used()
const {
27833 return total_memory_used(lua_state());
27836 int stack_top()
const {
27837 return stack::top(L);
27840 int stack_clear() {
27841 int s = stack_top();
27846 bool supports_gc_mode(gc_mode mode)
const noexcept {
27847 #if SOL_LUA_VERSION_I_ >= 504 27852 return mode == gc_mode::default_value;
27855 bool is_gc_on()
const {
27856 #if SOL_LUA_VERSION_I_ >= 502 27857 return lua_gc(lua_state(), LUA_GCISRUNNING, 0) == 1;
27864 void collect_garbage() {
27865 lua_gc(lua_state(), LUA_GCCOLLECT, 0);
27868 void collect_gc() {
27872 bool step_gc(
int step_size_kilobytes) {
27876 #if SOL_LUA_VERSION_I_ >= 504 27879 return lua_gc(lua_state(), LUA_GCSTEP, step_size_kilobytes) != 0;
27881 return lua_gc(lua_state(), LUA_GCSTEP, step_size_kilobytes) == 1;
27885 void restart_gc() {
27886 lua_gc(lua_state(), LUA_GCRESTART, 0);
27890 lua_gc(lua_state(), LUA_GCSTOP, 0);
27894 gc_mode change_gc_mode_incremental(
int pause,
int step_multiplier,
int step_byte_size) {
27901 #if SOL_LUA_VERSION_I_ >= 504 27902 int old_mode = lua_gc(lua_state(), LUA_GCINC, pause, step_multiplier, step_byte_size);
27903 if (old_mode == LUA_GCGEN) {
27904 return gc_mode::generational;
27906 else if (old_mode == LUA_GCINC) {
27907 return gc_mode::incremental;
27910 lua_gc(lua_state(), LUA_GCSETPAUSE, pause);
27911 lua_gc(lua_state(), LUA_GCSETSTEPMUL, step_multiplier);
27912 (void)step_byte_size;
27914 return gc_mode::default_value;
27918 gc_mode change_gc_mode_generational(
int minor_multiplier,
int major_multiplier) {
27919 #if SOL_LUA_VERSION_I_ >= 504 27922 int old_mode = lua_gc(lua_state(), LUA_GCGEN, minor_multiplier, major_multiplier);
27923 if (old_mode == LUA_GCGEN) {
27924 return gc_mode::generational;
27926 else if (old_mode == LUA_GCINC) {
27927 return gc_mode::incremental;
27930 (void)minor_multiplier;
27931 (void)major_multiplier;
27933 return gc_mode::default_value;
27937 return lua_state();
27940 void set_panic(lua_CFunction panic) {
27941 lua_atpanic(lua_state(), panic);
27944 void set_exception_handler(exception_handler_function handler) {
27945 set_default_exception_handler(lua_state(), handler);
27948 template <
typename... Args,
typename... Keys>
27949 decltype(
auto)
get(Keys&&... keys)
const {
27950 return global.get<Args...>(std::forward<Keys>(keys)...);
27953 template <
typename T,
typename Key>
27954 decltype(
auto) get_or(Key&& key, T&& otherwise)
const {
27955 return global.get_or(std::forward<Key>(key), std::forward<T>(otherwise));
27958 template <
typename T,
typename Key,
typename D>
27959 decltype(
auto) get_or(Key&& key, D&& otherwise)
const {
27960 return global.get_or<T>(std::forward<Key>(key), std::forward<D>(otherwise));
27963 template <
typename... Args>
27965 global.set(std::forward<Args>(args)...);
27969 template <
typename T,
typename... Keys>
27970 decltype(
auto) traverse_get(Keys&&... keys)
const {
27971 return global.traverse_get<T>(std::forward<Keys>(keys)...);
27974 template <
typename... Args>
27976 global.traverse_set(std::forward<Args>(args)...);
27980 template <
typename Class,
typename... Args>
27982 return global.new_usertype<Class>(std::forward<Args>(args)...);
27985 template <
bool read_only =
true,
typename... Args>
27986 state_view& new_enum(
const string_view& name, Args&&... args) {
27987 global.new_enum<read_only>(name, std::forward<Args>(args)...);
27991 template <
typename T,
bool read_only = true>
27992 state_view& new_enum(
const string_view& name, std::initializer_list<std::pair<string_view, T>> items) {
27993 global.new_enum<T, read_only>(name, std::move(items));
27997 template <
typename Fx>
27998 void for_each(Fx&& fx) {
27999 global.for_each(std::forward<Fx>(fx));
28002 template <
typename T>
28004 return global[std::forward<T>(key)];
28007 template <
typename T>
28009 return global[std::forward<T>(key)];
28012 template <
typename Sig,
typename... Args,
typename Key>
28013 state_view& set_function(Key&& key, Args&&... args) {
28014 global.set_function<Sig>(std::forward<Key>(key), std::forward<Args>(args)...);
28018 template <
typename... Args,
typename Key>
28019 state_view& set_function(Key&& key, Args&&... args) {
28020 global.set_function(std::forward<Key>(key), std::forward<Args>(args)...);
28024 template <
typename Name>
28025 table create_table(Name&& name,
int narr = 0,
int nrec = 0) {
28026 return global.create(std::forward<Name>(name), narr, nrec);
28029 template <
typename Name,
typename Key,
typename Value,
typename... Args>
28030 table create_table(Name&& name,
int narr,
int nrec, Key&& key, Value&& value, Args&&... args) {
28031 return global.create(std::forward<Name>(name), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
28034 template <
typename Name,
typename... Args>
28035 table create_named_table(Name&& name, Args&&... args) {
28036 table x = global.create_with(std::forward<Args>(args)...);
28037 global.set(std::forward<Name>(name), x);
28041 table create_table(
int narr = 0,
int nrec = 0) {
28042 return create_table(lua_state(), narr, nrec);
28045 template <
typename Key,
typename Value,
typename... Args>
28046 table create_table(
int narr,
int nrec, Key&& key, Value&& value, Args&&... args) {
28047 return create_table(lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
28050 template <
typename... Args>
28051 table create_table_with(Args&&... args) {
28052 return create_table_with(lua_state(), std::forward<Args>(args)...);
28055 static inline table create_table(
lua_State* L,
int narr = 0,
int nrec = 0) {
28056 return global_table::create(L, narr, nrec);
28059 template <
typename Key,
typename Value,
typename... Args>
28060 static inline table create_table(
lua_State* L,
int narr,
int nrec, Key&& key, Value&& value, Args&&... args) {
28061 return global_table::create(L, narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
28064 template <
typename... Args>
28065 static inline table create_table_with(
lua_State* L, Args&&... args) {
28066 return global_table::create_with(L, std::forward<Args>(args)...);
28082 lua_State* lua_state()
const noexcept {
28086 return lua_state();
28088 lua_State* operator->()
const noexcept {
28089 return lua_state();
28097 lua_pushthread(lts.L);
28113 template <
typename Handler>
28116 if (lts.lua_state() ==
nullptr) {
28117 handler(L, index, type::thread, type_of(L, index),
"value is not a valid thread type");
28126 template <
typename ref_t>
28132 using base_t::lua_state;
28137 template <
typename T,
28139 basic_thread(T&& r) : base_t(std::forward<T>(r)) {
28140 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28141 auto pp = stack::push_pop(*
this);
28143 stack::check<basic_thread>(lua_state(), -1, handler);
28146 basic_thread(
const stack_reference& r) : basic_thread(r.lua_state(), r.stack_index()) {};
28147 basic_thread(
stack_reference&& r) : basic_thread(r.lua_state(), r.stack_index()) {};
28148 basic_thread& operator=(
const basic_thread&) =
default;
28149 basic_thread& operator=(basic_thread&&) =
default;
28150 template <
typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
28151 basic_thread(
lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) {
28152 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28153 auto pp = stack::push_pop(*
this);
28155 stack::check<basic_thread>(lua_state(), -1, handler);
28158 basic_thread(
lua_State* L,
int index = -1) : base_t(L, index) {
28159 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28161 stack::check<basic_thread>(L, index, handler);
28165 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28166 auto pp = stack::push_pop(*
this);
28168 stack::check<basic_thread>(lua_state(), -1, handler);
28176 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28178 stack::check<basic_thread>(lua_state(), -1, handler);
28181 lua_pop(lua_state(), 1);
28189 bool is_main_thread()
const {
28190 return stack::is_main_thread(this->thread_state());
28194 auto pp = stack::push_pop(*
this);
28195 lua_State* lthread = lua_tothread(lua_state(), -1);
28199 thread_status status()
const {
28201 auto lstat =
static_cast<thread_status
>(lua_status(lthread));
28202 if (lstat == thread_status::ok) {
28204 if (lua_getstack(lthread, 0, &ar) > 0)
28205 return thread_status::ok;
28206 else if (lua_gettop(lthread) == 0)
28207 return thread_status::dead;
28209 return thread_status::yielded;
28214 basic_thread create() {
28215 return create(lua_state());
28218 static basic_thread create(
lua_State* L) {
28220 basic_thread result(L);
28238 typedef std::unique_ptr<lua_State, detail::state_deleter> unique_base;
28241 state(lua_CFunction panic = default_at_panic) : unique_base(luaL_newstate()),
state_view(unique_base::get()) {
28242 set_default_state(unique_base::get(), panic);
28245 state(lua_CFunction panic, lua_Alloc alfunc,
void* alpointer =
nullptr)
28246 : unique_base(lua_newstate(alfunc, alpointer)),
state_view(unique_base::get()) {
28247 set_default_state(unique_base::get(), panic);
28254 state_view::operator=(std::move(that));
28255 unique_base::operator=(std::move(that));
28259 using state_view::get;
28271 template <
typename Reference>
28278 call_status stats = call_status::yielded;
28280 void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) {
28281 #if SOL_LUA_VERSION_I_ >= 504 28283 stats =
static_cast<call_status
>(lua_resume(lua_state(),
nullptr, static_cast<int>(argcount), &nresults));
28285 stats =
static_cast<call_status
>(lua_resume(lua_state(),
nullptr, static_cast<int>(argcount)));
28289 template <std::size_t... I,
typename... Ret>
28290 auto invoke(
types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n) {
28291 luacall(n,
sizeof...(Ret));
28292 return stack::pop<std::tuple<Ret...>>(lua_state());
28295 template <std::
size_t I,
typename Ret>
28296 Ret invoke(
types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) {
28298 return stack::pop<Ret>(lua_state());
28301 template <std::
size_t I>
28302 void invoke(
types<void>, std::index_sequence<I>, std::ptrdiff_t n) {
28307 int firstreturn = 1;
28308 luacall(n, LUA_MULTRET);
28309 int poststacksize = lua_gettop(this->lua_state());
28310 int returncount = poststacksize - (firstreturn - 1);
28312 if (m_error_handler.valid()) {
28313 string_view err = stack::get<string_view>(this->lua_state(), poststacksize);
28314 m_error_handler.push();
28315 stack::push(this->lua_state(), err);
28316 lua_call(lua_state(), 1, 1);
28324 using base_t::lua_state;
28327 template <
typename T,
28328 meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>,
basic_coroutine>>,
28329 meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<T>>>, meta::neg<std::is_same<base_t, stack_reference>>,
28331 basic_coroutine(T&& r) noexcept
28333 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28334 if (!
is_function<meta::unqualified_t<T>>::value) {
28335 auto pp = stack::push_pop(*
this);
28337 stack::check<basic_coroutine>(lua_state(), -1, handler);
28342 basic_coroutine(
const basic_coroutine& other) =
default;
28343 basic_coroutine& operator=(
const basic_coroutine&) =
default;
28345 basic_coroutine(basic_coroutine&& other) noexcept : base_t(std::move(other)), m_error_handler(this->lua_state(), std::move(other.m_error_handler)) {
28348 basic_coroutine& operator=(basic_coroutine&& other) noexcept {
28349 base_t::operator=(std::move(other));
28351 m_error_handler = handler_t(this->lua_state(), std::move(other.m_error_handler));
28361 basic_coroutine(
const basic_function<base_t>& b, handler_t eh) noexcept : base_t(b), m_error_handler(std::move(eh)) {
28363 basic_coroutine(
basic_function<base_t>&& b, handler_t eh) noexcept : base_t(std::move(b)), m_error_handler(std::move(eh)) {
28366 : basic_coroutine(r.lua_state(), r.stack_index(), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) {
28369 : basic_coroutine(r.lua_state(), r.stack_index(), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) {
28371 basic_coroutine(
const stack_reference& r, handler_t eh) noexcept : basic_coroutine(r.lua_state(), r.stack_index(), std::move(eh)) {
28373 basic_coroutine(
stack_reference&& r, handler_t eh) noexcept : basic_coroutine(r.lua_state(), r.stack_index(), std::move(eh)) {
28376 template <
typename Super>
28380 template <
typename Super>
28384 template <
typename Proxy,
typename HandlerReference,
28385 meta::enable<std::is_base_of<proxy_base_tag, meta::unqualified_t<Proxy>>,
28386 meta::neg<is_lua_index<meta::unqualified_t<HandlerReference>>>> = meta::enabler>
28387 basic_coroutine(Proxy&& p, HandlerReference&& eh) : basic_coroutine(detail::force_cast<base_t>(p), std::forward<HandlerReference>(eh)) {
28390 template <
typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
28391 basic_coroutine(
lua_State* L, T&& r) noexcept
28394 template <
typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
28395 basic_coroutine(
lua_State* L, T&& r, handler_t eh) : base_t(L, std::forward<T>(r)), m_error_handler(std::move(eh)) {
28396 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28397 auto pp = stack::push_pop(*
this);
28399 stack::check<basic_coroutine>(lua_state(), -1, handler);
28403 basic_coroutine(
lua_nil_t n) : base_t(n), m_error_handler(n) {
28406 basic_coroutine(
lua_State* L,
int index = -1)
28409 basic_coroutine(
lua_State* L,
int index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
28410 #ifdef SOL_SAFE_REFERENCES 28412 stack::check<basic_coroutine>(L, index, handler);
28418 basic_coroutine(
lua_State* L,
absolute_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
28419 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28421 stack::check<basic_coroutine>(L, index, handler);
28427 basic_coroutine(
lua_State* L,
raw_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
28428 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28430 stack::check<basic_coroutine>(L, index, handler);
28436 basic_coroutine(
lua_State* L,
ref_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) {
28437 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28438 auto pp = stack::push_pop(*
this);
28440 stack::check<basic_coroutine>(lua_state(), -1, handler);
28444 call_status status()
const noexcept {
28448 bool error()
const noexcept {
28449 call_status cs = status();
28450 return cs != call_status::ok && cs != call_status::yielded;
28453 bool runnable()
const noexcept {
28454 return base_t::valid() && (status() == call_status::yielded);
28457 explicit operator bool()
const noexcept {
28461 template <
typename... Args>
28463 return call<>(std::forward<Args>(args)...);
28466 template <
typename... Ret,
typename... Args>
28468 return call<Ret...>(std::forward<Args>(args)...);
28471 template <
typename... Ret,
typename... Args>
28472 decltype(
auto) call(Args&&... args) {
28478 int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
28479 return invoke(
types<Ret...>(), std::make_index_sequence<
sizeof...(Ret)>(), pushcount);
28483 handler_t m_error_handler;
28492 template <
typename base_type>
28498 using base_t::lua_state;
28501 template <
typename T,
28502 meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>,
basic_userdata>>, meta::neg<std::is_same<base_t, stack_reference>>,
28504 basic_userdata(T&& r) noexcept : base_t(std::forward<T>(r)) {
28505 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28506 if (!
is_userdata<meta::unqualified_t<T>>::value) {
28507 auto pp = stack::push_pop(*
this);
28508 type_assert(lua_state(), -1, type::userdata);
28512 basic_userdata(
const basic_userdata&) =
default;
28513 basic_userdata(basic_userdata&&) =
default;
28514 basic_userdata& operator=(
const basic_userdata&) =
default;
28515 basic_userdata& operator=(basic_userdata&&) =
default;
28516 basic_userdata(
const stack_reference& r) : basic_userdata(r.lua_state(), r.stack_index()) {
28518 basic_userdata(
stack_reference&& r) : basic_userdata(r.lua_state(), r.stack_index()) {
28520 template <
typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
28521 basic_userdata(
lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) {
28522 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28523 auto pp = stack::push_pop(*
this);
28525 stack::check<basic_userdata>(L, -1, handler);
28528 basic_userdata(
lua_State* L,
int index = -1) : base_t(detail::no_safety, L, index) {
28529 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28531 stack::check<basic_userdata>(L, index, handler);
28534 basic_userdata(
lua_State* L,
ref_index index) : base_t(detail::no_safety, L, index) {
28535 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28536 auto pp = stack::push_pop(*
this);
28538 stack::check<basic_userdata>(L, -1, handler);
28543 template <
typename base_type>
28548 using base_t::lua_state;
28551 template <
typename T,
28552 meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>,
basic_lightuserdata>>, meta::neg<std::is_same<base_t, stack_reference>>,
28554 basic_lightuserdata(T&& r) noexcept : base_t(std::forward<T>(r)) {
28555 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28557 auto pp = stack::push_pop(*
this);
28558 type_assert(lua_state(), -1, type::lightuserdata);
28562 basic_lightuserdata(
const basic_lightuserdata&) =
default;
28563 basic_lightuserdata(basic_lightuserdata&&) =
default;
28564 basic_lightuserdata& operator=(
const basic_lightuserdata&) =
default;
28565 basic_lightuserdata& operator=(basic_lightuserdata&&) =
default;
28566 basic_lightuserdata(
const stack_reference& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {
28568 basic_lightuserdata(
stack_reference&& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {
28570 template <
typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
28571 basic_lightuserdata(
lua_State* L, T&& r) : basic_lightuserdata(L, std::forward<T>(r)) {
28572 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28573 auto pp = stack::push_pop(*
this);
28575 stack::check<basic_lightuserdata>(lua_state(), -1, handler);
28578 basic_lightuserdata(
lua_State* L,
int index = -1) : base_t(L, index) {
28579 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28581 stack::check<basic_lightuserdata>(L, index, handler);
28585 #if SOL_IS_ON(SOL_SAFE_REFERENCES) 28586 auto pp = stack::push_pop(*
this);
28588 stack::check<basic_lightuserdata>(lua_state(), index, handler);
28600 template <
typename T>
28605 template <
typename Source>
28606 auto as_args(Source&& source) {
28611 template <
typename T>
28615 for (
const auto& i : e.src) {
28616 p += stack::push(L, i);
28629 #include <iterator> 28642 typedef std::ptrdiff_t difference_type;
28643 typedef std::size_t size_type;
28646 typedef std::reverse_iterator<iterator> reverse_iterator;
28647 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
28650 variadic_args(
lua_State* luastate,
int stackindex = -1) : L(luastate), index(lua_absindex(luastate, stackindex)), stacktop(lua_gettop(luastate)) {
28652 variadic_args(
lua_State* luastate,
int stackindex,
int lastindex) : L(luastate), index(lua_absindex(luastate, stackindex)), stacktop(lastindex) {
28667 stacktop = o.stacktop;
28678 return iterator(L, index, stacktop + 1);
28681 return iterator(L, stacktop + 1, stacktop + 1);
28683 const_iterator begin()
const {
28684 return const_iterator(L, index, stacktop + 1);
28686 const_iterator end()
const {
28687 return const_iterator(L, stacktop + 1, stacktop + 1);
28689 const_iterator cbegin()
const {
28692 const_iterator cend()
const {
28696 reverse_iterator rbegin() {
28697 return std::reverse_iterator<iterator>(begin());
28699 reverse_iterator rend() {
28700 return std::reverse_iterator<iterator>(end());
28702 const_reverse_iterator rbegin()
const {
28703 return std::reverse_iterator<const_iterator>(begin());
28705 const_reverse_iterator rend()
const {
28706 return std::reverse_iterator<const_iterator>(end());
28708 const_reverse_iterator crbegin()
const {
28709 return std::reverse_iterator<const_iterator>(cbegin());
28711 const_reverse_iterator crend()
const {
28712 return std::reverse_iterator<const_iterator>(cend());
28721 for (
int i = index; i <= stacktop; ++i) {
28722 lua_pushvalue(L, i);
28726 lua_xmove(L, target, pushcount);
28731 template <
typename T>
28732 decltype(
auto)
get(difference_type index_offset = 0)
const {
28733 return stack::get<T>(L, index +
static_cast<int>(index_offset));
28736 type get_type(difference_type index_offset = 0)
const noexcept {
28737 return type_of(L, index + static_cast<int>(index_offset));
28740 stack_proxy operator[](difference_type index_offset)
const {
28741 return stack_proxy(L, index + static_cast<int>(index_offset));
28747 int stack_index()
const {
28750 int leftover_count()
const {
28751 return stacktop - (index - 1);
28753 std::size_t size()
const {
28754 return static_cast<std::size_t
>(leftover_count());
28773 return ref.push(L);
28786 template <
typename T>
28792 using base_t::base_t;
28793 using base_t::value;
28796 template <
typename Source>
28797 auto as_returns(Source&& source) {
28802 template <
typename T>
28805 auto& src = detail::unwrap(e.value());
28807 for (
const auto& i : src) {
28808 p += stack::push(L, i);
28822 template <
typename Al =
typename std::allocator<
object>>
28825 using base_t = std::vector<object, Al>;
28832 this->reserve(fr.return_count());
28833 this->insert(this->cend(), fr.begin(), fr.end());
28837 this->reserve(fr.return_count());
28838 this->insert(this->cend(), fr.begin(), fr.end());
28841 template <
typename Arg0,
typename... Args,
28842 meta::disable_any<std::is_same<meta::unqualified_t<Arg0>, basic_variadic_results>, std::is_same<meta::unqualified_t<Arg0>,
function_result>,
28844 basic_variadic_results(Arg0&& arg0, Args&&... args) : base_t(std::forward<Arg0>(arg0), std::forward<Args>(args)...) {
28847 basic_variadic_results(
const basic_variadic_results&) =
default;
28848 basic_variadic_results(basic_variadic_results&&) =
default;
28856 using base_t::base_t;
28859 template <
typename Al>
28866 template <
typename Al>
28870 for (
const auto& i : e) {
28871 p += stack::push(L, i);
28879 int push(
lua_State* L,
const variadic_results& r) {
28881 return stack::push(L, static_cast<const base_t&>(r));
28890 #if SOL_IS_ON(SOL_COMPILER_GCC) 28891 #pragma GCC diagnostic pop 28892 #elif SOL_IS_ON(SOL_COMPILER_CLANG) 28893 #elif SOL_IS_ON(SOL_COMPILER_VCXX) 28894 #pragma warning(pop) 28897 #if SOL_IS_ON(SOL_INSIDE_UNREAL_ENGINE) 28899 #pragma pop_macro("check") 28900 #endif // Unreal Engine 4 Bullshit 28905 #endif // SOL_SINGLE_INCLUDE_HPP Definition: sol.hpp:28076
Definition: sol.hpp:21381
Definition: sol.hpp:17437
Definition: sol.hpp:14889
Definition: sol.hpp:17226
Definition: sol.hpp:13372
SOL_TL_OPTIONAL_11_CONSTEXPR T & operator*() &
Definition: sol.hpp:5901
Definition: sol.hpp:17926
Definition: sol.hpp:12205
detail::enable_if_t< std::is_constructible< T, std::initializer_list< U > &, Args &&... >::value, T & > emplace(std::initializer_list< U > il, Args &&... args)
Definition: sol.hpp:5854
void swap(optional &rhs) noexcept
Definition: sol.hpp:6762
Definition: sol.hpp:10157
Definition: sol.hpp:11413
Definition: sol.hpp:11462
optional< T > SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) const &
Definition: sol.hpp:6494
Definition: sol.hpp:18159
Definition: sol.hpp:21405
Definition: sol.hpp:13075
Definition: sol.hpp:16992
Definition: sol.hpp:19805
Definition: sol.hpp:11379
Definition: sol.hpp:10810
Definition: sol.hpp:21332
Definition: lobject.h:497
Definition: sol.hpp:21537
optional take() &&
take
Definition: sol.hpp:5643
constexpr const T * operator->() const
Definition: sol.hpp:6770
SOL_TL_OPTIONAL_11_CONSTEXPR T & operator*()
Definition: sol.hpp:6784
SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) &&
disjunction
Definition: sol.hpp:6629
Definition: sol.hpp:19801
Definition: sol.hpp:21666
optional< T > or_else(F &&f) const &&
Definition: sol.hpp:6501
Definition: sol.hpp:20737
Definition: sol.hpp:21308
Definition: sol.hpp:13081
Definition: sol.hpp:25036
T & emplace(Args &&... args) noexcept
Definition: sol.hpp:6749
Definition: sol.hpp:10932
Definition: sol.hpp:19218
Definition: sol.hpp:23438
Definition: sol.hpp:17783
Definition: sol.hpp:18009
Definition: sol.hpp:10143
detail::invoke_result_t< U > map_or_else(F &&f, U &&u) &&
Definition: sol.hpp:5553
Definition: sol.hpp:11429
Definition: sol.hpp:11442
Definition: sol.hpp:10002
U map_or(F &&f, U &&u) const &
map_or
Definition: sol.hpp:5523
Definition: sol.hpp:21501
void reset() noexcept
Destroys the stored value if one exists, making the optional empty.
Definition: sol.hpp:5998
Definition: sol.hpp:10820
Definition: sol.hpp:15391
SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) &&
disjunction
Definition: sol.hpp:5594
Definition: sol.hpp:10050
Definition: sol.hpp:19100
constexpr const T & operator*() const &
Definition: sol.hpp:5907
constexpr detail::invoke_result_t< F, const T && > and_then(F &&f) const &&
Definition: sol.hpp:5344
Definition: sol.hpp:11450
optional take() &&
take
Definition: sol.hpp:6656
Definition: sol.hpp:16007
optional< T > SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) const &
Definition: sol.hpp:5481
SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) &
disjunction
Definition: sol.hpp:5606
SOL_TL_OPTIONAL_11_CONSTEXPR T * operator->()
Definition: sol.hpp:6776
detail::invoke_result_t< U > map_or_else(F &&f, U &&u) &&
Definition: sol.hpp:6566
Definition: sol.hpp:28851
Definition: sol.hpp:18506
U map_or(F &&f, U &&u) const &
map_or
Definition: sol.hpp:6536
Definition: sol.hpp:21369
Definition: sol.hpp:18984
Definition: sol.hpp:25390
SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t< F, T & > and_then(F &&f) &
Definition: sol.hpp:5313
Definition: sol.hpp:25442
Definition: sol.hpp:19831
Definition: json.hpp:16563
Definition: sol.hpp:10931
Definition: sol.hpp:17987
optional & operator=(U &&u)
Definition: sol.hpp:5781
optional(optional< U > &&rhs)
Definition: sol.hpp:5738
Definition: sol.hpp:12320
Definition: sol.hpp:10817
detail::invoke_result_t< U > map_or_else(F &&f, U &&u) const &&
Definition: sol.hpp:6583
Definition: sol.hpp:21489
detail::invoke_result_t< U > map_or_else(F &&f, U &&u) &
Maps the stored value with f if there is one, otherwise calls u and returns the result.
Definition: sol.hpp:6558
Definition: sol.hpp:19562
SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t< F, T && > and_then(F &&f) &&
Definition: sol.hpp:5323
SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) &
Definition: sol.hpp:6597
Definition: sol.hpp:17119
Definition: sol.hpp:17606
Definition: sol.hpp:28823
constexpr optional(const T &u)
Definition: sol.hpp:5714
Definition: sol.hpp:11439
Definition: sol.hpp:11455
Definition: sol.hpp:17758
Definition: lauxlib.h:193
U map_or(F &&f, U &&u) &
Maps the stored value with f if there is one, otherwise returns u.
Definition: sol.hpp:6524
Definition: sol.hpp:23455
Definition: sol.hpp:10938
Definition: lobject.h:100
Definition: sol.hpp:21208
U map_or(F &&f, U &&u) &&
map_or
Definition: sol.hpp:5517
Definition: sol.hpp:11554
Definition: sol.hpp:24555
Definition: sol.hpp:11431
constexpr detail::invoke_result_t< F, const T & > and_then(F &&f) const &
Definition: sol.hpp:6347
Definition: sol.hpp:23425
constexpr const T & operator*() const
Definition: sol.hpp:6790
Definition: sol.hpp:17775
constexpr optional disjunction(const optional &rhs) const &
disjunction
Definition: sol.hpp:6602
Definition: sol.hpp:26730
optional & operator=(const optional< U > &rhs)
Definition: sol.hpp:5798
optional< T > or_else(F &&f) &&
Definition: sol.hpp:6467
Definition: sol.hpp:13018
Definition: sol.hpp:14256
Definition: sol.hpp:12390
Definition: sol.hpp:25191
Definition: sol.hpp:19515
Definition: sol.hpp:18990
Definition: sol.hpp:18383
SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t< F, T & > and_then(F &&f) &&
Definition: sol.hpp:6337
Definition: sol.hpp:11437
Definition: sol.hpp:23643
optional< T > or_else(F &&f) const &
Definition: sol.hpp:5471
Definition: sol.hpp:17187
constexpr detail::invoke_result_t< F, const T & > and_then(F &&f) const &
Definition: sol.hpp:5333
Definition: sol.hpp:28787
SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t< F, T & > and_then(F &&f) &
Definition: sol.hpp:6327
Definition: sol.hpp:21441
Definition: sol.hpp:19162
constexpr detail::invoke_result_t< F, const T & > and_then(F &&f) const &&
Definition: sol.hpp:6358
Definition: sol.hpp:11453
Definition: sol.hpp:11474
Definition: sol.hpp:17648
optional & operator=(nullopt_t) noexcept
Definition: sol.hpp:5756
Definition: sol.hpp:19346
optional take() const &
take
Definition: sol.hpp:6649
Definition: sol.hpp:21417
Definition: sol.hpp:10814
Definition: sol.hpp:19617
Definition: sol.hpp:25433
optional take() const &
take
Definition: sol.hpp:5636
Definition: lobject.h:113
void swap(optional &rhs) noexcept(std::is_nothrow_move_constructible< T >::value &&detail::is_nothrow_swappable< T >::value)
Definition: sol.hpp:5866
SOL_TL_OPTIONAL_11_CONSTEXPR optional(detail::enable_if_t< std::is_constructible< T, std::initializer_list< U > &, Args &&... >::value, in_place_t >, std::initializer_list< U > il, Args &&... args)
Definition: sol.hpp:5691
Definition: sol.hpp:21429
Definition: sol.hpp:19485
Definition: sol.hpp:21453
Definition: sol.hpp:10940
An exception for when an optional is accessed through specific methods while it is not engaged...
Definition: sol.hpp:5225
optional take() &
Definition: sol.hpp:6642
optional take() &
Definition: sol.hpp:5629
SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) &&
disjunction
Definition: sol.hpp:6607
constexpr optional(const optional< U > &rhs)
Definition: sol.hpp:6703
constexpr optional(detail::enable_if_t< std::is_constructible< T, Args... >::value, in_place_t >, Args &&... args)
Definition: sol.hpp:5684
Definition: sol.hpp:21627
Definition: sol.hpp:22840
SOL_TL_OPTIONAL_11_CONSTEXPR T * operator->()
Definition: sol.hpp:5893
SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) &
disjunction
Definition: sol.hpp:6619
constexpr optional< typename std::decay< U >::type > conjunction(U &&u) const
Definition: sol.hpp:5577
Definition: sol.hpp:23673
Definition: sol.hpp:13068
U map_or(F &&f, U &&u) &&
map_or
Definition: sol.hpp:6530
Definition: sol.hpp:20541
Definition: sol.hpp:27235
Definition: sol.hpp:10894
SOL_TL_OPTIONAL_11_CONSTEXPR T & value()
Definition: sol.hpp:6809
Definition: sol.hpp:26938
Definition: sol.hpp:10789
Definition: sol.hpp:21633
Definition: sol.hpp:11460
SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional &&rhs) &&
disjunction
Definition: sol.hpp:5616
constexpr optional() noexcept
Definition: sol.hpp:6675
U map_or(F &&f, U &&u) const &&
map_or
Definition: sol.hpp:5530
optional & operator=(nullopt_t) noexcept
Definition: sol.hpp:6712
optional< T > or_else(F &&f) const &&
Definition: sol.hpp:5488
constexpr T & value_or(U &&u) const
Definition: sol.hpp:6833
optional< T > or_else(F &&f) const &
Definition: sol.hpp:6484
detail::invoke_result_t< U > map_or_else(F &&f, U &&u) const &
Definition: sol.hpp:5561
Definition: sol.hpp:16947
Definition: sol.hpp:21525
Definition: sol.hpp:15682
constexpr optional(nullopt_t) noexcept
ctor_empty
Definition: sol.hpp:6679
constexpr optional< typename std::decay< U >::type > conjunction(U &&u) const
Definition: sol.hpp:6590
Definition: sol.hpp:28632
Definition: sol.hpp:12375
SOL_TL_OPTIONAL_11_CONSTEXPR const T & value() const
Definition: sol.hpp:6820
constexpr optional(U &&u)
Definition: sol.hpp:6697
Definition: sol.hpp:21465
Definition: sol.hpp:10746
detail::invoke_result_t< U > map_or_else(F &&f, U &&u) const &&
Definition: sol.hpp:5570
optional & operator=(const optional< U > &rhs)
Definition: sol.hpp:6739
Definition: sol.hpp:10775
Definition: sol.hpp:13990
Definition: sol.hpp:21513
SOL_TL_OPTIONAL_11_CONSTEXPR T && operator*() &&
Definition: sol.hpp:5912
Definition: sol.hpp:12398
Definition: sol.hpp:10727
Definition: sol.hpp:17922
Definition: sol.hpp:28236
void reset() noexcept
Destroys the stored value if one exists, making the optional empty.
Definition: sol.hpp:6839
Definition: sol.hpp:13360
Definition: sol.hpp:19062
Definition: sol.hpp:23662
constexpr bool has_value() const noexcept
Definition: sol.hpp:5925
Definition: sol.hpp:21477
Definition: sol.hpp:23628
optional< T > or_else(F &&f) &&
Definition: sol.hpp:5454
constexpr optional disjunction(optional &&rhs) const &
disjunction
Definition: sol.hpp:6624
Definition: sol.hpp:11447
Definition: sol.hpp:17659
Definition: sol.hpp:15637
optional & operator=(U &&u)
Definition: sol.hpp:6728
optional & operator=(optional< U > &&rhs)
Definition: sol.hpp:5822
constexpr optional(nullopt_t) noexcept
ctor_empty
Definition: sol.hpp:5665
Definition: sol.hpp:11444
optional< T > SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) &&
Definition: sol.hpp:5464
SOL_TL_OPTIONAL_11_CONSTEXPR T && value() &&
Definition: sol.hpp:5959
Definition: sol.hpp:21320
optional< T > SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) &
Calls f if the optional is empty std::invoke_result_t<F> must be void or convertible to optional<T>...
Definition: sol.hpp:5437
SOL_TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) &&
value_or
Definition: sol.hpp:5992
T & emplace(Args &&... args)
Definition: sol.hpp:5843
Definition: sol.hpp:18150
optional(const optional< U > &rhs)
Definition: sol.hpp:5721
Definition: sol.hpp:18959
Definition: sol.hpp:21549
Definition: sol.hpp:15760
constexpr optional disjunction(optional &&rhs) const &
disjunction
Definition: sol.hpp:5611
SOL_TL_OPTIONAL_11_CONSTEXPR T & value() &
Definition: sol.hpp:5938
Definition: sol.hpp:23444
Definition: sol.hpp:10936
Definition: sol.hpp:25193
Definition: sol.hpp:21289
optional< T > SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) &&
Definition: sol.hpp:6477
Definition: sol.hpp:10934
detail::invoke_result_t< U > map_or_else(F &&f, U &&u) const &
Definition: sol.hpp:6574
Used to represent an optional with no data; essentially a bool.
Definition: sol.hpp:4704
Definition: sol.hpp:17609
Definition: sol.hpp:19398
SOL_TL_OPTIONAL_11_CONSTEXPR const T & value() const &
Definition: sol.hpp:5949
constexpr const T * operator->() const
Definition: sol.hpp:5887
detail::invoke_result_t< U > map_or_else(F &&f, U &&u) &
Maps the stored value with f if there is one, otherwise calls u and returns the result.
Definition: sol.hpp:5545
constexpr T value_or(U &&u) const &
Definition: sol.hpp:5985
Definition: sol.hpp:19127
Definition: sol.hpp:19635
optional< T > SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F &&f) &
Calls f if the optional is empty std::invoke_result_t<F> must be void or convertible to optional<T>...
Definition: sol.hpp:6450
Definition: sol.hpp:21393
Definition: sol.hpp:12304
U map_or(F &&f, U &&u) &
Maps the stored value with f if there is one, otherwise returns u.
Definition: sol.hpp:5511
Definition: sol.hpp:21345
U map_or(F &&f, U &&u) const &&
map_or
Definition: sol.hpp:6543
constexpr optional disjunction(const optional &rhs) const &
disjunction
Definition: sol.hpp:5589
Definition: sol.hpp:23448
constexpr bool has_value() const noexcept
Definition: sol.hpp:6796
Definition: sol.hpp:26810
const char * what() const noexcept override
Returns a pointer to a null-terminated string containing the reason for the exception.
Definition: sol.hpp:5230
SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional &rhs) &
Definition: sol.hpp:5584
Definition: sol.hpp:21303
Definition: sol.hpp:11434
Definition: sol.hpp:11458
Definition: sol.hpp:26936