mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-06-04 18:54:00 +08:00
Add invoke_result
and eliminate result_of
warnings for C++17+.
The `std::result_of` meta struct is deprecated in C++17 and removed in C++20. It was still slipping through due to a faulty definition of `EIGEN_HAS_STD_RESULT_OF`. Added a new macro `EIGEN_HAS_STD_INVOKE_RESULT` and `Eigen::internal::invoke_result` implementation with fallback for pre C++17. Replaces the `result_of` definition with one based on `std::invoke_result` for C++17 and higher. For completeness, added nullary op support for c++03. Fixes #1850.
This commit is contained in:
parent
8523d447a1
commit
a31effc3bc
@ -660,8 +660,7 @@
|
||||
// result_of was deprecated in c++17 and removed in c++ 20
|
||||
#ifndef EIGEN_HAS_STD_RESULT_OF
|
||||
#if EIGEN_MAX_CPP_VER >= 11 && \
|
||||
((defined(__cplusplus) && __cplusplus >= 201103L && __cplusplus < 201703L) || \
|
||||
__has_feature(cxx_lambdas))
|
||||
(defined(__cplusplus) && __cplusplus >= 201103L && __cplusplus < 201703L)
|
||||
#define EIGEN_HAS_STD_RESULT_OF 1
|
||||
#else
|
||||
#define EIGEN_HAS_STD_RESULT_OF 0
|
||||
@ -679,6 +678,15 @@
|
||||
#endif
|
||||
#endif // EIGEN_HAS_STD_HASH
|
||||
|
||||
#ifndef EIGEN_HAS_STD_INVOKE_RESULT
|
||||
#if EIGEN_MAX_CPP_VER >= 17 && \
|
||||
(defined(__cplusplus) && __cplusplus >= 201703L)
|
||||
#define EIGEN_HAS_STD_INVOKE_RESULT 1
|
||||
#else
|
||||
#define EIGEN_HAS_STD_INVOKE_RESULT 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_HAS_ALIGNAS
|
||||
#if EIGEN_MAX_CPP_VER>=11 && EIGEN_HAS_CXX11 && \
|
||||
( __has_feature(cxx_alignas) \
|
||||
|
@ -482,13 +482,29 @@ template<typename T,std::size_t N>
|
||||
Index size(const T (&) [N]) { return N; }
|
||||
|
||||
/** \internal
|
||||
* Convenient struct to get the result type of a unary or binary functor.
|
||||
* Convenient struct to get the result type of a nullary, unary, binary, or
|
||||
* ternary functor.
|
||||
*
|
||||
* It supports both the current STL mechanism (using the result_type member) as well as
|
||||
* upcoming next STL generation (using a templated result member).
|
||||
* If none of these members is provided, then the type of the first argument is returned. FIXME, that behavior is a pretty bad hack.
|
||||
* Pre C++11:
|
||||
* Supports both a Func::result_type member and templated
|
||||
* Func::result<Func(ArgTypes...)>::type member.
|
||||
*
|
||||
* If none of these members is provided, then the type of the first
|
||||
* argument is returned.
|
||||
*
|
||||
* Post C++11:
|
||||
* This uses std::result_of. However, note the `type` member removes
|
||||
* const and converts references/pointers to their corresponding value type.
|
||||
*/
|
||||
#if EIGEN_HAS_STD_RESULT_OF
|
||||
#if EIGEN_HAS_STD_INVOKE_RESULT
|
||||
template<typename T> struct result_of;
|
||||
|
||||
template<typename F, typename... ArgTypes>
|
||||
struct result_of<F(ArgTypes...)> {
|
||||
typedef typename std::invoke_result<F, ArgTypes...>::type type1;
|
||||
typedef typename remove_all<type1>::type type;
|
||||
};
|
||||
#elif EIGEN_HAS_STD_RESULT_OF
|
||||
template<typename T> struct result_of {
|
||||
typedef typename std::result_of<T>::type type1;
|
||||
typedef typename remove_all<type1>::type type;
|
||||
@ -500,6 +516,28 @@ struct has_none {int a[1];};
|
||||
struct has_std_result_type {int a[2];};
|
||||
struct has_tr1_result {int a[3];};
|
||||
|
||||
template<typename Func, int SizeOf>
|
||||
struct nullary_result_of_select {};
|
||||
|
||||
template<typename Func>
|
||||
struct nullary_result_of_select<Func, sizeof(has_std_result_type)> {typedef typename Func::result_type type;};
|
||||
|
||||
template<typename Func>
|
||||
struct nullary_result_of_select<Func, sizeof(has_tr1_result)> {typedef typename Func::template result<Func()>::type type;};
|
||||
|
||||
template<typename Func>
|
||||
struct result_of<Func()> {
|
||||
template<typename T>
|
||||
static has_std_result_type testFunctor(T const *, typename T::result_type const * = 0);
|
||||
template<typename T>
|
||||
static has_tr1_result testFunctor(T const *, typename T::template result<T()>::type const * = 0);
|
||||
static has_none testFunctor(...);
|
||||
|
||||
// note that the following indirection is needed for gcc-3.3
|
||||
enum {FunctorType = sizeof(testFunctor(static_cast<Func*>(0)))};
|
||||
typedef typename nullary_result_of_select<Func, FunctorType>::type type;
|
||||
};
|
||||
|
||||
template<typename Func, typename ArgType, int SizeOf=sizeof(has_none)>
|
||||
struct unary_result_of_select {typedef typename internal::remove_all<ArgType>::type type;};
|
||||
|
||||
@ -569,6 +607,45 @@ struct result_of<Func(ArgType0,ArgType1,ArgType2)> {
|
||||
enum {FunctorType = sizeof(testFunctor(static_cast<Func*>(0)))};
|
||||
typedef typename ternary_result_of_select<Func, ArgType0, ArgType1, ArgType2, FunctorType>::type type;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if EIGEN_HAS_STD_INVOKE_RESULT
|
||||
template<typename F, typename... ArgTypes>
|
||||
struct invoke_result {
|
||||
typedef typename std::invoke_result<F, ArgTypes...>::type type1;
|
||||
typedef typename remove_all<type1>::type type;
|
||||
};
|
||||
#elif EIGEN_HAS_CXX11
|
||||
template<typename F, typename... ArgTypes>
|
||||
struct invoke_result {
|
||||
typedef typename result_of<F(ArgTypes...)>::type type1;
|
||||
typedef typename remove_all<type1>::type type;
|
||||
};
|
||||
#else
|
||||
template<typename F, typename ArgType0 = void, typename ArgType1 = void, typename ArgType2 = void>
|
||||
struct invoke_result {
|
||||
typedef typename result_of<F(ArgType0, ArgType1, ArgType2)>::type type1;
|
||||
typedef typename remove_all<type1>::type type;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
struct invoke_result<F, void, void, void> {
|
||||
typedef typename result_of<F()>::type type1;
|
||||
typedef typename remove_all<type1>::type type;
|
||||
};
|
||||
|
||||
template<typename F, typename ArgType0>
|
||||
struct invoke_result<F, ArgType0, void, void> {
|
||||
typedef typename result_of<F(ArgType0)>::type type1;
|
||||
typedef typename remove_all<type1>::type type;
|
||||
};
|
||||
|
||||
template<typename F, typename ArgType0, typename ArgType1>
|
||||
struct invoke_result<F, ArgType0, ArgType1, void> {
|
||||
typedef typename result_of<F(ArgType0, ArgType1)>::type type1;
|
||||
typedef typename remove_all<type1>::type type;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct meta_yes { char a[1]; };
|
||||
|
Loading…
x
Reference in New Issue
Block a user