diff options
author | Antonio Sanchez <cantonios@google.com> | 2021-02-17 11:59:33 -0800 |
---|---|---|
committer | Rasmus Munk Larsen <rmlarsen@google.com> | 2021-02-24 21:36:14 +0000 |
commit | a31effc3bca2f0924752caeebfd6f61f7edf9a43 (patch) | |
tree | da21b842892e0e8f793756969e7840d71b3e1aa7 /Eigen/src/Core/util/Meta.h | |
parent | 8523d447a137f20de5485fbdd28aafc3d0774153 (diff) |
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.
Diffstat (limited to 'Eigen/src/Core/util/Meta.h')
-rwxr-xr-x | Eigen/src/Core/util/Meta.h | 89 |
1 files changed, 83 insertions, 6 deletions
diff --git a/Eigen/src/Core/util/Meta.h b/Eigen/src/Core/util/Meta.h index 32a03aecc..cad57c3a4 100755 --- a/Eigen/src/Core/util/Meta.h +++ b/Eigen/src/Core/util/Meta.h @@ -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. - * - * 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. + * Convenient struct to get the result type of a nullary, unary, binary, or + * ternary functor. + * + * 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]; }; |