Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Swiftb0y committed Sep 14, 2023
1 parent f5666a7 commit 72d5eae
Showing 1 changed file with 50 additions and 4 deletions.
54 changes: 50 additions & 4 deletions src/util/parented_ptr.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,65 @@
#pragma once

#include <QPointer>
#include <concepts>
#include <memory>
#include <type_traits>

#include "util/assert.h"

namespace mixxx {

/// this type trait tries its best to verify more statically that paranted_ptr's
/// are only used on QObject derived types
/// It is conservative by design. If it fails with a false positive, it can be
/// customized explicitly by adding the following explicit specialization:
/// template<> struct uses_qobject_tree<YourType> : std::true_type {};
template<typename T, typename... Args>
struct uses_qobject_tree
: public std::bool_constant<std::derived_from<T, QObject> &&

Check failure on line 19 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 x64

no member named 'derived_from' in namespace 'std'

Check failure on line 19 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 x64

'T' does not refer to a value

Check failure on line 19 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 arm64

no member named 'derived_from' in namespace 'std'

Check failure on line 19 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 arm64

'T' does not refer to a value
std::is_invocable_r_v<T, T(Args...), Args...>> {};

Check failure on line 20 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 x64

expected '{' after base class list

Check failure on line 20 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 x64

expected ';' after struct

Check failure on line 20 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 x64

expected ')'

Check failure on line 20 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 x64

C++ requires a type specifier for all declarations

Check failure on line 20 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 x64

expected ';' after top level declarator

Check failure on line 20 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 arm64

expected '{' after base class list

Check failure on line 20 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 arm64

expected ';' after struct

Check failure on line 20 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 arm64

expected ')'

Check failure on line 20 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 arm64

C++ requires a type specifier for all declarations

Check failure on line 20 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 arm64

expected ';' after top level declarator

/// convenience alias for uses_qobject_tree in the _v prefix style of the STL
template<typename T, typename... Args>
inline constexpr bool uses_qobject_tree_v = uses_qobject_tree<T, Args...>::value;

Check failure on line 24 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 x64

no member named 'value' in 'mixxx::uses_qobject_tree<mixxx::test::Derived>'

Check failure on line 24 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 x64

no member named 'value' in 'mixxx::uses_qobject_tree<mixxx::test::DerivedWithArgs, QObject *>'

Check failure on line 24 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 arm64

no member named 'value' in 'mixxx::uses_qobject_tree<mixxx::test::Derived>'

Check failure on line 24 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 arm64

no member named 'value' in 'mixxx::uses_qobject_tree<mixxx::test::DerivedWithArgs, QObject *>'

template<typename T, typename... Args>
concept UsesQObjectTree = uses_qobject_tree_v<T, Args...>;

Check failure on line 27 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 x64

substitution into constraint expression resulted in a non-constant expression

Check failure on line 27 in src/util/parented_ptr.h

View workflow job for this annotation

GitHub Actions / macOS 11 arm64

substitution into constraint expression resulted in a non-constant expression

// inline unit tests :)
namespace test {

struct Derived : public QObject {
};
struct DerivedWithArgs : public QObject {
DerivedWithArgs(QObject*) {
}
};
struct Plain {};
struct PlainWithArgs {
PlainWithArgs(QObject*) {
}
};

// static_assert(UsesQObjectTree<QObject>); TODO FIX
static_assert(UsesQObjectTree<Derived>);
static_assert(UsesQObjectTree<DerivedWithArgs, QObject*>);
// static_assert(not UsesQObjectTree<DerivedWithArgs, int>); TODO FIX
static_assert(not UsesQObjectTree<Plain>);
static_assert(not UsesQObjectTree<PlainWithArgs, QObject*>);
} // namespace test

} // namespace mixxx

// Use this wrapper class to clearly represent a raw pointer that is owned by the QT object tree.
// Objects which both derive from QObject AND have a parent object, have their lifetime governed by
// the QT object tree, and thus such pointers do not require a manual delete to free the heap memory
// when they go out of scope.
//
// NOTE: A parented_ptr must not dangle! Therefore, the lifetime of the parent must exceed the
// lifetime of the parented_ptr.
// note that we can not constraint on UsesQObjectTree here as this would make
// it incompatible with incomplete types (e.g. forward declared types)
template<typename T>
class parented_ptr final {
public:
Expand Down Expand Up @@ -89,11 +137,9 @@ class parented_ptr final {
private:
T* m_ptr;

template<typename>
friend class parented_ptr;
};

template<typename T, typename... Args>
template<mixxx::UsesQObjectTree T, typename... Args>
inline parented_ptr<T> make_parented(Args&&... args) {
return parented_ptr<T>(new T(std::forward<Args>(args)...));
}
Expand All @@ -106,7 +152,7 @@ inline parented_ptr<T> make_parented(Args&&... args) {
// where `child` is a `std::unique_ptr`. After the call, the created `parented_ptr` will
// automatically be destructed such that the DEBUG_ASSERT that checks whether a parent exists is
// triggered.
template<typename T>
template<mixxx::UsesQObjectTree T>
inline parented_ptr<T> to_parented(std::unique_ptr<T>& u) noexcept {
// the DEBUG_ASSERT in the parented_ptr constructor will catch cases where the unique_ptr should
// not have been released
Expand Down

0 comments on commit 72d5eae

Please sign in to comment.