00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef IS_CALLABLE_HH
00018 # define IS_CALLABLE_HH
00019
00020 # include <type_traits>
00021 # include <memory>
00022 # include "try_first.hh"
00023 # include "always_false.hh"
00024 # include "../concept/concept_tools.hh"
00025 # include "../type_traits/identity.hh"
00026
00027 namespace catsfoot {
00028
00030 template <typename T>
00031 struct undefined_return {};
00032
00033 namespace details {
00035 template <typename T, typename... U>
00036 std::false_type is_callable_helper(try_second, T&&, U&&...) {
00037 static_assert(always_false<T>::value,
00038 "Cannot use this function");
00039 return 0;
00040 }
00041
00043 template <typename T, typename... U,
00044 typename =
00045 decltype(std::declval<T>()(std::declval<U>()...))>
00046 std::true_type is_callable_helper(try_first, T&&, U&&...) {
00047 static_assert(always_false<T>::value,
00048 "Cannot use this function");
00049 return 0;
00050 }
00051
00053 template <typename T>
00054 struct callable_real_map {};
00055
00057 template <typename T>
00058 struct callable_bad_map {};
00059
00061 template <typename T, typename... U>
00062 struct callable_real_map<T(U...)> {
00063 typedef decltype(std::declval<T>()(std::declval<U>()...))
00064 result_type;
00065 };
00066
00068 template <typename T, typename... U>
00069 struct callable_bad_map<T(U...)> {
00070 typedef undefined_return<T(U...)> result_type;
00071 };
00072 }
00073
00075 template <typename T>
00076 struct is_callable
00077 #ifndef DOC_GEN
00078 : public is_callable<T()>
00079 #endif
00080 {
00081 };
00082
00085 template <typename T, typename... U>
00086 struct is_callable<T(U...)>:
00087 public identity<decltype(details::
00088 is_callable_helper(details::try_first(),
00089 std::declval<T>(),
00090 std::declval<U>()...))>
00091 ::type {
00092 typedef decltype(details::
00093 is_callable_helper(details::try_first(),
00094 std::declval<T>(),
00095 std::declval<U>()...))
00096 super;
00097 typedef typename
00098 std::conditional<super::value,
00099 details::callable_real_map<T(U...)>,
00100 details::callable_bad_map<T(U...)> >::type::result_type
00101 result_type;
00102 };
00103
00105 template <typename... U>
00106 struct is_callable<void(U...)>:
00107 public std::false_type {
00108 typedef undefined_return<void(U...)> result_type;
00109 };
00110 }
00111
00112 #endif