]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Add a compatibility type for C++20's std::identity_type.
authorWolfgang Bangerth <bangerth@colostate.edu>
Sun, 19 Mar 2023 19:59:55 +0000 (13:59 -0600)
committerWolfgang Bangerth <bangerth@colostate.edu>
Sun, 19 Mar 2023 21:09:02 +0000 (15:09 -0600)
include/deal.II/base/std_cxx20/type_traits.h [new file with mode: 0644]

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 (file)
index 0000000..95bb6b4
--- /dev/null
@@ -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 <deal.II/base/config.h>
+
+#ifdef DEAL_II_HAVE_CXX20
+#  include <type_traits>
+#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 <typename T>
+   * void f(T, T);
+   * @endcode
+   * then it can't be called in an expression like <code>f(1, 3.141)</code>
+   * because the type <code>T</code> 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 <typename T>
+   * void f(T, typename identity<T>::type);
+   * @endcode
+   * then the call becomes valid: the type <code>T</code> 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 <typename RT, typename A>
+   * 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 <code>A</code> should be <code>double</code> (from the
+   * signature of the function given as first argument to
+   * <code>forward_call</code>, or <code>int</code> because the expression
+   * <code>1</code> has that type. Of course, what we would like the compiler
+   * to do is simply cast the <code>1</code> to <code>double</code>. We can
+   * achieve this by writing the code as follows:
+   * @code
+   * template <typename RT, typename A>
+   * void forward_call(RT (*p) (A), typename identity<A>::type a)
+   * {
+   *   p(a);
+   * }
+   *
+   * void h (double);
+   *
+   * void g()
+   * {
+   *   forward_call(&h, 1);
+   * }
+   * @endcode
+   */
+  template <typename T>
+  struct type_identity
+  {
+    using type = T;
+  };
+
+  template <class T>
+  using type_identity_t = typename type_identity<T>::type;
+
+#endif
+} // namespace std_cxx20
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.