Skip to content

Instantly share code, notes, and snippets.

@ink19
Created February 12, 2021 08:28
Show Gist options
  • Save ink19/21539175950b1bebda2a1e842151de13 to your computer and use it in GitHub Desktop.
Save ink19/21539175950b1bebda2a1e842151de13 to your computer and use it in GitHub Desktop.
my impl invoke_result
#ifndef __INK_INVOKE_RESULT_HPP
#define __INK_INVOKE_RESULT_HPP
#include <type_traits>
namespace ink {
template<typename __Tp>
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<__Tp>>;
struct __failure_type{};
template<typename FuncType>
struct __is_mem_func : public std::false_type{};
template<typename _Tp, typename _Cp>
struct __is_mem_func<_Tp _Cp::*> : public std::is_function<_Tp>::type {};
template<typename FuncType>
struct __is_mem_obj : public std::false_type{};
template<typename _Tp, typename _Cp>
struct __is_mem_obj<_Tp _Cp::*> : public std::negation<typename std::is_function<_Tp>::type>::type {};
template<typename>
struct __mem_and_obj_type: public std::__failure_type{};
template<typename _Tp, typename _Cp>
struct __mem_and_obj_type<_Tp _Cp::*> {
typedef _Tp mem_type;
typedef _Cp obj_type;
};
// obj impl
template<typename MemType, typename ObjectType>
struct __mem_obj_ref_return_impl {
typedef decltype(std::declval<ObjectType>().*std::declval<MemType>()) type;
};
template<typename MemType, typename ObjectType>
struct __mem_obj_deref_return_impl {
typedef decltype((*std::declval<ObjectType>()).*std::declval<MemType>()) type;
};
// obj func
template<typename FuncType, typename ObjectType, typename ...ArgsType>
struct __mem_func_ref_return_impl {
typedef decltype((std::declval<ObjectType>().*std::declval<FuncType>())(std::declval<ArgsType>()...)) type;
};
template<typename FuncType, typename ObjectType, typename ...ArgsType>
struct __mem_func_deref_return_impl {
typedef decltype(((*std::declval<ObjectType>()).*std::declval<FuncType>())(std::declval<ArgsType>()...)) type;
};
template<bool, bool, typename...>
struct __invoke_result_impl: public __failure_type{};
// mem func
template<typename FuncType, typename ObjectType, typename ...ArgsType>
struct __invoke_result_impl<true, false, FuncType, ObjectType, ArgsType...> {
typedef
typename std::conditional<
std::disjunction<
typename std::is_same<
remove_cvref_t<ObjectType>
, typename __mem_and_obj_type<FuncType>::obj_type
>::type,
typename std::is_base_of<
typename __mem_and_obj_type<FuncType>::obj_type,
remove_cvref_t<ObjectType>
>::type
>::value,
__mem_func_ref_return_impl<FuncType, ObjectType, ArgsType...>,
__mem_func_deref_return_impl<FuncType, ObjectType, ArgsType...>
>::type::type
type;
};
// mem obj
template<typename MemType, typename ObjectType>
struct __invoke_result_impl<false, true, MemType, ObjectType> {
typedef
typename std::conditional<
std::disjunction<
typename std::is_same<
std::remove_reference_t<std::remove_cv_t<ObjectType>>
, typename __mem_and_obj_type<MemType>::obj_type
>::type,
typename std::is_base_of<
typename __mem_and_obj_type<MemType>::obj_type,
std::remove_reference_t<std::remove_cv_t<ObjectType>>
>::type
>::value,
__mem_obj_ref_return_impl<MemType, ObjectType>,
__mem_obj_deref_return_impl<MemType, ObjectType>
>::type::type
type;
};
// other
template<typename FuncType, typename ...ArgsType>
struct __invoke_result_impl<false, false, FuncType, ArgsType...> {
typedef decltype((std::declval<FuncType>())(std::declval<ArgsType>()...)) type;
};
template<typename FuncType, typename ...ArgsType>
struct __invoke_result {
typedef typename __invoke_result_impl<
__is_mem_func<remove_cvref_t<FuncType>>::value
, __is_mem_obj<remove_cvref_t<FuncType>>::value,
FuncType, ArgsType...>::type type;
};
template<typename FuncType, typename ...ArgsType>
struct invoke_result : public __invoke_result<FuncType, ArgsType...> {};
template<typename>
struct result_of : public __failure_type{};
template<typename FuncType, typename ...ArgsType>
struct result_of<FuncType(ArgsType...)>: public invoke_result<FuncType, ArgsType...>{};
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment