Skip to content

Commit

Permalink
Add DependencyRef<Handle, Manager> alias for
Browse files Browse the repository at this point in the history
`Dependency<Handle, TargetRefT<Manager>>`, which commonly appears in
functions accepting any initializer deduced from a function argument.

Rename `IsValidDependency` to `SupportsDependency`.

Add `Target{,Ref}SupportsDependency` which apply `Target{,Ref}T` to `Manager`
to be stored.

These predicates also verify that the stored object can be constructed from the
appropriate initializer. This excludes passing already constructed objects of
immovable types, and before C++17 this excludes all usages of immovable types.

Use `SupportsDependency` etc. in `Any{,Ref,Initializer}`.

PiperOrigin-RevId: 697950623
  • Loading branch information
QrczakMK committed Nov 19, 2024
1 parent dc364ce commit aaf91d0
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 55 deletions.
20 changes: 10 additions & 10 deletions riegeli/base/any.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ class
// Otherwise returns `nullptr`.
template <
typename Manager,
std::enable_if_t<IsValidDependency<Handle, Manager>::value, int> = 0>
std::enable_if_t<SupportsDependency<Handle, Manager&&>::value, int> = 0>
Manager* GetIf() ABSL_ATTRIBUTE_LIFETIME_BOUND;
template <
typename Manager,
std::enable_if_t<IsValidDependency<Handle, Manager>::value, int> = 0>
std::enable_if_t<SupportsDependency<Handle, Manager&&>::value, int> = 0>
const Manager* GetIf() const ABSL_ATTRIBUTE_LIFETIME_BOUND;

// A variant of `GetIf()` with the expected type passed as a `TypeId`.
Expand Down Expand Up @@ -250,14 +250,14 @@ class
typename Manager,
std::enable_if_t<
absl::conjunction<absl::negation<std::is_same<TargetT<Manager>, Any>>,
IsValidDependency<Handle, TargetT<Manager>>>::value,
TargetSupportsDependency<Handle, Manager>>::value,
int> = 0>
/*implicit*/ Any(Manager&& manager);
template <
typename Manager,
std::enable_if_t<
absl::conjunction<absl::negation<std::is_same<TargetT<Manager>, Any>>,
IsValidDependency<Handle, TargetT<Manager>>>::value,
TargetSupportsDependency<Handle, Manager>>::value,
int> = 0>
Any& operator=(Manager&& manager);
template <
Expand Down Expand Up @@ -403,7 +403,7 @@ class
std::enable_if_t<
absl::conjunction<
absl::negation<std::is_same<std::decay_t<Manager>, AnyRef>>,
IsValidDependency<Handle, Manager&&>>::value,
SupportsDependency<Handle, Manager&&>>::value,
int> = 0>
/*implicit*/ AnyRef(Manager&& manager ABSL_ATTRIBUTE_LIFETIME_BOUND);

Expand Down Expand Up @@ -638,15 +638,15 @@ inline void AnyBase<Handle, inline_size, inline_align>::Reset() {

template <typename Handle, size_t inline_size, size_t inline_align>
template <typename Manager,
std::enable_if_t<IsValidDependency<Handle, Manager>::value, int>>
std::enable_if_t<SupportsDependency<Handle, Manager&&>::value, int>>
inline Manager* AnyBase<Handle, inline_size, inline_align>::GetIf()
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return static_cast<Manager*>(GetIf(TypeId::For<Manager>()));
}

