From 5034bd7980deccbe0dddf1de3c14063cfa626719 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Thu, 4 Feb 2016 20:16:53 -0500 Subject: [PATCH] Benchmarking will be done in a separate repository, alongside other frameworks. --- .gitmodules | 2 +- bench.cpp | 17 ------- bench_cpp_function.hpp | 92 ------------------------------------ bench_get.hpp | 59 ----------------------- bench_lua_function.hpp | 92 ------------------------------------ bench_set.hpp | 55 --------------------- bench_usertype.hpp | 105 ----------------------------------------- sol/function.hpp | 6 +-- sol/function_types.hpp | 30 ++++++------ sol/resolve.hpp | 4 +- sol/stack.hpp | 8 ++-- sol/table_core.hpp | 2 +- sol/traits.hpp | 3 ++ sol/tuple.hpp | 3 ++ 14 files changed, 32 insertions(+), 446 deletions(-) delete mode 100644 bench.cpp delete mode 100644 bench_cpp_function.hpp delete mode 100644 bench_get.hpp delete mode 100644 bench_lua_function.hpp delete mode 100644 bench_set.hpp delete mode 100644 bench_usertype.hpp diff --git a/.gitmodules b/.gitmodules index 1c1a2167..570fde0f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "Catch"] path = Catch - url = https://github.com/philsquared/Catch.git + url = https://github.com/philsquared/Catch.git \ No newline at end of file diff --git a/bench.cpp b/bench.cpp deleted file mode 100644 index 4a778547..00000000 --- a/bench.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "bench_cpp_function.hpp" -#include "bench_lua_function.hpp" -#include "bench_get.hpp" -#include "bench_set.hpp" -#include "bench_usertype.hpp" -#include "nonius/nonius.h++" - -int main( int argc, char* argv[] ) { - using namespace std::literals::string_literals; - std::string configurationname = argv[ 1 ]; - std::string platformname = argv[ 2 ]; - bench_lua_function( "bench/", configurationname, platformname ); - bench_cpp_function( "bench/", configurationname, platformname ); - bench_get( "bench/", configurationname, platformname ); - bench_set( "bench/", configurationname, platformname ); - bench_usertype( "bench/", configurationname, platformname ); -} diff --git a/bench_cpp_function.hpp b/bench_cpp_function.hpp deleted file mode 100644 index 860a856f..00000000 --- a/bench_cpp_function.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once - -#include "sol.hpp" -#include "nonius/nonius.h++" - -static sol::state prepare_cpp_function_state( ) { - sol::state lua; - lua.set_function( "r", - [ ] ( ) { - return 1 + 1; - } - ); - return lua; -} - -struct sol_protected_function_result_cpp_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_cpp_function_state( ); - auto measurement = [ & ] ( int run_index ) { - sol::protected_function r = lua[ "r" ]; - int value = r( ); - return value; - }; - meter.measure( measurement ); - } -}; - -struct sol_protected_call_cpp_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_cpp_function_state( ); - auto measurement = [ & ] ( int run_index ) { - sol::protected_function r = lua[ "r" ]; - int value = r.call( ); - return value; - }; - meter.measure( measurement ); - } -}; - -struct sol_function_result_cpp_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_cpp_function_state( ); - auto measurement = [ & ] ( int run_index ) { - sol::function r = lua[ "r" ]; - int value = r( ); - return value; - }; - meter.measure( measurement ); - } -}; - -struct sol_call_cpp_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_cpp_function_state( ); - auto measurement = [ & ] ( int run_index ) { - sol::function r = lua[ "r" ]; - int value = r.call( ); - return value; - }; - meter.measure( measurement ); - } -}; - -struct c_call_cpp_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_cpp_function_state( ); - lua_State* L = lua.lua_state( ); - auto measurement = [ & ] ( int run_index ) { - lua_getglobal( L, "r" ); - lua_call( L, 0, 1 ); - int value = (int)lua_tonumber( L, -1 ); - lua_pop( L, 1 ); - return value; - }; - meter.measure( measurement ); - } -}; - -void bench_cpp_function( const std::string& dir, std::string& configurationname, const std::string& platformname ) { - nonius::configuration cfg; - cfg.output_file = dir + "sol.functions (C++ source) - " + configurationname + " " + platformname + ".html"; - cfg.title = "sol::function (C++ source) (" + configurationname + " " + platformname + ")"; - cfg.samples = 100; - nonius::benchmark benchmarks [] = { - nonius::benchmark( "protected_function - function_result", sol_protected_function_result_cpp_bench( ) ), - nonius::benchmark( "protected_function - call<>", sol_protected_call_cpp_bench( ) ), - nonius::benchmark( "function - function_result", sol_function_result_cpp_bench( ) ), - nonius::benchmark( "function - call<>", sol_call_cpp_bench( ) ), - nonius::benchmark( "plain C", c_call_cpp_bench( ) ), - }; - nonius::go( cfg, std::begin( benchmarks ), std::end( benchmarks ), nonius::html_reporter( ) ); -} diff --git a/bench_get.hpp b/bench_get.hpp deleted file mode 100644 index 0946ee63..00000000 --- a/bench_get.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include "sol.hpp" -#include "nonius/nonius.h++" - -static sol::state prepare_get_state( ) { - sol::state lua; - lua.set( "r", 25 ); - return lua; -} - -struct sol_get_proxy_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_get_state( ); - auto measurement = [ & ] ( int run_index ) { - int value = lua[ "r" ]; - return value; - }; - meter.measure( measurement ); - } -}; - -struct sol_get_typed_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_get_state( ); - auto measurement = [ & ] ( int run_index ) { - int value = lua.get( "r" ); - return value; - }; - meter.measure( measurement ); - } -}; - -struct c_get_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_get_state( ); - lua_State* L = lua.lua_state( ); - auto measurement = [ & ] ( int run_index ) { - lua_getglobal( L, "r" ); - int value = (int)lua_tonumber( L, -1 ); - lua_pop( L, 1 ); - return value; - }; - meter.measure( measurement ); - } -}; - -void bench_get( const std::string& dir, std::string& configurationname, const std::string& platformname ) { - nonius::configuration cfg; - cfg.output_file = dir + "sol.get - " + configurationname + " " + platformname + ".html"; - cfg.title = "sol get (" + configurationname + " " + platformname + ")"; - cfg.samples = 100; - nonius::benchmark benchmarks [] = { - nonius::benchmark( "sol - proxy get", sol_get_proxy_bench( ) ), - nonius::benchmark( "sol - typed get", sol_get_typed_bench( ) ), - nonius::benchmark( "plain C", c_get_bench( ) ), - }; - nonius::go( cfg, std::begin( benchmarks ), std::end( benchmarks ), nonius::html_reporter( ) ); -} diff --git a/bench_lua_function.hpp b/bench_lua_function.hpp deleted file mode 100644 index 06454cc7..00000000 --- a/bench_lua_function.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once - -#include "sol.hpp" -#include "nonius/nonius.h++" - -static sol::state prepare_lua_function_state( ) { - sol::state lua; - lua.script( R"( -function r () - return 1 + 1 -end -)" ); - return lua; -} - -struct sol_function_result_lua_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_lua_function_state( ); - auto measurement = [ & ] ( int run_index ) { - sol::function r = lua[ "r" ]; - int value = r( ); - return value; - }; - meter.measure( measurement ); - } -}; - -struct sol_call_lua_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_lua_function_state( ); - auto measurement = [ & ] ( int run_index ) { - sol::function r = lua[ "r" ]; - int value = r.call( ); - return value; - }; - meter.measure( measurement ); - } -}; - -struct sol_protected_function_result_lua_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_lua_function_state( ); - auto measurement = [ & ] ( int run_index ) { - sol::protected_function r = lua[ "r" ]; - int value = r( ); - return value; - }; - meter.measure( measurement ); - } -}; - -struct sol_protected_call_lua_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_lua_function_state( ); - auto measurement = [ & ] ( int run_index ) { - sol::protected_function r = lua[ "r" ]; - int value = r.call( ); - return value; - }; - meter.measure( measurement ); - } -}; - -struct c_direct_lua_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_lua_function_state( ); - lua_State* L = lua.lua_state( ); - auto measurement = [ & ] ( int run_index ) { - lua_getglobal( L, "r" ); - lua_call( L, 0, 1 ); - int value = (int)lua_tonumber( L, -1 ); - lua_pop( L, 1 ); - return value; - }; - meter.measure( measurement ); - } -}; - -void bench_lua_function( const std::string& dir, std::string& configurationname, const std::string& platformname ) { - nonius::configuration cfg; - cfg.output_file = dir + "sol.functions (lua source) - " + configurationname + " " + platformname + ".html"; - cfg.title = "sol::function (lua source) (" + configurationname + " " + platformname + ")"; - cfg.samples = 100; - nonius::benchmark benchmarks[] = { - nonius::benchmark("function - function_result", sol_function_result_lua_bench()), - nonius::benchmark("function - call<>", sol_call_lua_bench()), - nonius::benchmark("protected_function - function_result", sol_protected_function_result_lua_bench()), - nonius::benchmark("protected_function - call<>", sol_protected_call_lua_bench()), - nonius::benchmark( "plain C", c_direct_lua_bench( ) ), - }; - nonius::go( cfg, std::begin( benchmarks ), std::end( benchmarks ), nonius::html_reporter( ) ); -} diff --git a/bench_set.hpp b/bench_set.hpp deleted file mode 100644 index c25987f9..00000000 --- a/bench_set.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include "sol.hpp" -#include "nonius/nonius.h++" - -static sol::state prepare_set_state( ) { - sol::state lua; - lua.set( "r", 25 ); - return lua; -} - -struct sol_set_proxy_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_set_state( ); - auto measurement = [ & ] ( int run_index ) { - lua[ "r" ] = 40; - }; - meter.measure( measurement ); - } -}; - -struct sol_set_typed_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_set_state( ); - auto measurement = [ & ] ( int run_index ) { - lua.set( "r", 40 ); - }; - meter.measure( measurement ); - } -}; - -struct c_set_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_set_state( ); - lua_State* L = lua.lua_state( ); - auto measurement = [ & ] ( int run_index ) { - lua_pushinteger( L, 40 ); - lua_setglobal( L, "r" ); - }; - meter.measure( measurement ); - } -}; - -void bench_set( const std::string& dir, std::string& configurationname, const std::string& platformname ) { - nonius::configuration cfg; - cfg.output_file = dir + "sol.set - " + configurationname + " " + platformname + ".html"; - cfg.title = "sol set (" + configurationname + " " + platformname + ")"; - cfg.samples = 100; - nonius::benchmark benchmarks [] = { - nonius::benchmark( "sol - proxy set", sol_set_proxy_bench( ) ), - nonius::benchmark( "sol - typed set", sol_set_typed_bench( ) ), - nonius::benchmark( "plain C", c_set_bench( ) ), - }; - nonius::go( cfg, std::begin( benchmarks ), std::end( benchmarks ), nonius::html_reporter( ) ); -} diff --git a/bench_usertype.hpp b/bench_usertype.hpp deleted file mode 100644 index 26a8cb23..00000000 --- a/bench_usertype.hpp +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once - -#include "sol.hpp" -#include "nonius/nonius.h++" - -struct woof { - int var; - - int func( int x ) { - return var + x; - } - - int operator + (int x) const { - return var + x; - } -}; - -static sol::state prepare_usertype_state( ) { - sol::state lua; - lua.new_usertype( "woof", - "var", &woof::var, - "func", &woof::func, - sol::meta_function::addition, &woof::operator+ ); - lua.script( R"( -r = woof:new() -)" ); - return lua; -} - -struct sol_usertype_special_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_usertype_state( ); - auto measurement = [ & ] ( int run_index ) { - lua.script("x = r + 2"); - }; - meter.measure( measurement ); - } -}; - -struct sol_usertype_regular_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_usertype_state( ); - auto measurement = [ & ] ( int run_index ) { - lua.script("x = r:func( 2 )"); - }; - meter.measure( measurement ); - } -}; - -struct sol_usertype_variable_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_usertype_state( ); - auto measurement = [ & ] ( int run_index ) { - lua.script("x = r.var + 2"); - }; - meter.measure( measurement ); - } -}; - -struct c_usertype_special_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_usertype_state( ); - lua_State* L = lua.lua_state( ); - auto measurement = [ & ] ( int run_index ) { - - }; - meter.measure( measurement ); - } -}; - -struct c_usertype_regular_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_usertype_state( ); - lua_State* L = lua.lua_state( ); - auto measurement = [ & ] ( int run_index ) { - }; - meter.measure( measurement ); - } -}; - -struct c_usertype_variable_bench { - void operator () ( nonius::chronometer meter ) const { - sol::state lua = prepare_usertype_state( ); - lua_State* L = lua.lua_state( ); - auto measurement = [ & ] ( int run_index ) { - }; - meter.measure( measurement ); - } -}; - -void bench_usertype( const std::string& dir, std::string& configurationname, const std::string& platformname ) { - nonius::configuration cfg; - cfg.output_file = dir + "sol.usertype - " + configurationname + " " + platformname + ".html"; - cfg.title = "sol usertype (" + configurationname + " " + platformname + ")"; - cfg.samples = 100; - nonius::benchmark benchmarks [] = { - nonius::benchmark( "sol - usertype special", sol_usertype_special_bench( ) ), - nonius::benchmark( "sol - usertype regular", sol_usertype_regular_bench( ) ), - nonius::benchmark( "sol - usertype variable", sol_usertype_variable_bench( ) ), - //nonius::benchmark( "plain C - usertype special", c_usertype_special_bench( ) ), - //nonius::benchmark( "plain C - usertype regular", c_usertype_regular_bench( ) ), - //nonius::benchmark( "plain C - usertype variable", c_usertype_variable_bench( ) ), - }; - nonius::go( cfg, std::begin( benchmarks ), std::end( benchmarks ), nonius::html_reporter( ) ); -} diff --git a/sol/function.hpp b/sol/function.hpp index 0e18830a..28ca7e3c 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -224,7 +224,7 @@ namespace stack { template struct pusher> { - template::type> + template> static void set_memfx(types t, lua_State* L, Fx&& fx) { typedef Decay>> raw_fx_t; typedef R(* fx_ptr_t)(Args...); @@ -287,7 +287,7 @@ struct pusher> { template static void set_reference_fx(std::false_type, lua_State* L, Fx&& fx, T&& obj) { - typedef typename std::remove_pointer>::type clean_fx; + typedef std::remove_pointer_t> clean_fx; std::unique_ptr sptr(new member_function>(std::forward(obj), std::forward(fx))); return set_fx(L, std::move(sptr)); } @@ -373,7 +373,7 @@ template struct getter> { typedef function_traits fx_t; typedef typename fx_t::args_type args_t; - typedef typename tuple_types::type ret_t; + typedef typename tuple_types_t ret_t; template static std::function get_std_func(types, types, lua_State* L, int index = -1) { diff --git a/sol/function_types.hpp b/sol/function_types.hpp index 5fa9c280..d70bff86 100644 --- a/sol/function_types.hpp +++ b/sol/function_types.hpp @@ -77,7 +77,7 @@ struct functor { }; template -struct functor::value>::type> { +struct functor::value>> { typedef member_traits traits_type; typedef typename traits_type::args_type args_type; typedef typename traits_type::return_type return_type; @@ -109,11 +109,11 @@ struct functor -struct functor::value || std::is_class::value>::type> { +struct functor::value || std::is_class::value>> { typedef member_traits traits_type; typedef remove_one_type args_type; typedef typename traits_type::return_type return_type; - typedef typename std::conditional::value || std::is_class::value, Func, typename std::add_pointer::type>::type function_type; + typedef std::conditional_t::value || std::is_class::value, Func, std::add_pointer_t> function_type; T* item; function_type invocation; @@ -157,7 +157,7 @@ public: template struct static_function { - typedef typename std::remove_pointer::type>::type function_type; + typedef std::remove_pointer_t> function_type; typedef function_traits traits_type; template @@ -175,7 +175,7 @@ struct static_function { template static int typed_call(types, types ta, function_type* fx, lua_State* L) { - typedef typename return_type::type return_type; + typedef return_type_t return_type; typedef decltype(stack::call(L, 0, types(), ta, fx)) ret_t; ret_t r = stack::call(L, 0, types(), ta, fx); int nargs = static_cast(sizeof...(Args)); @@ -197,7 +197,7 @@ struct static_function { template struct static_member_function { - typedef typename std::remove_pointer::type>::type function_type; + typedef std::remove_pointer_t> function_type; typedef function_traits traits_type; template @@ -216,7 +216,7 @@ struct static_member_function { template static int typed_call(types tr, types ta, T& item, function_type& ifx, lua_State* L) { - typedef typename return_type::type return_type; + typedef return_type_t return_type; auto fx = [&item, &ifx](Args&&... args) -> return_type { return (item.*ifx)(std::forward(args)...); }; return_type r = stack::call(L, 0, tr, ta, fx); int nargs = static_cast(sizeof...(Args)); @@ -369,7 +369,7 @@ struct functor_function : public base_function { template struct member_function : public base_function { - typedef typename std::remove_pointer>::type function_type; + typedef std::remove_pointer_t> function_type; typedef function_return_t return_type; typedef function_args_t args_type; struct functor { @@ -420,8 +420,8 @@ struct member_function : public base_function { template struct usertype_function_core : public base_function { - typedef typename std::remove_pointer::type T; - typedef typename std::remove_pointer::type>::type function_type; + typedef std::remove_pointer_t T; + typedef std::remove_pointer_t> function_type; typedef detail::functor fx_t; typedef typename fx_t::traits_type traits_type; typedef typename fx_t::args_type args_type; @@ -433,7 +433,7 @@ struct usertype_function_core : public base_function { usertype_function_core(FxArgs&&... fxargs): fx(std::forward(fxargs)...) {} template> - typename std::enable_if::value, int>::type push(lua_State* L, Return&& r) { + std::enable_if_t::value, int> push(lua_State* L, Return&& r) { if(detail::get_ptr(r) == fx.item) { // push nothing // note that pushing nothing with the ':' @@ -449,7 +449,7 @@ struct usertype_function_core : public base_function { } template> - typename std::enable_if::value, int>::type push(lua_State* L, Return&& r) { + std::enable_if_t::value, int> push(lua_State* L, Return&& r) { return stack::push(L, std::forward(r)); } @@ -486,7 +486,7 @@ struct usertype_function_core : public base_function { template struct usertype_function : public usertype_function_core { typedef usertype_function_core base_t; - typedef typename std::remove_pointer::type T; + typedef std::remove_pointer_t T; typedef typename base_t::traits_type traits_type; typedef typename base_t::args_type args_type; typedef typename base_t::return_type return_type; @@ -515,7 +515,7 @@ struct usertype_function : public usertype_function_core { template struct usertype_variable_function : public usertype_function_core { typedef usertype_function_core base_t; - typedef typename std::remove_pointer::type T; + typedef std::remove_pointer_t T; typedef typename base_t::traits_type traits_type; typedef typename base_t::args_type args_type; typedef typename base_t::return_type return_type; @@ -554,7 +554,7 @@ struct usertype_variable_function : public usertype_function_core template struct usertype_indexing_function : public usertype_function_core { typedef usertype_function_core base_t; - typedef typename std::remove_pointer::type T; + typedef std::remove_pointer_t T; typedef typename base_t::traits_type traits_type; typedef typename base_t::args_type args_type; typedef typename base_t::return_type return_type; diff --git a/sol/resolve.hpp b/sol/resolve.hpp index 4299a85b..d6e27ec8 100644 --- a/sol/resolve.hpp +++ b/sol/resolve.hpp @@ -27,7 +27,7 @@ namespace sol { namespace detail { -template(Args...)>::type> +template(Args...)>> inline auto resolve_i(types, F&&) -> R(Unqualified::*)(Args...) { using Sig = R(Args...); typedef Unqualified Fu; @@ -51,7 +51,7 @@ inline auto resolve_i(types<>, F&& f) -> decltype(resolve_f(has_deducible_signat return resolve_f(has_deducible_signature {}, std::forward(f)); } -template::type> +template> inline auto resolve_i(types, F&& f) -> decltype( resolve_i(types(), std::forward(f))) { return resolve_i(types(), std::forward(f)); } diff --git a/sol/stack.hpp b/sol/stack.hpp index 10366409..c1c60856 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -248,7 +248,7 @@ struct getter { template, std::is_unsigned> = 0> static U get(lua_State* L, int index = -1) { - typedef typename std::make_signed::type signed_int; + typedef std::make_signed_t signed_int; return static_cast(stack::get(L, index)); } @@ -373,7 +373,7 @@ struct pusher { template, std::is_unsigned> = 0> static int push(lua_State* L, const T& value) { - typedef typename std::make_signed::type signed_int; + typedef std::make_signed_t signed_int; return stack::push(L, static_cast(value)); } @@ -526,7 +526,7 @@ struct pusher> { namespace detail { template inline int push_as_upvalues(lua_State* L, T& item) { - typedef typename std::decay::type TValue; + typedef std::decay_t TValue; const static std::size_t itemsize = sizeof(TValue); const static std::size_t voidsize = sizeof(void*); const static std::size_t voidsizem1 = voidsize - 1; @@ -579,7 +579,7 @@ struct check_arguments { } }; -template ::value>::type> +template ::value>> inline R call(lua_State* L, int start, indices, types, types ta, Fx&& fx, FxArgs&&... args) { const int stacksize = lua_gettop(L); const int firstargument = static_cast(start + stacksize - std::max(sizeof...(Args)-1, static_cast(0))); diff --git a/sol/table_core.hpp b/sol/table_core.hpp index a8f5cd10..a086ff85 100644 --- a/sol/table_core.hpp +++ b/sol/table_core.hpp @@ -207,7 +207,7 @@ public: } private: - template::type> + template> void set_fx( types, Key&& key, Fx&& fx ) { set_resolved_function( std::forward( key ), std::forward( fx ) ); } diff --git a/sol/traits.hpp b/sol/traits.hpp index 5d74e4bd..a64989da 100644 --- a/sol/traits.hpp +++ b/sol/traits.hpp @@ -123,6 +123,9 @@ struct return_type<> { typedef void type; }; +template +using return_type_t = typename return_type::type; + template using ReturnTypeOr = typename std::conditional<(sizeof...(Tn) < 1), Empty, typename return_type::type>::type; diff --git a/sol/tuple.hpp b/sol/tuple.hpp index 431c8de6..22863cb4 100644 --- a/sol/tuple.hpp +++ b/sol/tuple.hpp @@ -85,6 +85,9 @@ struct tuple_types : types {}; template struct tuple_types> : types {}; +template +using tuple_types_t = typename tuple_types::type; + template struct remove_one_type : detail::chop_one {};