1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-14 02:08:27 +08:00

Memory management: cast functions for managed pointers

This commit is contained in:
Marc Chevrier
2019-11-18 19:15:49 +01:00
parent 7046a52198
commit fc3b4caa2e
9 changed files with 158 additions and 3 deletions

View File

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

View File

@@ -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()

View File

@@ -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()

View File

@@ -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)

View File

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

View File

@@ -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;
}

View File

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

View File

@@ -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

View File

@@ -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