From a7b3770285f33fdd27010c5a41a89324df4adad0 Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Sun, 19 Mar 2023 13:59:55 -0600 Subject: [PATCH] Add a compatibility type for C++20's std::identity_type. --- include/deal.II/base/std_cxx20/type_traits.h | 103 +++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 include/deal.II/base/std_cxx20/type_traits.h diff --git a/include/deal.II/base/std_cxx20/type_traits.h b/include/deal.II/base/std_cxx20/type_traits.h new file mode 100644 index 0000000000..95bb6b4af0 --- /dev/null +++ b/include/deal.II/base/std_cxx20/type_traits.h @@ -0,0 +1,103 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2023 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE.md at +// the top level directory of deal.II. +// +// --------------------------------------------------------------------- +#ifndef dealii_cxx20_type_traits_h +#define dealii_cxx20_type_traits_h + +#include + +#ifdef DEAL_II_HAVE_CXX20 +# include +#endif + +DEAL_II_NAMESPACE_OPEN + +namespace std_cxx20 +{ +#ifdef DEAL_II_HAVE_CXX20 + using std::type_identity; + using std::type_identity_t; +#else + /** + * A template class that simply exports its template argument as a local + * alias. This class, while at first appearing useless, makes sense in the + * following context: if you have a function template as follows: + * @code + * template + * void f(T, T); + * @endcode + * then it can't be called in an expression like f(1, 3.141) + * because the type T of the template can not be deduced in a + * unique way from the types of the arguments. However, if the template is + * written as + * @code + * template + * void f(T, typename identity::type); + * @endcode + * then the call becomes valid: the type T is not deducible + * from the second argument to the function, so only the first argument + * participates in template type resolution. + * + * The context for this feature is as follows: consider + * @code + * template + * void forward_call(RT (*p) (A), A a) + * { + * p(a); + * } + * + * void h (double); + * + * void g() + * { + * forward_call(&h, 1); + * } + * @endcode + * This code fails to compile because the compiler can't decide whether the + * template type A should be double (from the + * signature of the function given as first argument to + * forward_call, or int because the expression + * 1 has that type. Of course, what we would like the compiler + * to do is simply cast the 1 to double. We can + * achieve this by writing the code as follows: + * @code + * template + * void forward_call(RT (*p) (A), typename identity::type a) + * { + * p(a); + * } + * + * void h (double); + * + * void g() + * { + * forward_call(&h, 1); + * } + * @endcode + */ + template + struct type_identity + { + using type = T; + }; + + template + using type_identity_t = typename type_identity::type; + +#endif +} // namespace std_cxx20 + +DEAL_II_NAMESPACE_CLOSE + +#endif -- 2.39.5