Skip to content

Commit bcd01da

Browse files
Hendiadyoin1gmta
authored andcommitted
AK: Use Deducing this for OptionalBase
This is taken from and akin to SerenityOS/serenity#25894
1 parent fd4888e commit bcd01da

File tree

12 files changed

+81
-94
lines changed

12 files changed

+81
-94
lines changed

AK/Optional.h

Lines changed: 67 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@
99
#pragma once
1010

1111
#include <AK/Assertions.h>
12+
#include <AK/Concepts.h>
13+
#include <AK/Forward.h>
1214
#include <AK/Noncopyable.h>
15+
#include <AK/Platform.h>
16+
#include <AK/StdLibExtraDetails.h>
1317
#include <AK/StdLibExtras.h>
1418
#include <AK/Traits.h>
1519
#include <AK/Try.h>
@@ -33,10 +37,17 @@ struct ConditionallyResultType<false, T> {
3337
using Type = T;
3438
};
3539

40+
template<typename Self, typename T>
41+
struct AddConstIfNeeded {
42+
using Type = Conditional<IsConst<RemoveReference<Self>> && !IsConst<T>, AddConst<T>, T>;
43+
};
44+
3645
}
3746

3847
template<auto condition, typename T>
3948
using ConditionallyResultType = typename Detail::ConditionallyResultType<condition, T>::Type;
49+
template<typename Self, typename T>
50+
using AddConstIfNeeded = typename Detail::AddConstIfNeeded<Self, T>::Type;
4051

4152
// NOTE: If you're here because of an internal compiler error in GCC 10.3.0+,
4253
// it's because of the following bug:
@@ -53,124 +64,100 @@ struct OptionalNone {
5364
explicit constexpr OptionalNone() = default;
5465
};
5566

