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
|
namespace detail
|
||||||
{
|
{
|
||||||
const auto _ = [](auto&& arg) -> decltype(auto) { return std::forward<decltype(arg)>(arg); };
|
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::_);
|
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
|
#endif //DLIB_IF_CONSTEXPR_H
|
@ -95,6 +95,8 @@ namespace
|
|||||||
static_assert(std::is_same<dlib::callable_return<decltype(func_testargs)>,
|
static_assert(std::is_same<dlib::callable_return<decltype(func_testargs)>,
|
||||||
void>::value, "make this correct");
|
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)>,
|
static_assert(std::is_same<dlib::callable_args<decltype(func_return_addition)>,
|
||||||
dlib::types_<int, int>
|
dlib::types_<int, int>
|
||||||
>::value, "make this correct");
|
>::value, "make this correct");
|
||||||
@ -111,6 +113,8 @@ namespace
|
|||||||
|
|
||||||
static_assert(std::is_same<dlib::callable_return<decltype(func_return_addition)>,
|
static_assert(std::is_same<dlib::callable_return<decltype(func_return_addition)>,
|
||||||
int>::value, "make this correct");
|
int>::value, "make this correct");
|
||||||
|
|
||||||
|
static_assert(is_callable<decltype(func_return_addition)>::value, "bad");
|
||||||
|
|
||||||
{
|
{
|
||||||
std::string str = run1_str4;
|
std::string str = run1_str4;
|
||||||
@ -160,6 +164,8 @@ namespace
|
|||||||
|
|
||||||
static_assert(std::is_same<dlib::callable_return<decltype(f)>,
|
static_assert(std::is_same<dlib::callable_return<decltype(f)>,
|
||||||
long>::value, "make this correct");
|
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>,
|
static_assert(std::is_same<dlib::callable_return<example_struct>,
|
||||||
float>::value, "make this correct");
|
float>::value, "make this correct");
|
||||||
|
|
||||||
|
static_assert(is_callable<example_struct>::value, "bad");
|
||||||
|
|
||||||
void test_member_functions_and_data()
|
void test_member_functions_and_data()
|
||||||
{
|
{
|
||||||
example_struct obj1(10);
|
example_struct obj1(10);
|
||||||
@ -482,6 +490,7 @@ namespace
|
|||||||
{
|
{
|
||||||
template <
|
template <
|
||||||
class Callable,
|
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<callable_nargs<Callable>::value >= 1, bool> = true,
|
||||||
std::enable_if_t<std::is_floating_point<callable_arg<0, Callable>>::value, bool> = true
|
std::enable_if_t<std::is_floating_point<callable_arg<0, Callable>>::value, bool> = true
|
||||||
>
|
>
|
||||||
@ -499,6 +508,7 @@ namespace
|
|||||||
|
|
||||||
template <
|
template <
|
||||||
class Callable,
|
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<callable_nargs<Callable>::value >= 1, bool> = true,
|
||||||
std::enable_if_t<std::is_integral<callable_arg<0, Callable>>::value, bool> = true
|
std::enable_if_t<std::is_integral<callable_arg<0, Callable>>::value, bool> = true
|
||||||
>
|
>
|
||||||
@ -516,6 +526,7 @@ namespace
|
|||||||
|
|
||||||
template <
|
template <
|
||||||
class Callable,
|
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<callable_nargs<Callable>::value < 1, bool> = true
|
||||||
>
|
>
|
||||||
auto wrap (
|
auto wrap (
|
||||||
@ -543,6 +554,8 @@ namespace
|
|||||||
const auto f6 = wrap(f3, i);
|
const auto f6 = wrap(f3, i);
|
||||||
DLIB_TEST(i == 3);
|
DLIB_TEST(i == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static_assert(!is_callable<int>::value, "bad");
|
||||||
}
|
}
|
||||||
|
|
||||||
class invoke_tester : public tester
|
class invoke_tester : public tester
|
||||||
|
@ -210,6 +210,24 @@ namespace dlib
|
|||||||
template<class T>
|
template<class T>
|
||||||
using is_complete_type = details::is_complete_type<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>
|
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>
|
template<class F>
|
||||||
struct callable_traits;
|
struct callable_traits : details::callable_traits<void, F> {};
|
||||||
/*!
|
/*!
|
||||||
WHAT THIS OBJECT REPRESENTS
|
WHAT THIS OBJECT REPRESENTS
|
||||||
This is a type trait for callable types like function pointers, functors and lambdas.
|
This is a type trait for callable types.
|
||||||
It provides the following 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
|
return_type : the return type of the callable object
|
||||||
args : a parameter pack packaged in a types_<> meta container containing
|
args : a parameter pack packaged in a types_<> meta container containing
|
||||||
all the function argument types
|
all the function argument types
|
||||||
It also provides the following static members:
|
It also provides the following static members:
|
||||||
nargs : the number of function arguments
|
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:
|
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>::return_type == R
|
||||||
callable_traits<F>::args == types_<T1,T2,T3>
|
callable_traits<F>::args == types_<T1,T2,T3>
|
||||||
callable_traits<F>::nargs == 3
|
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>
|
template<class Callable>
|
||||||
using callable_args = typename callable_traits<Callable>::args;
|
using callable_args = typename callable_traits<Callable>::args;
|
||||||
|
|
||||||
@ -320,6 +359,9 @@ namespace dlib
|
|||||||
template<class Callable>
|
template<class Callable>
|
||||||
using callable_return = typename callable_traits<Callable>::return_type;
|
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