github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/3rd_party/fflib/include/ff/util/function_traits.h (about)

     1  /***********************************************
     2  The MIT License (MIT)
     3  
     4  Copyright (c) 2012 Athrun Arthur <athrunarthur@gmail.com>
     5  
     6  Permission is hereby granted, free of charge, to any person obtaining a copy
     7  of this software and associated documentation files (the "Software"), to deal
     8  in the Software without restriction, including without limitation the rights
     9  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    10  copies of the Software, and to permit persons to whom the Software is
    11  furnished to do so, subject to the following conditions:
    12  
    13  The above copyright notice and this permission notice shall be included in
    14  all copies or substantial portions of the Software.
    15  
    16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    21  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    22  THE SOFTWARE.
    23  *************************************************/
    24  #pragma once
    25  #include "ff/util/func_type_checker.h"
    26  #include "ff/util/is_callable.h"
    27  #include <functional>
    28  #include <type_traits>
    29  
    30  namespace ff {
    31  namespace util {
    32  template <class F>
    33  struct deduce_function {};
    34  
    35  template <class Ret, class C, class... Args>
    36  struct deduce_function<Ret (C::*)(Args...) const> {
    37    typedef std::function<Ret(Args...)> type;
    38    typedef Ret ret_type;
    39  };
    40  
    41  template <class Ret, class C, class... Args>
    42  struct deduce_function<Ret (C::*)(Args...)> {
    43    typedef std::function<Ret(Args...)> type;
    44    typedef Ret ret_type;
    45  };
    46  
    47  template <class Ret, class... Args>
    48  struct deduce_function<Ret(Args...)> {
    49    typedef std::function<Ret(Args...)> type;
    50    typedef Ret ret_type;
    51  };
    52  
    53  template <class F>
    54  struct is_no_args_function {
    55    const static bool value = false;
    56  };
    57  
    58  template <class Ret, class C>
    59  struct is_no_args_function<Ret (C::*)(void) const> {
    60    const static bool value = true;
    61  };
    62  
    63  template <class Ret, class C>
    64  struct is_no_args_function<Ret (C::*)(void)> {
    65    const static bool value = true;
    66  };
    67  
    68  template <class Ret>
    69  struct is_no_args_function<Ret(void)> {
    70    const static bool value = true;
    71  };
    72  template <class Ret>
    73  struct is_no_args_function<Ret (*)(void)> {
    74    const static bool value = true;
    75  };
    76  
    77  template <class F, bool flag>
    78  struct functor_res_traits {
    79    typedef typename deduce_function<decltype(
    80        &std::remove_reference<F>::type::operator())>::ret_type ret_type;
    81  };
    82  
    83  template <class F>
    84  struct functor_res_traits<F, false> {
    85    typedef void ret_type;
    86  };
    87  
    88  template <class F, bool flag>
    89  struct bind_res_traits {
    90    typedef typename F::result_type ret_type;
    91  };
    92  
    93  template <class F>
    94  struct bind_res_traits<F, false> {
    95    typedef void ret_type;
    96  };
    97  
    98  namespace internal {
    99  template <class F, bool flag>
   100  struct function_res_traits_impl {
   101    typedef typename deduce_function<F>::ret_type ret_type;
   102  };
   103  template <class F>
   104  struct function_res_traits_impl<F, false> {
   105    typedef void ret_type;
   106  };
   107  
   108  template <class F>
   109  struct function_res_traits_impl<F *, true> {
   110    typedef typename deduce_function<F>::ret_type ret_type;
   111  };
   112  template <class F>
   113  struct function_res_traits_impl<F &, true> {
   114    typedef typename deduce_function<F>::ret_type ret_type;
   115  };
   116  } // namespace internal
   117  
   118  template <class F>
   119  struct function_res_traits {
   120    typedef typename std::remove_reference<F>::type FT;
   121    const static bool s_is_class = std::is_class<FT>::value;
   122    const static bool s_is_bind_expr = std::is_bind_expression<FT>::value;
   123  
   124    typedef typename std::conditional<
   125        s_is_class,
   126        typename std::conditional<
   127            s_is_bind_expr,
   128            typename bind_res_traits<FT, s_is_bind_expr>::ret_type,
   129            typename functor_res_traits<FT, !s_is_bind_expr &&
   130                                                s_is_class>::ret_type>::type,
   131        typename internal::function_res_traits_impl<FT, !s_is_class>::ret_type>::
   132        type ret_type;
   133  };
   134  
   135  template <class F, bool flag>
   136  struct functor_args_traits {
   137    const static bool is_no_args = is_no_args_function<decltype(
   138        &std::remove_reference<F>::type::operator())>::value;
   139  };
   140  
   141  template <class F>
   142  struct functor_args_traits<F, false> {
   143    const static bool is_no_args = false;
   144  };
   145  
   146  namespace internal {
   147  template <class F, bool flag>
   148  struct function_args_traits_impl {
   149    const static bool is_no_args = is_no_args_function<F>::value;
   150  };
   151  
   152  template <class F>
   153  struct function_args_traits_impl<F, false> {
   154    const static bool is_no_args = false;
   155  };
   156  
   157  template <class F>
   158  struct function_args_traits_impl<F *, true> {
   159    const static bool is_no_args = is_no_args_function<F>::value;
   160  };
   161  template <class F>
   162  struct function_args_traits_impl<F &, true> {
   163    const static bool is_no_args = is_no_args_function<F>::value;
   164  };
   165  } // namespace internal
   166  
   167  template <class F>
   168  struct function_args_traits {
   169    typedef typename std::remove_reference<F>::type FT;
   170    const static bool s_is_class = std::is_class<FT>::value;
   171  
   172    const static bool is_no_args =
   173        functor_args_traits<FT, s_is_class>::is_no_args ||
   174        internal::function_args_traits_impl<FT, !s_is_class>::is_no_args;
   175  };
   176  
   177  } // end namespace util
   178  };  // end namespace ff