Benchmarking will be done in a separate repository, alongside other frameworks.

This commit is contained in:
ThePhD 2016-02-04 20:16:53 -05:00
parent a9c5bfc0b8
commit 5034bd7980
14 changed files with 32 additions and 446 deletions

2
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "Catch"]
path = Catch
url = https://github.com/philsquared/Catch.git
url = https://github.com/philsquared/Catch.git

View File

@ -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 );
}

View File

@ -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<int>( );
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<int>( );
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( ) );
}

View File

@ -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<int>( "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( ) );
}

View File

@ -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<int>( );
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<int>( );
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( ) );
}

View File

@ -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( ) );
}

View File

@ -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>( "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( ) );
}

View File

@ -224,7 +224,7 @@ namespace stack {
template<typename... Sigs>
struct pusher<function_sig<Sigs...>> {
template<typename R, typename... Args, typename Fx, typename = typename std::result_of<Fx(Args...)>::type>
template<typename R, typename... Args, typename Fx, typename = std::result_of_t<Fx(Args...)>>
static void set_memfx(types<R(Args...)> t, lua_State* L, Fx&& fx) {
typedef Decay<Unwrap<Unqualified<Fx>>> raw_fx_t;
typedef R(* fx_ptr_t)(Args...);
@ -287,7 +287,7 @@ struct pusher<function_sig<Sigs...>> {
template<typename Fx, typename T>
static void set_reference_fx(std::false_type, lua_State* L, Fx&& fx, T&& obj) {
typedef typename std::remove_pointer<Decay<Fx>>::type clean_fx;
typedef std::remove_pointer_t<Decay<Fx>> clean_fx;
std::unique_ptr<base_function> sptr(new member_function<clean_fx, Unqualified<T>>(std::forward<T>(obj), std::forward<Fx>(fx)));
return set_fx<Fx>(L, std::move(sptr));
}
@ -373,7 +373,7 @@ template<typename Signature>
struct getter<std::function<Signature>> {
typedef function_traits<Signature> fx_t;
typedef typename fx_t::args_type args_t;
typedef typename tuple_types<typename fx_t::return_type>::type ret_t;
typedef typename tuple_types_t<typename fx_t::return_type> ret_t;
template<typename... FxArgs, typename... Ret>
static std::function<Signature> get_std_func(types<FxArgs...>, types<Ret...>, lua_State* L, int index = -1) {

View File

@ -77,7 +77,7 @@ struct functor {
};
template<typename T, typename Func>
struct functor<T, Func, typename std::enable_if<std::is_member_object_pointer<Func>::value>::type> {
struct functor<T, Func, std::enable_if_t<std::is_member_object_pointer<Func>::value>> {
typedef member_traits<Func> traits_type;
typedef typename traits_type::args_type args_type;
typedef typename traits_type::return_type return_type;
@ -109,11 +109,11 @@ struct functor<T, Func, typename std::enable_if<std::is_member_object_pointer<Fu
};
template<typename T, typename Func>
struct functor<T, Func, typename std::enable_if<std::is_function<Func>::value || std::is_class<Func>::value>::type> {
struct functor<T, Func, std::enable_if_t<std::is_function<Func>::value || std::is_class<Func>::value>> {
typedef member_traits<Func> traits_type;
typedef remove_one_type<typename traits_type::args_type> args_type;
typedef typename traits_type::return_type return_type;
typedef typename std::conditional<std::is_pointer<Func>::value || std::is_class<Func>::value, Func, typename std::add_pointer<Func>::type>::type function_type;
typedef std::conditional_t<std::is_pointer<Func>::value || std::is_class<Func>::value, Func, std::add_pointer_t<Func>> function_type;
T* item;
function_type invocation;
@ -157,7 +157,7 @@ public:
template<typename Function>
struct static_function {
typedef typename std::remove_pointer<typename std::decay<Function>::type>::type function_type;
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
typedef function_traits<function_type> traits_type;
template<typename... Args>
@ -175,7 +175,7 @@ struct static_function {
template<typename... Ret, typename... Args>
static int typed_call(types<Ret...>, types<Args...> ta, function_type* fx, lua_State* L) {
typedef typename return_type<Ret...>::type return_type;
typedef return_type_t<Ret...> return_type;
typedef decltype(stack::call(L, 0, types<return_type>(), ta, fx)) ret_t;
ret_t r = stack::call(L, 0, types<return_type>(), ta, fx);
int nargs = static_cast<int>(sizeof...(Args));
@ -197,7 +197,7 @@ struct static_function {
template<typename T, typename Function>
struct static_member_function {
typedef typename std::remove_pointer<typename std::decay<Function>::type>::type function_type;
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
typedef function_traits<function_type> traits_type;
template<typename... Args>
@ -216,7 +216,7 @@ struct static_member_function {
template<typename... Ret, typename... Args>
static int typed_call(types<Ret...> tr, types<Args...> ta, T& item, function_type& ifx, lua_State* L) {
typedef typename return_type<Ret...>::type return_type;
typedef return_type_t<Ret...> return_type;
auto fx = [&item, &ifx](Args&&... args) -> return_type { return (item.*ifx)(std::forward<Args>(args)...); };
return_type r = stack::call(L, 0, tr, ta, fx);
int nargs = static_cast<int>(sizeof...(Args));
@ -369,7 +369,7 @@ struct functor_function : public base_function {
template<typename Function, typename T>
struct member_function : public base_function {
typedef typename std::remove_pointer<Decay<Function>>::type function_type;
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
typedef function_return_t<function_type> return_type;
typedef function_args_t<function_type> args_type;
struct functor {
@ -420,8 +420,8 @@ struct member_function : public base_function {
template<typename Function, typename Tp>
struct usertype_function_core : public base_function {
typedef typename std::remove_pointer<Tp>::type T;
typedef typename std::remove_pointer<typename std::decay<Function>::type>::type function_type;
typedef std::remove_pointer_t<Tp> T;
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
typedef detail::functor<T, function_type> 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>(fxargs)...) {}
template<typename Return, typename Raw = Unqualified<Return>>
typename std::enable_if<std::is_same<T, Raw>::value, int>::type push(lua_State* L, Return&& r) {
std::enable_if_t<std::is_same<T, Raw>::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 Return, typename Raw = Unqualified<Return>>
typename std::enable_if<!std::is_same<T, Raw>::value, int>::type push(lua_State* L, Return&& r) {
std::enable_if_t<!std::is_same<T, Raw>::value, int> push(lua_State* L, Return&& r) {
return stack::push(L, std::forward<Return>(r));
}
@ -486,7 +486,7 @@ struct usertype_function_core : public base_function {
template<typename Function, typename Tp>
struct usertype_function : public usertype_function_core<Function, Tp> {
typedef usertype_function_core<Function, Tp> base_t;
typedef typename std::remove_pointer<Tp>::type T;
typedef std::remove_pointer_t<Tp> 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<Function, Tp> {
template<typename Function, typename Tp>
struct usertype_variable_function : public usertype_function_core<Function, Tp> {
typedef usertype_function_core<Function, Tp> base_t;
typedef typename std::remove_pointer<Tp>::type T;
typedef std::remove_pointer_t<Tp> 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<Function, Tp>
template<typename Function, typename Tp>
struct usertype_indexing_function : public usertype_function_core<Function, Tp> {
typedef usertype_function_core<Function, Tp> base_t;
typedef typename std::remove_pointer<Tp>::type T;
typedef std::remove_pointer_t<Tp> 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;

View File

@ -27,7 +27,7 @@
namespace sol {
namespace detail {
template<typename R, typename... Args, typename F, typename = typename std::result_of<Unqualified<F>(Args...)>::type>
template<typename R, typename... Args, typename F, typename = std::result_of_t<Unqualified<F>(Args...)>>
inline auto resolve_i(types<R(Args...)>, F&&) -> R(Unqualified<F>::*)(Args...) {
using Sig = R(Args...);
typedef Unqualified<F> Fu;
@ -51,7 +51,7 @@ inline auto resolve_i(types<>, F&& f) -> decltype(resolve_f(has_deducible_signat
return resolve_f(has_deducible_signature<U> {}, std::forward<F>(f));
}
template<typename... Args, typename F, typename R = typename std::result_of<F&(Args...)>::type>
template<typename... Args, typename F, typename R = std::result_of_t<F&(Args...)>>
inline auto resolve_i(types<Args...>, F&& f) -> decltype( resolve_i(types<R(Args...)>(), std::forward<F>(f))) {
return resolve_i(types<R(Args...)>(), std::forward<F>(f));
}

View File

@ -248,7 +248,7 @@ struct getter {
template<typename U = T, EnableIf<std::is_integral<U>, std::is_unsigned<U>> = 0>
static U get(lua_State* L, int index = -1) {
typedef typename std::make_signed<U>::type signed_int;
typedef std::make_signed_t<U> signed_int;
return static_cast<U>(stack::get<signed_int>(L, index));
}
@ -373,7 +373,7 @@ struct pusher {
template<typename U = T, EnableIf<std::is_integral<U>, std::is_unsigned<U>> = 0>
static int push(lua_State* L, const T& value) {
typedef typename std::make_signed<T>::type signed_int;
typedef std::make_signed_t<T> signed_int;
return stack::push(L, static_cast<signed_int>(value));
}
@ -526,7 +526,7 @@ struct pusher<std::tuple<Args...>> {
namespace detail {
template<typename T>
inline int push_as_upvalues(lua_State* L, T& item) {
typedef typename std::decay<T>::type TValue;
typedef std::decay_t<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<false> {
}
};
template <bool checkargs = detail::default_check_arguments, std::size_t... I, typename R, typename... Args, typename Fx, typename... FxArgs, typename = typename std::enable_if<!std::is_void<R>::value>::type>
template <bool checkargs = detail::default_check_arguments, std::size_t... I, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
inline R call(lua_State* L, int start, indices<I...>, types<R>, types<Args...> ta, Fx&& fx, FxArgs&&... args) {
const int stacksize = lua_gettop(L);
const int firstargument = static_cast<int>(start + stacksize - std::max(sizeof...(Args)-1, static_cast<std::size_t>(0)));

View File

@ -207,7 +207,7 @@ public:
}
private:
template<typename R, typename... Args, typename Fx, typename Key, typename = typename std::result_of<Fx( Args... )>::type>
template<typename R, typename... Args, typename Fx, typename Key, typename = std::result_of_t<Fx( Args... )>>
void set_fx( types<R( Args... )>, Key&& key, Fx&& fx ) {
set_resolved_function<R( Args... )>( std::forward<Key>( key ), std::forward<Fx>( fx ) );
}

View File

@ -123,6 +123,9 @@ struct return_type<> {
typedef void type;
};
template <typename... Args>
using return_type_t = typename return_type<Args...>::type;
template <typename Empty, typename... Tn>
using ReturnTypeOr = typename std::conditional<(sizeof...(Tn) < 1), Empty, typename return_type<Tn...>::type>::type;

View File

@ -85,6 +85,9 @@ struct tuple_types : types<Args...> {};
template<typename... Args>
struct tuple_types<std::tuple<Args...>> : types<Args...> {};
template<typename... Args>
using tuple_types_t = typename tuple_types<Args...>::type;
template<typename Arg>
struct remove_one_type : detail::chop_one<Arg> {};