// Copyright Sebastian Jeckel 2014. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef REACT_COMMON_UTIL_H_INCLUDED #define REACT_COMMON_UTIL_H_INCLUDED #pragma once #include "react/detail/Defs.h" #include #include #include /***************************************/ REACT_IMPL_BEGIN /**************************************/ /////////////////////////////////////////////////////////////////////////////////////////////////// /// Unpack tuple - see /// http://stackoverflow.com/questions/687490/how-do-i-expand-a-tuple-into-variadic-template-functions-arguments /////////////////////////////////////////////////////////////////////////////////////////////////// template struct Apply { template static inline auto apply(F && f, T && t, A &&... a) -> decltype(Apply::apply(std::forward(f), std::forward(t), std::get(std::forward(t)), std::forward(a)...)) { return Apply::apply(std::forward(f), std::forward(t), std::get(std::forward(t)), std::forward(a)...); } }; template<> struct Apply<0> { template static inline auto apply(F && f, T &&, A &&... a) -> decltype(std::forward(f)(std::forward(a)...)) { return std::forward(f)(std::forward(a)...); } }; template inline auto apply(F && f, T && t) -> decltype(Apply::type>::value>::apply(std::forward(f), std::forward(t))) { return Apply::type>::value> ::apply(std::forward(f), std::forward(t)); } template struct ApplyMemberFn { template static inline auto apply(O obj, F f, T && t, A &&... a) -> decltype(ApplyMemberFn::apply(obj, f, std::forward(t), std::get(std::forward(t)), std::forward(a)...)) { return ApplyMemberFn::apply(obj, f, std::forward(t), std::get(std::forward(t)), std::forward(a)...); } }; template<> struct ApplyMemberFn<0> { template static inline auto apply(O obj, F f, T &&, A &&... a) -> decltype((obj->*f)(std::forward(a)...)) { return (obj->*f)(std::forward(a)...); } }; template inline auto applyMemberFn(O obj, F f, T&& t) -> decltype(ApplyMemberFn::type>::value>::apply(obj, f, std::forward(t))) { return ApplyMemberFn::type>::value> ::apply(obj, f, std::forward(t)); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// Helper to enable calling a function on each element of an argument pack. /// We can't do f(args) ...; because ... expands with a comma. /// But we can do nop_func(f(args) ...); /////////////////////////////////////////////////////////////////////////////////////////////////// template inline void pass(TArgs&& ...) {} /////////////////////////////////////////////////////////////////////////////////////////////////// // Identity (workaround to enable enable decltype()::X) /////////////////////////////////////////////////////////////////////////////////////////////////// template struct Identity { using Type = T; }; /////////////////////////////////////////////////////////////////////////////////////////////////// /// DontMove! /////////////////////////////////////////////////////////////////////////////////////////////////// struct DontMove {}; /////////////////////////////////////////////////////////////////////////////////////////////////// /// AddDummyArgWrapper /////////////////////////////////////////////////////////////////////////////////////////////////// template struct AddDummyArgWrapper { // Dummy int to make sure it calls the right ctor template AddDummyArgWrapper(int, FIn&& func) : MyFunc( std::forward(func) ) {} AddDummyArgWrapper(const AddDummyArgWrapper& other) = default; AddDummyArgWrapper(AddDummyArgWrapper&& other) : MyFunc( std::move(other.MyFunc) ) {} TRet operator()(TArg, TDepValues& ... args) { return MyFunc(args ...); } F MyFunc; }; template struct AddDummyArgWrapper { // Dummy int to make sure it calls the right ctor template AddDummyArgWrapper(int, FIn&& func) : MyFunc( std::forward(func) ) {} AddDummyArgWrapper(const AddDummyArgWrapper& other) = default; AddDummyArgWrapper(AddDummyArgWrapper&& other) : MyFunc( std::move(other.MyFunc) ) {} void operator()(TArg, TDepValues& ... args) { MyFunc(args ...); } F MyFunc; }; /////////////////////////////////////////////////////////////////////////////////////////////////// /// AddDefaultReturnValueWrapper /////////////////////////////////////////////////////////////////////////////////////////////////// template < typename F, typename TRet, TRet return_value > struct AddDefaultReturnValueWrapper { template AddDefaultReturnValueWrapper(FIn&& func) : MyFunc( std::forward(func) ) {} template TRet operator()(TArgs&& ... args) { MyFunc(std::forward(args) ...); return return_value; } F MyFunc; }; /****************************************/ REACT_IMPL_END /***************************************/ // Expand args by wrapping them in a dummy function // Use comma operator to replace potential void return value with 0 #define REACT_EXPAND_PACK(...) REACT_IMPL::pass((__VA_ARGS__ , 0) ...) #endif // REACT_COMMON_UTIL_H_INCLUDED