template <typename Handle, size_t inline_size, size_t inline_align>
template <typename Manager,
std::enable_if_t<IsValidDependency<Handle, Manager>::value, int>>
std::enable_if_t<SupportsDependency<Handle, Manager&&>::value, int>>
inline const Manager* AnyBase<Handle, inline_size, inline_align>::GetIf() const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return static_cast<const Manager*>(GetIf(TypeId::For<Manager>()));
Expand All @@ -673,7 +673,7 @@ template <
absl::conjunction<
absl::negation<std::is_same<
TargetT<Manager>, Any<Handle, inline_size, inline_align>>>,
IsValidDependency<Handle, TargetT<Manager>>>::value,
TargetSupportsDependency<Handle, Manager>>::value,
int>>
inline Any<Handle, inline_size, inline_align>::Any(Manager&& manager) {
this->template Initialize<TargetT<Manager>>(std::forward<Manager>(manager));
Expand All @@ -686,7 +686,7 @@ template <
absl::conjunction<
absl::negation<std::is_same<
TargetT<Manager>, Any<Handle, inline_size, inline_align>>>,
IsValidDependency<Handle, TargetT<Manager>>>::value,
TargetSupportsDependency<Handle, Manager>>::value,
int>>
inline Any<Handle, inline_size, inline_align>&
Any<Handle, inline_size, inline_align>::operator=(Manager&& manager) {
Expand Down Expand Up @@ -716,7 +716,7 @@ template <
std::enable_if_t<
absl::conjunction<
absl::negation<std::is_same<std::decay_t<Manager>, AnyRef<Handle>>>,
IsValidDependency<Handle, Manager&&>>::value,
SupportsDependency<Handle, Manager&&>>::value,
int>>
inline AnyRef<Handle>::AnyRef(Manager&& manager ABSL_ATTRIBUTE_LIFETIME_BOUND) {
this->template Initialize<Manager&&>(std::forward<Manager>(manager));
Expand Down
2 changes: 1 addition & 1 deletion riegeli/base/any_initializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class AnyInitializer {
std::is_same<std::decay_t<Manager>, AnyInitializer>>,
absl::disjunction<
any_internal::IsAny<Handle, TargetT<Manager>>,
IsValidDependency<Handle, TargetT<Manager>>>>::value,
TargetSupportsDependency<Handle, Manager>>>::value,
int> = 0>
/*implicit*/ AnyInitializer(Manager&& manager ABSL_ATTRIBUTE_LIFETIME_BOUND)
: construct_(ConstructMethod<Manager>),
Expand Down
102 changes: 78 additions & 24 deletions riegeli/base/dependency.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "riegeli/base/assert.h"
#include "riegeli/base/compare.h"
#include "riegeli/base/dependency_manager.h"
#include "riegeli/base/initializer.h"
#include "riegeli/base/to_string_view.h"
#include "riegeli/base/type_id.h"
#include "riegeli/base/type_traits.h"
Expand Down Expand Up @@ -398,14 +399,14 @@ class DependencyImpl<

namespace dependency_internal {

// `IsValidDependencyImpl<Handle, Manager>::value` is `true` when
// `SupportsDependencyImpl<Handle, Manager>::value` is `true` when
// `DependencyImpl<Handle, Manager>` is defined.

template <typename Handle, typename Manager, typename Enable = void>
struct IsValidDependencyImpl : std::false_type {};
struct SupportsDependencyImpl : std::false_type {};

template <typename Handle, typename Manager>
struct IsValidDependencyImpl<
struct SupportsDependencyImpl<
Handle, Manager,
absl::void_t<
decltype(std::declval<const DependencyImpl<Handle, Manager>&>().get())>>
Expand All @@ -425,7 +426,7 @@ class DependencyDefault;
template <typename Handle, typename Manager>
class DependencyDefault<
Handle, Manager,
std::enable_if_t<IsValidDependencyImpl<Handle, Manager>::value>>
std::enable_if_t<SupportsDependencyImpl<Handle, Manager>::value>>
: public DependencyImpl<Handle, Manager> {
public:
using DependencyDefault::DependencyImpl::DependencyImpl;
Expand Down Expand Up @@ -456,7 +457,7 @@ template <typename Handle, typename Manager>
class DependencyDefault<
Handle, Manager,
std::enable_if_t<absl::conjunction<
absl::negation<IsValidDependencyImpl<Handle, Manager>>,
absl::negation<SupportsDependencyImpl<Handle, Manager>>,
std::is_pointer<DependencyManagerPtr<Manager>>,
std::is_constructible<Handle, DependencyManagerRef<Manager>>>::value>>
: public DependencyManager<Manager> {
Expand Down Expand Up @@ -505,7 +506,7 @@ template <typename Handle, typename Manager>
class DependencyDefault<
Handle, Manager,
std::enable_if_t<absl::conjunction<
absl::negation<IsValidDependencyImpl<Handle, Manager>>,
absl::negation<SupportsDependencyImpl<Handle, Manager>>,
absl::negation<absl::conjunction<
std::is_pointer<DependencyManagerPtr<Manager>>,
std::is_constructible<Handle, DependencyManagerRef<Manager>>>>,
Expand Down Expand Up @@ -547,12 +548,12 @@ class DependencyDefault<
~DependencyDefault() = default;
};

// `IsValidDependencyDefault<Handle, Manager>::value` is `true` when
// `SupportsDependencyDefault<Handle, Manager>::value` is `true` when
// `DependencyDefault<Handle, Manager, Manager&>` is defined.
template <typename Handle, typename Manager>
struct IsValidDependencyDefault
struct SupportsDependencyDefault
: absl::disjunction<
dependency_internal::IsValidDependencyImpl<Handle, Manager>,
dependency_internal::SupportsDependencyImpl<Handle, Manager>,
absl::conjunction<
std::is_pointer<DependencyManagerPtr<Manager>>,
std::is_constructible<Handle, DependencyManagerRef<Manager>>>,
Expand All @@ -574,7 +575,7 @@ class DependencyDeref;
template <typename Handle, typename Manager>
class DependencyDeref<
Handle, Manager,
std::enable_if_t<IsValidDependencyDefault<Handle, Manager>::value>>
std::enable_if_t<SupportsDependencyDefault<Handle, Manager>::value>>
: public DependencyDefault<Handle, Manager> {
public:
using DependencyDeref::DependencyDefault::DependencyDefault;
Expand All @@ -592,16 +593,16 @@ class DependencyDeref<
// Specialization of `DependencyDeref<Handle, Manager>` when
// `DependencyDefault<Handle, Manager>` is not defined,
// `Manager` is a reference, and
// `DependencyDefault<Handle, absl::remove_cvref_t<Manager>>`
// is defined: delegate to the latter.
// `DependencyDefault<Handle, absl::remove_cvref_t<Manager>>` is defined:
// delegate to the latter.
template <typename Handle, typename Manager>
class DependencyDeref<
Handle, Manager,
std::enable_if_t<absl::conjunction<
std::is_reference<Manager>,
absl::negation<IsValidDependencyDefault<Handle, Manager>>,
IsValidDependencyDefault<Handle,
absl::remove_cvref_t<Manager>>>::value>>
absl::negation<SupportsDependencyDefault<Handle, Manager>>,
SupportsDependencyDefault<Handle,
absl::remove_cvref_t<Manager>>>::value>>
: public DependencyDefault<Handle, absl::remove_cvref_t<Manager>> {
public:
using DependencyDeref::DependencyDefault::DependencyDefault;
Expand All @@ -616,18 +617,66 @@ class DependencyDeref<
~DependencyDeref() = default;
};

} // namespace dependency_internal

// `IsValidDependency<Handle, Manager>::value` is `true` when
// `Dependency<Handle, Manager>` is defined.
// `SupportsDependencyDeref<Handle, Manager>::value` is `true` when
// `DependencyDeref<Handle, Manager>` is defined.
template <typename Handle, typename Manager>
struct IsValidDependency
struct SupportsDependencyDeref
: absl::disjunction<
dependency_internal::IsValidDependencyDefault<Handle, Manager>,
SupportsDependencyDefault<Handle, Manager>,
absl::conjunction<std::is_reference<Manager>,
dependency_internal::IsValidDependencyDefault<
SupportsDependencyDefault<
Handle, absl::remove_cvref_t<Manager>>>> {};

} // namespace dependency_internal

// `SupportsDependency<Handle, Manager>::value` is `true` when
// `Dependency<Handle, Manager>` is defined and usable, i.e. constructible from
// `Initializer<Manager>`.
//
// An immovable `Manager` is usable since C++17 which guarantees copy elision.
// In this case the `Initializer<Manager>` must have been constructed from
// `riegeli::Maker()` or `riegeli::Invoker()`, not from an already constructed
// object.
template <typename Handle, typename Manager>
struct SupportsDependency
: absl::conjunction<
dependency_internal::SupportsDependencyDeref<Handle, Manager>
#if !__cpp_guaranteed_copy_elision
,
std::is_convertible<Manager&&, Manager>
#endif
> {
};

// `TargetSupportsDependency<Handle, Manager>::value` is `true` when
// `Dependency<Handle, TargetT<Manager>>` is defined and constructible from
// `Manager&&`.
//
// An immovable `TargetT<Manager>` is usable since C++17 which guarantees
// copy elision. In this case the `Dependency` must be initialized with
// `riegeli::Maker()` or `riegeli::Invoker()`, possibly behind `Initializer`,
// not from an already constructed object.
template <typename Handle, typename Manager>
struct TargetSupportsDependency
: absl::conjunction<
SupportsDependency<Handle, TargetT<Manager>>,
std::is_convertible<Manager&&, Initializer<TargetT<Manager>>>> {};

// `TargetRefSupportsDependency<Handle, Manager>::value` is `true` when
// `DependencyRef<Handle, Manager>` i.e.
// `Dependency<Handle, TargetRefT<Manager>>` is defined and constructible from
// `Manager&&`.
//
// An immovable `TargetRefT<Manager>` is usable since C++17 which guarantees
// copy elision. In this case the `Dependency` must be initialized with
// `riegeli::Maker()` or `riegeli::Invoker()`, possibly behind `Initializer`,
// not from an already constructed object.
template <typename Handle, typename Manager>
struct TargetRefSupportsDependency
: absl::conjunction<
SupportsDependency<Handle, TargetRefT<Manager>>,
std::is_convertible<Manager&&, Initializer<TargetRefT<Manager>>>> {};

namespace dependency_internal {

template <bool value>
Expand Down Expand Up @@ -778,13 +827,13 @@ class DependencyDerived
}

template <typename OtherManager,
std::enable_if_t<IsValidDependency<Handle, OtherManager&&>::value,
std::enable_if_t<SupportsDependency<Handle, OtherManager&&>::value,
int> = 0>
OtherManager* GetIf() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return GetIfImpl<OtherManager>();
}
template <typename OtherManager,
std::enable_if_t<IsValidDependency<Handle, OtherManager&&>::value,
std::enable_if_t<SupportsDependency<Handle, OtherManager&&>::value,
int> = 0>
const OtherManager* GetIf() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return GetIfImpl<OtherManager>();
Expand Down Expand Up @@ -944,6 +993,11 @@ class
Dependency& operator=(Dependency&& that) = default;
};

// `DependencyRef<Handle, Manager>` is an alias for
// `Dependency<Handle, TargetRefT<Manager>>`.
template <typename Handle, typename Manager>
using DependencyRef = Dependency<Handle, TargetRefT<Manager>>;

namespace dependency_internal {

// `AlwaysFalse<T...>::value` is `false`, but formally depends on `T...`.
Expand Down
Loading

0 comments on commit aaf91d0

Please sign in to comment.