AK: Move "conditional xtor" pattern into a macro

`Optional` and `Variant` both use essentially the same pattern of only
declaring a copy constructor/move constructor/destructor and copy/move
assignment operator if all of their template parameters have one.

Let's move these into a macro to avoid code duplication and to give a
name to the thing we are trying to accomplish.
This commit is contained in:
Jonne Ransijn 2024-10-30 13:44:20 +01:00 committed by Andreas Kling
parent a70ed6a2ad
commit fcdf3014f1
Notes: github-actions[bot] 2024-10-31 22:27:29 +00:00
3 changed files with 51 additions and 46 deletions

View file

@ -25,3 +25,46 @@ public: \
public: \
c(c const&) = default; \
c& operator=(c const&) = default
#define AK_MAKE_CONDITIONALLY_NONMOVABLE(c, ...) \
public: \
c(c&&) \
requires(!(AK::Detail::IsMoveConstructible __VA_ARGS__)) \
= delete; \
c& operator=(c&&) \
requires(!(AK::Detail::IsMoveConstructible __VA_ARGS__) \
|| !(AK::Detail::IsDestructible __VA_ARGS__)) \
= delete
#define AK_MAKE_CONDITIONALLY_MOVABLE(c, T) \
AK_MAKE_CONDITIONALLY_NONMOVABLE(c, T); \
c(c&&) = default; \
c& operator=(c&&) = default
#define AK_MAKE_CONDITIONALLY_NONCOPYABLE(c, ...) \
public: \
c(c const&) \
requires(!(AK::Detail::IsCopyConstructible __VA_ARGS__)) \
= delete; \
c& operator=(c const&) \
requires(!(AK::Detail::IsCopyConstructible __VA_ARGS__) \
|| !(AK::Detail::IsDestructible __VA_ARGS__)) \
= delete
#define AK_MAKE_CONDITIONALLY_COPYABLE(c, ...) \
AK_MAKE_CONDITIONALLY_NONCOPYABLE(c, __VA_ARGS__); \
c(c const&) = default; \
c& operator=(c const&) = default
#define AK_MAKE_CONDITIONALLY_NONDESTRUCTIBLE(c, ...) \
public: \
~c() \
requires(!(AK::Detail::IsDestructible __VA_ARGS__)) \
= delete
#define AK_MAKE_CONDITIONALLY_DESTRUCTIBLE(c, ...) \
public: \
~c() \
requires(!(AK::Detail::IsDestructible __VA_ARGS__)) \
= delete; \
~c() = default

View file

@ -8,6 +8,7 @@
#pragma once
#include <AK/Assertions.h>
#include <AK/Noncopyable.h>
#include <AK/StdLibExtras.h>
#include <AK/Try.h>
#include <AK/Types.h>
@ -189,28 +190,9 @@ public:
return *this;
}
Optional(Optional const& other)
requires(!IsCopyConstructible<T>)
= delete;
Optional(Optional const& other) = default;
Optional(Optional&& other)
requires(!IsMoveConstructible<T>)
= delete;
Optional& operator=(Optional const&)
requires(!IsCopyConstructible<T> || !IsDestructible<T>)
= delete;
Optional& operator=(Optional const&) = default;
Optional& operator=(Optional&& other)
requires(!IsMoveConstructible<T> || !IsDestructible<T>)
= delete;
~Optional()
requires(!IsDestructible<T>)
= delete;
~Optional() = default;
AK_MAKE_CONDITIONALLY_COPYABLE(Optional, <T>);
AK_MAKE_CONDITIONALLY_NONMOVABLE(Optional, <T>);
AK_MAKE_CONDITIONALLY_DESTRUCTIBLE(Optional, <T>);
ALWAYS_INLINE Optional(Optional const& other)
requires(!IsTriviallyCopyConstructible<T>)

View file

@ -8,6 +8,7 @@
#include <AK/Array.h>
#include <AK/BitCast.h>
#include <AK/Noncopyable.h>
#include <AK/StdLibExtras.h>
#include <AK/TypeList.h>
@ -267,30 +268,9 @@ public:
{
}
Variant(Variant const&)
requires(!(IsCopyConstructible<Ts> && ...))
= delete;
Variant(Variant const&) = default;
Variant(Variant&&)
requires(!(IsMoveConstructible<Ts> && ...))
= delete;
Variant(Variant&&) = default;
~Variant()
requires(!(IsDestructible<Ts> && ...))
= delete;
~Variant() = default;
Variant& operator=(Variant const&)
requires(!(IsCopyConstructible<Ts> && ...) || !(IsDestructible<Ts> && ...))
= delete;
Variant& operator=(Variant const&) = default;
Variant& operator=(Variant&&)
requires(!(IsMoveConstructible<Ts> && ...) || !(IsDestructible<Ts> && ...))
= delete;
Variant& operator=(Variant&&) = default;
AK_MAKE_CONDITIONALLY_COPYABLE(Variant, <Ts>&&...);
AK_MAKE_CONDITIONALLY_MOVABLE(Variant, <Ts>&&...);
AK_MAKE_CONDITIONALLY_DESTRUCTIBLE(Variant, <Ts>&&...);
ALWAYS_INLINE Variant(Variant const& old)
requires(!(IsTriviallyCopyConstructible<Ts> && ...))