56-
template<typename T, typename Self = Optional<T>>
57-
requires(!IsLvalueReference<Self>) class [[nodiscard]] OptionalBase {
67+
template<typename T>
68+
requires(!IsLvalueReference<T>)
69+
class [[nodiscard]] OptionalBase {
5870
public:
5971
using ValueType = T;
6072

61-
template<SameAs<OptionalNone> V>
62-
ALWAYS_INLINE constexpr Self& operator=(V)
73+
template<typename Self, SameAs<OptionalNone> V>
74+
ALWAYS_INLINE constexpr Self& operator=(this Self& self, V)
6375
{
64-
static_cast<Self&>(*this).clear();
65-
return static_cast<Self&>(*this);
76+
self.clear();
77+
return self;
6678
}
6779

68-
[[nodiscard]] ALWAYS_INLINE constexpr T* ptr() &
80+
template<typename Self>
81+
[[nodiscard]] ALWAYS_INLINE constexpr AddConstIfNeeded<Self, T>* ptr(this Self& self)
6982
{
70-
return static_cast<Self&>(*this).has_value() ? __builtin_launder(reinterpret_cast<T*>(&static_cast<Self&>(*this).value())) : nullptr;
83+
return self.has_value() ? &self.value() : nullptr;
7184
}
7285

73-
[[nodiscard]] ALWAYS_INLINE constexpr T const* ptr() const&
86+
template<typename O = T, typename Fallback = O, typename Self>
87+
[[nodiscard]] ALWAYS_INLINE constexpr O value_or(this Self&& self, Fallback&& fallback)
7488
{
75-
return static_cast<Self const&>(*this).has_value() ? __builtin_launder(reinterpret_cast<T const*>(&static_cast<Self const&>(*this).value())) : nullptr;
89+
if (self.has_value())
90+
return forward<Self>(self).value();
91+
return forward<Fallback>(fallback);
7692
}
7793

78-
template<typename O = T, typename Fallback = O>
79-
[[nodiscard]] ALWAYS_INLINE constexpr O value_or(Fallback const& fallback) const&
94+
template<typename Callback, typename O = T, typename Self>
95+
[[nodiscard]] ALWAYS_INLINE constexpr O value_or_lazy_evaluated(this Self&& self, Callback callback)
8096
{
81-
if (static_cast<Self const&>(*this).has_value())
82-
return static_cast<Self const&>(*this).value();
83-
return fallback;
84-
}
85-
86-
template<typename O = T, typename Fallback = O>
87-
requires(!IsLvalueReference<O> && !IsRvalueReference<O>)
88-
[[nodiscard]] ALWAYS_INLINE constexpr O value_or(Fallback&& fallback) &&
89-
{
90-
if (static_cast<Self&>(*this).has_value())
91-
return move(static_cast<Self&>(*this).value());
92-
return move(fallback);
93-
}
94-
95-
template<typename Callback, typename O = T>
96-
[[nodiscard]] ALWAYS_INLINE constexpr O value_or_lazy_evaluated(Callback callback) const
97-
{
98-
if (static_cast<Self const&>(*this).has_value())
99-
return static_cast<Self const&>(*this).value();
97+
if (self.has_value())
98+
return forward<Self>(self).value();
10099
return callback();
101100
}
102101

103-
template<typename Callback, typename O = T>
104-
[[nodiscard]] ALWAYS_INLINE constexpr Optional<O> value_or_lazy_evaluated_optional(Callback callback) const
102+
template<typename Callback, typename O = T, typename Self>
103+
[[nodiscard]] ALWAYS_INLINE constexpr Optional<O> value_or_lazy_evaluated_optional(this Self&& self, Callback callback)
105104
{
106-
if (static_cast<Self const&>(*this).has_value())
107-
return static_cast<Self const&>(*this).value();
105+
if (self.has_value())
106+
return forward<Self>(self);
108107
return callback();
109108
}
110109

111-
template<typename Callback, typename O = T>
112-
[[nodiscard]] ALWAYS_INLINE constexpr ErrorOr<O> try_value_or_lazy_evaluated(Callback callback) const
110+
template<typename Callback, typename O = T, typename Self>
111+
[[nodiscard]] ALWAYS_INLINE constexpr ErrorOr<O> try_value_or_lazy_evaluated(this Self&& self, Callback callback)
113112
{
114-
if (static_cast<Self const&>(*this).has_value())
115-
return static_cast<Self const&>(*this).value();
113+
if (self.has_value())
114+
return forward<Self>(self).value();
116115
return TRY(callback());
117116
}
118117

119-
template<typename Callback, typename O = T>
120-
[[nodiscard]] ALWAYS_INLINE constexpr ErrorOr<Optional<O>> try_value_or_lazy_evaluated_optional(Callback callback) const
118+
template<typename Callback, typename O = T, typename Self>
119+
[[nodiscard]] ALWAYS_INLINE constexpr ErrorOr<Optional<O>> try_value_or_lazy_evaluated_optional(this Self&& self, Callback callback)
121120
{
122-
if (static_cast<Self const&>(*this).has_value())
123-
return static_cast<Self const&>(*this).value();
121+
if (self.has_value())
122+
return forward<Self>(self);
124123
return TRY(callback());
125124
}
126125

127-
template<typename Callable>
128-
[[nodiscard]] ALWAYS_INLINE constexpr T& ensure(Callable callable) &
126+
template<typename Callable, typename Self>
127+
[[nodiscard]] ALWAYS_INLINE constexpr T& ensure(this Self& self, Callable callable)
129128
{
130-
if (!static_cast<Self&>(*this).has_value())
131-
static_cast<Self&>(*this) = callable();
132-
return static_cast<Self&>(*this).value();
129+
if (!self.has_value())
130+
self = callable();
131+
return self.value();
133132
}
134133

135-
[[nodiscard]] ALWAYS_INLINE constexpr T const& operator*() const { return static_cast<Self const&>(*this).value(); }
136-
[[nodiscard]] ALWAYS_INLINE constexpr T& operator*() { return static_cast<Self&>(*this).value(); }
137-
138-
ALWAYS_INLINE constexpr T const* operator->() const { return &static_cast<Self const&>(*this).value(); }
139-
ALWAYS_INLINE constexpr T* operator->() { return &static_cast<Self&>(*this).value(); }
134+
template<typename Self>
135+
[[nodiscard]] ALWAYS_INLINE constexpr auto operator*(this Self&& self) -> decltype(forward<Self>(self).value()) { return forward<Self>(self).value(); }
136+
template<typename Self>
137+
[[nodiscard]] ALWAYS_INLINE constexpr AddConstIfNeeded<Self, T>* operator->(this Self&& self) { return &self.value(); }
140138

141-
template<typename F, typename MappedType = decltype(declval<F>()(declval<T&>())), auto IsErrorOr = IsSpecializationOf<MappedType, ErrorOr>, typename OptionalType = Optional<ConditionallyResultType<IsErrorOr, MappedType>>>
142-
ALWAYS_INLINE constexpr Conditional<IsErrorOr, ErrorOr<OptionalType>, OptionalType> map(F&& mapper)
143-
{
144-
if constexpr (IsErrorOr) {
145-
if (static_cast<Self&>(*this).has_value())
146-
return OptionalType { TRY(mapper(static_cast<Self&>(*this).value())) };
147-
return OptionalType {};
148-
} else {
149-
if (static_cast<Self&>(*this).has_value())
150-
return OptionalType { mapper(static_cast<Self&>(*this).value()) };
151-
152-
return OptionalType {};
153-
}
154-
}
155-
156-
template<typename F, typename MappedType = decltype(declval<F>()(declval<T&>())), auto IsErrorOr = IsSpecializationOf<MappedType, ErrorOr>, typename OptionalType = Optional<ConditionallyResultType<IsErrorOr, MappedType>>>
157-
ALWAYS_INLINE constexpr Conditional<IsErrorOr, ErrorOr<OptionalType>, OptionalType> map(F&& mapper) const
139+
template<typename F,
140+
typename MappedType = decltype(declval<F>()(declval<T&>())),
141+
auto IsErrorOr = IsSpecializationOf<MappedType, ErrorOr>,
142+
typename OptionalType = Optional<ConditionallyResultType<IsErrorOr, MappedType>>,
143+
typename Self>
144+
ALWAYS_INLINE constexpr Conditional<IsErrorOr, ErrorOr<OptionalType>, OptionalType> map(this Self&& self, F&& mapper)
158145
{
159146
if constexpr (IsErrorOr) {
160-
if (static_cast<Self const&>(*this).has_value())
161-
return OptionalType { TRY(mapper(static_cast<Self const&>(*this).value())) };
147+
if (self.has_value())
148+
return OptionalType { TRY(mapper(forward<Self>(self).value())) };
162149
return OptionalType {};
163150
} else {
164-
if (static_cast<Self const&>(*this).has_value())
165-
return OptionalType { mapper(static_cast<Self const&>(*this).value()) };
151+
if (self.has_value())
152+
return OptionalType { mapper(forward<Self>(self).value()) };
166153

167154
return OptionalType {};
168155
}
169156
}
170157
};
171158

172159
template<typename T>
173-
requires(!IsLvalueReference<T>) class [[nodiscard]] Optional<T> : public OptionalBase<T, Optional<T>> {
160+
requires(!IsLvalueReference<T>) class [[nodiscard]] Optional<T> : public OptionalBase<T> {
174161
template<typename U>
175162
friend class Optional;
176163

@@ -509,12 +496,12 @@ requires(IsLvalueReference<T>) class [[nodiscard]] Optional<T> {
509496

510497
[[nodiscard]] ALWAYS_INLINE constexpr bool has_value() const { return m_pointer != nullptr; }
511498

512-
[[nodiscard]] ALWAYS_INLINE RemoveReference<T>* ptr()
499+
[[nodiscard]] ALWAYS_INLINE constexpr RemoveReference<T>* ptr()
513500
{
514501
return m_pointer;
515502
}
516503

517-
[[nodiscard]] ALWAYS_INLINE RemoveReference<T> const* ptr() const
504+
[[nodiscard]] ALWAYS_INLINE constexpr RemoveReference<T> const* ptr() const
518505
{
519506
return m_pointer;
520507
}
@@ -532,7 +519,7 @@ requires(IsLvalueReference<T>) class [[nodiscard]] Optional<T> {
532519
}
533520

534521
template<typename U>
535-
requires(IsBaseOf<RemoveReference<T>, U>) [[nodiscard]] ALWAYS_INLINE constexpr AddConstToReferencedType<T> value_or(U& fallback) const
522+
requires(IsBaseOf<RemoveCVReference<T>, U>) [[nodiscard]] ALWAYS_INLINE constexpr AddConstToReferencedType<T> value_or(U& fallback) const
536523
{
537524
if (m_pointer)
538525
return value();
@@ -555,8 +542,8 @@ requires(IsLvalueReference<T>) class [[nodiscard]] Optional<T> {
555542
ALWAYS_INLINE constexpr AddConstToReferencedType<T> operator*() const { return value(); }
556543
ALWAYS_INLINE constexpr T operator*() { return value(); }
557544

558-
ALWAYS_INLINE RawPtr<AddConst<RemoveReference<T>>> operator->() const { return &value(); }
559-
ALWAYS_INLINE RawPtr<RemoveReference<T>> operator->() { return &value(); }
545+
ALWAYS_INLINE constexpr RawPtr<AddConst<RemoveReference<T>>> operator->() const { return &value(); }
546+
ALWAYS_INLINE constexpr RawPtr<RemoveReference<T>> operator->() { return &value(); }
560547

561548
// Conversion operators from Optional<T&> -> Optional<T>, implicit when T is trivially copyable.
562549
ALWAYS_INLINE constexpr operator Optional<RemoveCVReference<T>>() const

Libraries/LibWeb/CSS/CSSMathClamp.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ WebIDL::ExceptionOr<GC::Ref<CSSMathClamp>> CSSMathClamp::construct_impl(JS::Real
3434
// 2. Let type be the result of adding the types of lower, value, and upper. If type is failure, throw a TypeError.
3535
auto type = lower_rectified->type()
3636
.added_to(value_rectified->type())
37-
.map([&](auto& type) { return type.added_to(upper_rectified->type()); });
37+
.map([&](auto&& type) { return type.added_to(upper_rectified->type()); });
3838
if (!type.has_value()) {
3939
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Cannot create a CSSMathClamp with values of incompatible types"sv };
4040
}

Libraries/LibWeb/CSS/CSSStyleProperties.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ Optional<StyleProperty> CSSStyleProperties::get_direct_property(PropertyNameAndI
555555
}
556556

557557
if (property_name_and_id.is_custom_property())
558-
return custom_property(property_name_and_id.name()).map([](auto& it) { return it; });
558+
return custom_property(property_name_and_id.name()).copy();
559559

560560
for (auto const& property : m_properties) {
561561
if (property.property_id == property_id)

Libraries/LibWeb/CSS/CalculatedOr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ NonnullRefPtr<StyleValue const> LengthOrCalculated::create_style_value() const
7070

7171
Optional<LengthOrAuto> LengthOrAutoOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue const> const& calculated, CalculationResolutionContext const& context) const
7272
{
73-
return calculated->resolve_length(context).map([](auto& length) { return LengthOrAuto { length }; });
73+
return calculated->resolve_length(context).map([](auto&& length) { return LengthOrAuto { length }; });
7474
}
7575

7676
NonnullRefPtr<StyleValue const> LengthOrAutoOrCalculated::create_style_value() const

Libraries/LibWeb/CSS/MediaQuery.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ MatchResult MediaFeature::evaluate(DOM::Document const* document) const
125125
if (queried_value.is_ratio())
126126
return as_match_result(!queried_value.ratio().is_degenerate());
127127
if (queried_value.is_resolution())
128-
return as_match_result(queried_value.resolution().resolved(calculation_context).map([](auto& it) { return it.to_dots_per_pixel(); }).value_or(0) != 0);
128+
return as_match_result(queried_value.resolution().resolved(calculation_context).map([](auto&& it) { return it.to_dots_per_pixel(); }).value_or(0) != 0);
129129
if (queried_value.is_ident()) {
130130
if (media_feature_keyword_is_falsey(m_id, queried_value.ident()))
131131
return MatchResult::False;
@@ -237,8 +237,8 @@ MatchResult MediaFeature::compare(DOM::Document const& document, MediaFeatureVal
237237
}
238238

239239
if (left.is_resolution()) {
240-
auto left_dppx = left.resolution().resolved(calculation_context).map([](auto& it) { return it.to_dots_per_pixel(); }).value_or(0);
241-
auto right_dppx = right.resolution().resolved(calculation_context).map([](auto& it) { return it.to_dots_per_pixel(); }).value_or(0);
240+
auto left_dppx = left.resolution().resolved(calculation_context).map([](auto&& it) { return it.to_dots_per_pixel(); }).value_or(0);
241+
auto right_dppx = right.resolution().resolved(calculation_context).map([](auto&& it) { return it.to_dots_per_pixel(); }).value_or(0);
242242

243243
switch (comparison) {
244244
case Comparison::Equal:

Libraries/LibWeb/CSS/Parser/Parser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1229,7 +1229,7 @@ Optional<Rule> Parser::parse_a_rule(TokenStream<T>& input)
12291229
// Otherwise, if the next token from input is an <at-keyword-token>,
12301230
// consume an at-rule from input, and let rule be the return value.
12311231
else if (input.next_token().is(Token::Type::AtKeyword)) {
1232-
rule = consume_an_at_rule(m_token_stream).map([](auto& it) { return Rule { it }; });
1232+
rule = consume_an_at_rule(m_token_stream).map([](auto&& it) { return Rule { it }; });
12331233
}
12341234
// Otherwise, consume a qualified rule from input and let rule be the return value.
12351235
// If nothing or an invalid rule error was returned, return a syntax error.

Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ RefPtr<StyleValue const> Parser::parse_coordinating_value_list_shorthand(TokenSt
166166
RefPtr<StyleValue const> Parser::parse_css_value_for_property(PropertyID property_id, TokenStream<ComponentValue>& tokens)
167167
{
168168
return parse_css_value_for_properties({ &property_id, 1 }, tokens)
169-
.map([](auto& it) { return it.style_value; })
169+
.map([](auto&& it) { return it.style_value; })
170170
.value_or(nullptr);
171171
}
172172

Libraries/LibWeb/CSS/Parser/ValueParsing.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4010,14 +4010,14 @@ Optional<ExplicitGridTrack> Parser::parse_grid_fixed_size(TokenStream<ComponentV
40104010
auto const& function_token = token.function();
40114011
if (function_token.name.equals_ignoring_ascii_case("minmax"sv)) {
40124012
{
4013-
GridMinMaxParamParser parse_min = [this](auto& tokens) { return parse_grid_fixed_breadth(tokens).map([](auto& it) { return GridSize(Size::make_length_percentage(it)); }); };
4013+
GridMinMaxParamParser parse_min = [this](auto& tokens) { return parse_grid_fixed_breadth(tokens).map([](auto&& it) { return GridSize(Size::make_length_percentage(it)); }); };
40144014
GridMinMaxParamParser parse_max = [this](auto& tokens) { return parse_grid_track_breadth(tokens); };
40154015
if (auto result = parse_grid_minmax(tokens, parse_min, parse_max); result.has_value())
40164016
return result;
40174017
}
40184018
{
40194019
GridMinMaxParamParser parse_min = [this](auto& tokens) { return parse_grid_inflexible_breadth(tokens); };
4020-
GridMinMaxParamParser parse_max = [this](auto& tokens) { return parse_grid_fixed_breadth(tokens).map([](auto& it) { return GridSize(Size::make_length_percentage(it)); }); };
4020+
GridMinMaxParamParser parse_max = [this](auto& tokens) { return parse_grid_fixed_breadth(tokens).map([](auto&& it) { return GridSize(Size::make_length_percentage(it)); }); };
40214021
if (auto result = parse_grid_minmax(tokens, parse_min, parse_max); result.has_value())
40224022
return result;
40234023
}

Libraries/LibWeb/CSS/StyleComputer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2488,7 +2488,7 @@ RefPtr<StyleValue const> StyleComputer::recascade_font_size_if_needed(DOM::Abstr
24882488

24892489
VERIFY(font_size_value->is_length());
24902490

2491-
auto inherited_line_height = ancestor.element_to_inherit_style_from().map([](auto& parent_element) { return parent_element.computed_properties()->line_height(); }).value_or(InitialValues::line_height());
2491+
auto inherited_line_height = ancestor.element_to_inherit_style_from().map([](auto&& parent_element) { return parent_element.computed_properties()->line_height(); }).value_or(InitialValues::line_height());
24922492

24932493
current_size_in_px = font_size_value->as_length().length().to_px(viewport_rect(), Length::FontMetrics { current_size_in_px, monospace_font->with_size(current_size_in_px * 0.75f)->pixel_metrics(), inherited_line_height }, m_root_element_font_metrics);
24942494
};

Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1271,7 +1271,7 @@ Optional<CalculatedStyleValue::CalculationResult> ClampCalculationNode::run_oper
12711271
if (!max_result.has_value())
12721272
return {};
12731273

1274-
auto consistent_type = min_result->type()->consistent_type(center_result->type().value()).map([&](auto& it) { return it.consistent_type(max_result->type().value()); });
1274+
auto consistent_type = min_result->type()->consistent_type(center_result->type().value()).map([&](auto&& it) { return it.consistent_type(max_result->type().value()); });
12751275
if (!consistent_type.has_value())
12761276
return {};
12771277

0 commit comments

Comments
 (0)