diff options
-rw-r--r-- | .clang-format | 2 | ||||
-rw-r--r-- | Source/Checks/cm_cxx14_check.cmake | 2 | ||||
-rw-r--r-- | Source/Checks/cm_cxx17_check.cmake | 2 | ||||
-rw-r--r-- | Source/Checks/cm_cxx17_check.cpp | 10 | ||||
-rw-r--r-- | Tests/CMakeLib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Tests/CMakeLib/testCMExtMemory.cxx | 65 | ||||
-rw-r--r-- | Utilities/std/.gitattributes | 1 | ||||
-rw-r--r-- | Utilities/std/cm/type_traits | 46 | ||||
-rw-r--r-- | Utilities/std/cmext/memory | 32 |
9 files changed, 158 insertions, 3 deletions
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 <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) 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 <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; +} 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 <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 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 <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 |