Просмотр исходного кода

Memory management: cast functions for managed pointers

Marc Chevrier 6 лет назад
Родитель
Сommit
fc3b4caa2e

+ 1 - 1
.clang-format

@@ -22,7 +22,7 @@ IncludeBlocks: Regroup
 IncludeCategories:
   - Regex:           '^[<"]cmConfigure\.h'
     Priority:        -1
-  - Regex:           '^(<|")cm/'
+  - Regex:           '^(<|")cm(ext)?/'
     Priority:        2
   - Regex:           '^(<|")windows\.h'
     Priority:        3

+ 1 - 1
Source/Checks/cm_cxx14_check.cmake

@@ -1,5 +1,5 @@
 set(CMake_CXX14_BROKEN 0)
-if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI")
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI|Intel")
   if(NOT CMAKE_CXX14_STANDARD_COMPILE_OPTION)
     set(CMake_CXX14_WORKS 0)
   endif()

+ 1 - 1
Source/Checks/cm_cxx17_check.cmake

@@ -1,5 +1,5 @@
 set(CMake_CXX17_BROKEN 0)
-if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI")
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI|Intel")
   if(NOT CMAKE_CXX17_STANDARD_COMPILE_OPTION)
     set(CMake_CXX17_WORKS 0)
   endif()

+ 10 - 0
Source/Checks/cm_cxx17_check.cpp

@@ -8,6 +8,13 @@
 #  include <comdef.h>
 #endif
 
+template <typename T,
+          typename std::invoke_result<decltype(&T::get), T>::type = nullptr>
+typename T::pointer get_ptr(T& item)
+{
+  return item.get();
+}
+
 int main()
 {
   int a[] = { 0, 1, 2 };
@@ -20,6 +27,9 @@ int main()
 
   std::unique_ptr<int> u(new int(0));
 
+  // Intel compiler do not handle correctly 'decltype' inside 'invoke_result'
+  get_ptr(u);
+
 #ifdef _MSC_VER
   // clang-cl has problems instantiating this constructor in C++17 mode
   //  error: indirection requires pointer operand ('const _GUID' invalid)

+ 1 - 0
Tests/CMakeLib/CMakeLists.txt

@@ -25,6 +25,7 @@ set(CMakeLib_TESTS
   testUVProcessChain.cxx
   testUVRAII.cxx
   testUVStreambuf.cxx
+  testCMExtMemory.cxx
   )
 
 add_executable(testUVProcessChainHelper testUVProcessChainHelper.cxx)

+ 65 - 0
Tests/CMakeLib/testCMExtMemory.cxx

@@ -0,0 +1,65 @@
+#include <iostream>
+#include <memory>
+
+#include <cmext/memory>
+
+namespace {
+class Base
+{
+public:
+  virtual ~Base() = default;
+};
+
+class Derived : public Base
+{
+public:
+  ~Derived() = default;
+
+  void method() {}
+};
+
+template <typename T>
+class Wrapper
+{
+public:
+  Wrapper(T* v)
+    : value(v)
+  {
+  }
+  ~Wrapper() { delete value; }
+
+  T* get() const { return value; }
+
+private:
+  T* value;
+};
+
+bool testReferenceCast()
+{
+  std::cout << "testReferenceCast()" << std::endl;
+
+  std::unique_ptr<Base> u(new Derived);
+  cm::static_reference_cast<Derived>(u).method();
+  cm::dynamic_reference_cast<Derived>(u).method();
+
+  std::shared_ptr<Base> s(new Derived);
+  cm::static_reference_cast<Derived>(s).method();
+  cm::dynamic_reference_cast<Derived>(s).method();
+
+  // can also be used with custom wrappers
+  Wrapper<Base> w(new Derived);
+  cm::static_reference_cast<Derived>(w).method();
+  cm::dynamic_reference_cast<Derived>(w).method();
+
+  return true;
+}
+}
+
+int testCMExtMemory(int /*unused*/, char* /*unused*/ [])
+{
+  if (!testReferenceCast()) {
+    return 1;
+  }
+
+  return 0;
+}

+ 1 - 0
Utilities/std/.gitattributes

@@ -1 +1,2 @@
 cm/* our-c-style
+cmext/* our-c-style

+ 46 - 0
Utilities/std/cm/type_traits

@@ -0,0 +1,46 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cm_type_traits
+#define cm_type_traits
+
+#include <type_traits> // IWYU pragma: export
+
+namespace cm {
+
+#if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
+
+// Miscellaneous transformations
+template <bool B, typename T = void>
+using enable_if_t = std::enable_if_t<B, T>;
+
+#else
+
+// Miscellaneous transformations
+template <bool B, typename T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+#endif
+
+#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703)
+
+// Miscellaneous transformations
+using std::invoke_result;
+using std::invoke_result_t;
+
+#else
+
+// Miscellaneous transformations
+template <typename F, typename... ArgTypes>
+using invoke_result = std::result_of<F(ArgTypes...)>;
+
+template <class F, typename... ArgTypes>
+using invoke_result_t = typename invoke_result<F, ArgTypes...>::type;
+
+#endif
+
+} // namespace cm
+
+#endif

+ 32 - 0
Utilities/std/cmext/memory

@@ -0,0 +1,32 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmext_memory
+#define cmext_memory
+
+#include <cm/type_traits>
+
+namespace cm {
+
+template <typename T, typename O,
+          cm::enable_if_t<
+            std::is_pointer<cm::invoke_result_t<decltype(&O::get), O>>::value,
+            int> = 0>
+T& static_reference_cast(O& item)
+{
+  return *(static_cast<T*>(item.get()));
+}
+template <typename T, typename O,
+          cm::enable_if_t<
+            std::is_pointer<cm::invoke_result_t<decltype(&O::get), O>>::value,
+            int> = 0>
+T& dynamic_reference_cast(O& item)
+{
+  return *(dynamic_cast<T*>(item.get()));
+}
+
+} // namespace cm
+
+#endif