@@ -55,13 +55,39 @@ inline T_actual&& forward_as(T_actual&& a) { // NOLINT
5555 * @throw always throws std::runtime_error
5656 */
5757template <typename T_desired, typename T_actual,
58+ require_any_not_eigen_t <T_desired, T_actual>* = nullptr ,
5859 typename = std::enable_if_t <
5960 !std::is_same<std::decay<T_actual>, std::decay<T_desired>>::value
60- && (!is_eigen<T_desired>::value || !is_eigen<T_actual>::value)>>
61+ && !(std::is_arithmetic_v<std::decay_t <T_desired>>
62+ && std::is_arithmetic_v<std::decay_t <T_actual>>)>>
6163inline T_desired forward_as (const T_actual& a) {
6264 throw std::runtime_error (" Wrong type assumed! Please file a bug report." );
6365}
6466
67+ /* * \ingroup type_trait
68+ * Assume which type we get. If actual type is not convertible to assumed type
69+ * or in case of eigen types compile time rows and columns are not the same and
70+ * desired sizes are not dynamic this has return type of \c T_desired, but it
71+ * only throws. This version should only be used where it is optimized away so
72+ * the throw should never happen.
73+ *
74+ * This handles the edge case where both types are simple arithmetic types
75+ * and we would like to just convert one to another.
76+ *
77+ * @tparam T_desired type of output we need to avoid compile time errors
78+ * @tparam T_actual actual type of the argument
79+ * @param a input value
80+ * @return a
81+ */
82+ template <typename T_desired, typename T_actual,
83+ typename = std::enable_if_t <
84+ !std::is_same_v<std::decay_t <T_actual>, std::decay_t <T_desired>>
85+ && std::is_arithmetic_v<std::decay_t <T_desired>>
86+ && std::is_arithmetic_v<std::decay_t <T_actual>>>>
87+ inline T_desired forward_as (const T_actual& a) {
88+ return static_cast <T_desired>(a);
89+ }
90+
6591/* * \ingroup type_trait
6692 * Assume which type we get. If actual type is convertible to assumed type or in
6793 * case of eigen types compile time rows and columns also match or desired sizes
0 commit comments