mirror of
https://github.com/davisking/dlib.git
synced 2024-11-01 10:14:53 +08:00
- moved is_detected in type_traits.h (#2794)
- fixed callable_traits - added tests Co-authored-by: pf <pf@me>
This commit is contained in:
parent
191d280d64
commit
775ac0799f
@ -13,12 +13,6 @@ namespace dlib
|
||||
namespace detail
|
||||
{
|
||||
const auto _ = [](auto&& arg) -> decltype(auto) { return std::forward<decltype(arg)>(arg); };
|
||||
|
||||
template<typename Void, template <class...> class Op, class... Args>
|
||||
struct is_detected : std::false_type{};
|
||||
|
||||
template<template <class...> class Op, class... Args>
|
||||
struct is_detected<dlib::void_t<Op<Args...>>, Op, Args...> : std::true_type {};
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -111,16 +105,9 @@ namespace dlib
|
||||
{
|
||||
return overloaded(std::forward<Cases>(cases)...)(types_<T>{}..., detail::_);
|
||||
}
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template<template <class...> class Op, class... Args>
|
||||
using is_detected = detail::is_detected<void, Op, Args...>;
|
||||
/*!
|
||||
ensures
|
||||
- This is exactly the same as std::experimental::is_detected from library fundamentals v
|
||||
!*/
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
#endif //DLIB_IF_CONSTEXPR_H
|
@ -95,6 +95,8 @@ namespace
|
||||
static_assert(std::is_same<dlib::callable_return<decltype(func_testargs)>,
|
||||
void>::value, "make this correct");
|
||||
|
||||
static_assert(is_callable<decltype(func_testargs)>::value, "bad");
|
||||
|
||||
static_assert(std::is_same<dlib::callable_args<decltype(func_return_addition)>,
|
||||
dlib::types_<int, int>
|
||||
>::value, "make this correct");
|
||||
@ -111,6 +113,8 @@ namespace
|
||||
|
||||
static_assert(std::is_same<dlib::callable_return<decltype(func_return_addition)>,
|
||||
int>::value, "make this correct");
|
||||
|
||||
static_assert(is_callable<decltype(func_return_addition)>::value, "bad");
|
||||
|
||||
{
|
||||
std::string str = run1_str4;
|
||||
@ -160,6 +164,8 @@ namespace
|
||||
|
||||
static_assert(std::is_same<dlib::callable_return<decltype(f)>,
|
||||
long>::value, "make this correct");
|
||||
|
||||
static_assert(is_callable<decltype(f)>::value, "bad");
|
||||
}
|
||||
|
||||
{
|
||||
@ -228,6 +234,8 @@ namespace
|
||||
static_assert(std::is_same<dlib::callable_return<example_struct>,
|
||||
float>::value, "make this correct");
|
||||
|
||||
static_assert(is_callable<example_struct>::value, "bad");
|
||||
|
||||
void test_member_functions_and_data()
|
||||
{
|
||||
example_struct obj1(10);
|
||||
@ -482,6 +490,7 @@ namespace
|
||||
{
|
||||
template <
|
||||
class Callable,
|
||||
std::enable_if_t<is_callable<Callable>::value, bool> = true,
|
||||
std::enable_if_t<callable_nargs<Callable>::value >= 1, bool> = true,
|
||||
std::enable_if_t<std::is_floating_point<callable_arg<0, Callable>>::value, bool> = true
|
||||
>
|
||||
@ -499,6 +508,7 @@ namespace
|
||||
|
||||
template <
|
||||
class Callable,
|
||||
std::enable_if_t<is_callable<Callable>::value, bool> = true,
|
||||
std::enable_if_t<callable_nargs<Callable>::value >= 1, bool> = true,
|
||||
std::enable_if_t<std::is_integral<callable_arg<0, Callable>>::value, bool> = true
|
||||
>
|
||||
@ -516,6 +526,7 @@ namespace
|
||||
|
||||
template <
|
||||
class Callable,
|
||||
std::enable_if_t<is_callable<Callable>::value, bool> = true,
|
||||
std::enable_if_t<callable_nargs<Callable>::value < 1, bool> = true
|
||||
>
|
||||
auto wrap (
|
||||
@ -543,6 +554,8 @@ namespace
|
||||
const auto f6 = wrap(f3, i);
|
||||
DLIB_TEST(i == 3);
|
||||
}
|
||||
|
||||
static_assert(!is_callable<int>::value, "bad");
|
||||
}
|
||||
|
||||
class invoke_tester : public tester
|
||||
|
@ -210,6 +210,24 @@ namespace dlib
|
||||
template<class T>
|
||||
using is_complete_type = details::is_complete_type<T>;
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
namespace details
|
||||
{
|
||||
template<typename Void, template <class...> class Op, class... Args>
|
||||
struct is_detected : std::false_type{};
|
||||
|
||||
template<template <class...> class Op, class... Args>
|
||||
struct is_detected<dlib::void_t<Op<Args...>>, Op, Args...> : std::true_type {};
|
||||
}
|
||||
|
||||
template<template <class...> class Op, class... Args>
|
||||
using is_detected = details::is_detected<void, Op, Args...>;
|
||||
/*!
|
||||
ensures
|
||||
- This is exactly the same as std::experimental::is_detected from library fundamentals v
|
||||
!*/
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template<typename... T>
|
||||
@ -264,50 +282,71 @@ namespace dlib
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
namespace details
|
||||
{
|
||||
template<class AlwaysVoid, class F>
|
||||
struct callable_traits
|
||||
{
|
||||
constexpr static bool is_callable = false;
|
||||
};
|
||||
|
||||
template<class AlwaysVoid, class R, class... Args>
|
||||
struct callable_traits<AlwaysVoid, R(Args...)>
|
||||
{
|
||||
using return_type = R;
|
||||
using args = types_<Args...>;
|
||||
constexpr static std::size_t nargs = sizeof...(Args);
|
||||
constexpr static bool is_callable = true;
|
||||
};
|
||||
|
||||
template<class AlwaysVoid, class R, class... Args>
|
||||
struct callable_traits<AlwaysVoid, R(*)(Args...)>
|
||||
: public callable_traits<AlwaysVoid, R(Args...)>{};
|
||||
|
||||
template<class AlwaysVoid, class C, class R, class... Args>
|
||||
struct callable_traits<AlwaysVoid, R(C::*)(Args...)>
|
||||
: public callable_traits<AlwaysVoid, R(Args...)>{};
|
||||
|
||||
template<class AlwaysVoid, class C, class R, class... Args>
|
||||
struct callable_traits<AlwaysVoid, R(C::*)(Args...) const>
|
||||
: public callable_traits<AlwaysVoid, R(Args...)>{};
|
||||
|
||||
template<class F>
|
||||
struct callable_traits<void_t<decltype(&std::decay_t<F>::operator())>, F>
|
||||
: public callable_traits<void, decltype(&std::decay_t<F>::operator())>{};
|
||||
}
|
||||
|
||||
template<class F>
|
||||
struct callable_traits;
|
||||
struct callable_traits : details::callable_traits<void, F> {};
|
||||
/*!
|
||||
WHAT THIS OBJECT REPRESENTS
|
||||
This is a type trait for callable types like function pointers, functors and lambdas.
|
||||
It provides the following types:
|
||||
This is a type trait for callable types.
|
||||
|
||||
If the template parameter F is function pointer, functor or lambda then
|
||||
it provides the following types:
|
||||
return_type : the return type of the callable object
|
||||
args : a parameter pack packaged in a types_<> meta container containing
|
||||
all the function argument types
|
||||
It also provides the following static members:
|
||||
nargs : the number of function arguments
|
||||
is_callable : a boolean which determines whether F is callable. In this case, it is true
|
||||
|
||||
If the template parameter F is not function-like object, then it provides:
|
||||
is_callable : false
|
||||
|
||||
For example, a function type F with signature R(T1, T2, T3) has the following traits:
|
||||
callable_traits<F>::return_type == R
|
||||
callable_traits<F>::args == types_<T1,T2,T3>
|
||||
callable_traits<F>::nargs == 3
|
||||
callable_traits<F>::is_callable == true
|
||||
|
||||
Another example:
|
||||
callable_traits<int>::is_callable == false
|
||||
callable_traits<int>::return_type == does not exist. Compile error
|
||||
callable_traits<int>::args == does not exist. Compile error
|
||||
callable_traits<int>::nargs == does not exist. Compile error
|
||||
!*/
|
||||
|
||||
template<class R, class... Args>
|
||||
struct callable_traits<R(Args...)>
|
||||
{
|
||||
using return_type = R;
|
||||
using args = types_<Args...>;
|
||||
constexpr static std::size_t nargs = sizeof...(Args);
|
||||
};
|
||||
|
||||
template<class R, class... Args>
|
||||
struct callable_traits<R(*)(Args...)> : public callable_traits<R(Args...)>{};
|
||||
|
||||
template<class C, class R, class... Args>
|
||||
struct callable_traits<R(C::*)(Args...)> : public callable_traits<R(Args...)>{};
|
||||
|
||||
template<class C, class R, class... Args>
|
||||
struct callable_traits<R(C::*)(Args...) const> : public callable_traits<R(Args...)>{};
|
||||
|
||||
template<class F>
|
||||
struct callable_traits
|
||||
{
|
||||
using call_type = callable_traits<decltype(&std::decay_t<F>::operator())>;
|
||||
using return_type = typename call_type::return_type;
|
||||
using args = typename call_type::args;
|
||||
constexpr static std::size_t nargs = call_type::nargs;
|
||||
};
|
||||
|
||||
template<class Callable>
|
||||
using callable_args = typename callable_traits<Callable>::args;
|
||||
|
||||
@ -320,6 +359,9 @@ namespace dlib
|
||||
template<class Callable>
|
||||
using callable_return = typename callable_traits<Callable>::return_type;
|
||||
|
||||
template<class F>
|
||||
using is_callable = std::integral_constant<bool, callable_traits<F>::is_callable>;
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user