From: Jean-Paul Pelteret Date: Mon, 16 Oct 2017 07:47:02 +0000 (+0200) Subject: Implement a more generic method of converting between number types. X-Git-Tag: v9.0.0-rc1~947^2 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f2fd123f727fd265bc7a6095c990a3ba58827ebe;p=dealii.git Implement a more generic method of converting between number types. This is particularly useful when needing to cast exotic number types to a floating point numbers, such as might happen when converting between tensor types. --- diff --git a/include/deal.II/base/numbers.h b/include/deal.II/base/numbers.h index 33fcdc6acf..c25eadb659 100644 --- a/include/deal.II/base/numbers.h +++ b/include/deal.II/base/numbers.h @@ -384,6 +384,36 @@ namespace numbers namespace internal { + /** + * A test to see if it is possible to convert one number + * type to the other. + */ + template + struct is_explicitly_convertible + { + // Source: https://stackoverflow.com/a/16944130 + private: + template + static void f(T); + + template + static constexpr auto test(int) -> + decltype(f(static_cast(std::declval())),true) + { + return true; + } + + template + static constexpr auto test(...) -> bool + { + return false; + } + + public: + + static bool const value = test(0); + }; + /** * The structs below are needed since VectorizedArray is a POD-type without a constructor and * can be a template argument for SymmetricTensor<...,T2> where T2 would equal VectorizedArray. @@ -401,6 +431,38 @@ namespace internal { return t; } + + // Below are generic functions that allows an overload for any + // type U that is transformable to type T. This is particularly + // useful when needing to cast exotic number types + // (e.g. auto-differentiable or symbolic numbers) to a floating + // point one, such as might happen when converting between tensor + // types. + + // Type T is constructible from F. + template + static T + value (const F &f, + typename std::enable_if< + !std::is_same::type,typename std::decay::type>::value && + std::is_constructible::value + >::type * = 0) + { + return T(f); + } + + // Type T is explicitly convertible (but not constructible) from F. + template + static T + value (const F &f, + typename std::enable_if< + !std::is_same::type,typename std::decay::type>::value && + !std::is_constructible::value && + is_explicitly_convertible::value + >::type * = 0) + { + return static_cast(f); + } }; template