From fc3b4caa2e6a1970c75830445ef4aa7d03c5a533 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Mon, 18 Nov 2019 19:15:49 +0100 Subject: Memory management: cast functions for managed pointers --- .clang-format | 2 +- Source/Checks/cm_cxx14_check.cmake | 2 +- Source/Checks/cm_cxx17_check.cmake | 2 +- Source/Checks/cm_cxx17_check.cpp | 10 ++++++ Tests/CMakeLib/CMakeLists.txt | 1 + Tests/CMakeLib/testCMExtMemory.cxx | 65 ++++++++++++++++++++++++++++++++++++++ Utilities/std/.gitattributes | 1 + Utilities/std/cm/type_traits | 46 +++++++++++++++++++++++++++ Utilities/std/cmext/memory | 32 +++++++++++++++++++ 9 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 Tests/CMakeLib/testCMExtMemory.cxx create mode 100644 Utilities/std/cm/type_traits create mode 100644 Utilities/std/cmext/memory diff --git a/.clang-format b/.clang-format index 0c7d6b0..a7f049a 100644 --- a/.clang-format +++ b/.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 diff --git a/Source/Checks/cm_cxx14_check.cmake b/Source/Checks/cm_cxx14_check.cmake index 8e9c2c7..e5656bf 100644 --- a/Source/Checks/cm_cxx14_check.cmake +++ b/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() diff --git a/Source/Checks/cm_cxx17_check.cmake b/Source/Checks/cm_cxx17_check.cmake index 9e1d9c3..dba3eaf 100644 --- a/Source/Checks/cm_cxx17_check.cmake +++ b/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() diff --git a/Source/Checks/cm_cxx17_check.cpp b/Source/Checks/cm_cxx17_check.cpp index 29863b1..abbe22c 100644 --- a/Source/Checks/cm_cxx17_check.cpp +++ b/Source/Checks/cm_cxx17_check.cpp @@ -8,6 +8,13 @@ # include #endif +template ::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 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) diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt index 840afc1..976c924 100644 --- a/Tests/CMakeLib/CMakeLists.txt +++ b/Tests/CMakeLib/CMakeLists.txt @@ -25,6 +25,7 @@ set(CMakeLib_TESTS testUVProcessChain.cxx testUVRAII.cxx testUVStreambuf.cxx + testCMExtMemory.cxx ) add_executable(testUVProcessChainHelper testUVProcessChainHelper.cxx) diff --git a/Tests/CMakeLib/testCMExtMemory.cxx b/Tests/CMakeLib/testCMExtMemory.cxx new file mode 100644 index 0000000..6663c17 --- /dev/null +++ b/Tests/CMakeLib/testCMExtMemory.cxx @@ -0,0 +1,65 @@ +#include +#include + +#include + +namespace { +class Base +{ +public: + virtual ~Base() = default; +}; + +class Derived : public Base +{ +public: + ~Derived() = default; + + void method() {} +}; + +template +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 u(new Derived); + cm::static_reference_cast(u).method(); + cm::dynamic_reference_cast(u).method(); + + std::shared_ptr s(new Derived); + cm::static_reference_cast(s).method(); + cm::dynamic_reference_cast(s).method(); + + // can also be used with custom wrappers + Wrapper w(new Derived); + cm::static_reference_cast(w).method(); + cm::dynamic_reference_cast(w).method(); + + return true; +} +} + +int testCMExtMemory(int /*unused*/, char* /*unused*/ []) +{ + if (!testReferenceCast()) { + return 1; + } + + return 0; +} diff --git a/Utilities/std/.gitattributes b/Utilities/std/.gitattributes index cd20549..789a754 100644 --- a/Utilities/std/.gitattributes +++ b/Utilities/std/.gitattributes @@ -1 +1,2 @@ cm/* our-c-style +cmext/* our-c-style diff --git a/Utilities/std/cm/type_traits b/Utilities/std/cm/type_traits new file mode 100644 index 0000000..6d7a2c0 --- /dev/null +++ b/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 // IWYU pragma: export + +namespace cm { + +#if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) + +// Miscellaneous transformations +template +using enable_if_t = std::enable_if_t; + +#else + +// Miscellaneous transformations +template +using enable_if_t = typename std::enable_if::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 +using invoke_result = std::result_of; + +template +using invoke_result_t = typename invoke_result::type; + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cmext/memory b/Utilities/std/cmext/memory new file mode 100644 index 0000000..540a3de --- /dev/null +++ b/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 + +namespace cm { + +template >::value, + int> = 0> +T& static_reference_cast(O& item) +{ + return *(static_cast(item.get())); +} +template >::value, + int> = 0> +T& dynamic_reference_cast(O& item) +{ + return *(dynamic_cast(item.get())); +} + +} // namespace cm + +#endif -- cgit v0.12