summaryrefslogtreecommitdiff
path: root/AK
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-02-23 09:41:26 +0100
committerAndreas Kling <kling@serenityos.org>2021-02-23 17:42:05 +0100
commit145923bdc951bef4c6c323da80c883a98377b982 (patch)
tree0b615287dacee5daf09d9f062e2a7da2177ea977 /AK
parentde52fe6156e1e6f862e6ed520d6782f86ae996d6 (diff)
downloadserenity-145923bdc951bef4c6c323da80c883a98377b982.zip
AK: Slap Optional with the ALWAYS_INLINE stick
I saw some Optional constructors when profiling the dynamic loader and that seemed silly since we can inline them at no/little cost.
Diffstat (limited to 'AK')
-rw-r--r--AK/Optional.h39
1 files changed, 17 insertions, 22 deletions
diff --git a/AK/Optional.h b/AK/Optional.h
index 057c16fcf4..8d385e8ea4 100644
--- a/AK/Optional.h
+++ b/AK/Optional.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,28 +36,28 @@ namespace AK {
template<typename T>
class alignas(T) [[nodiscard]] Optional {
public:
- Optional() = default;
+ ALWAYS_INLINE Optional() = default;
- Optional(const T& value)
+ ALWAYS_INLINE Optional(const T& value)
: m_has_value(true)
{
new (&m_storage) T(value);
}
template<typename U>
- Optional(const U& value)
+ ALWAYS_INLINE Optional(const U& value)
: m_has_value(true)
{
new (&m_storage) T(value);
}
- Optional(T&& value)
+ ALWAYS_INLINE Optional(T&& value)
: m_has_value(true)
{
new (&m_storage) T(move(value));
}
- Optional(Optional&& other)
+ ALWAYS_INLINE Optional(Optional&& other)
: m_has_value(other.m_has_value)
{
if (other.has_value()) {
@@ -66,15 +66,15 @@ public:
}
}
- Optional(const Optional& other)
+ ALWAYS_INLINE Optional(const Optional& other)
: m_has_value(other.m_has_value)
{
if (m_has_value) {
- new (&m_storage) T(other.value_without_consume_state());
+ new (&m_storage) T(other.value());
}
}
- Optional& operator=(const Optional& other)
+ ALWAYS_INLINE Optional& operator=(const Optional& other)
{
if (this != &other) {
clear();
@@ -86,7 +86,7 @@ public:
return *this;
}
- Optional& operator=(Optional&& other)
+ ALWAYS_INLINE Optional& operator=(Optional&& other)
{
if (this != &other) {
clear();
@@ -98,7 +98,7 @@ public:
}
template<typename O>
- bool operator==(const Optional<O>& other) const
+ ALWAYS_INLINE bool operator==(const Optional<O>& other) const
{
return has_value() == other.has_value() && (!has_value() || value() == other.value());
}
@@ -134,7 +134,8 @@ public:
[[nodiscard]] ALWAYS_INLINE const T& value() const
{
- return value_without_consume_state();
+ ASSERT(m_has_value);
+ return *reinterpret_cast<const T*>(&m_storage);
}
[[nodiscard]] T release_value()
@@ -153,19 +154,13 @@ public:
return fallback;
}
- const T& operator*() const { return value(); }
- T& operator*() { return value(); }
+ ALWAYS_INLINE const T& operator*() const { return value(); }
+ ALWAYS_INLINE T& operator*() { return value(); }
- const T* operator->() const { return &value(); }
- T* operator->() { return &value(); }
+ ALWAYS_INLINE const T* operator->() const { return &value(); }
+ ALWAYS_INLINE T* operator->() { return &value(); }
private:
- // Call when we don't want to alter the consume state
- ALWAYS_INLINE const T& value_without_consume_state() const
- {
- ASSERT(m_has_value);
- return *reinterpret_cast<const T*>(&m_storage);
- }
u8 m_storage[sizeof(T)] { 0 };
bool m_has_value { false };
};