1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 05:27:46 +00:00

AK: Allow AK::Variant::visit to return a value

This changes Variant::visit() to forward the value returned by the
selected visitor invocation. By perfectly forwarding the returned value,
this allows for the visitor to return by value or reference.

Note that all provided visitors must return the same type - the compiler
will otherwise fail with the message: "inconsistent deduction for auto
return type".
This commit is contained in:
Timothy Flynn 2021-05-19 11:28:27 -04:00 committed by Andreas Kling
parent 585e7890cd
commit 145e246a5e
2 changed files with 79 additions and 27 deletions

View file

@ -6,8 +6,16 @@
#include <LibTest/TestSuite.h>
#include <AK/RefPtr.h>
#include <AK/Variant.h>
namespace {
struct Object : public RefCounted<Object> {
};
}
TEST_CASE(basic)
{
Variant<int, String> the_value { 42 };
@ -117,3 +125,50 @@ TEST_CASE(duplicated_types)
EXPECT(its_just_an_int.has<int>());
EXPECT_EQ(its_just_an_int.get<int>(), 42);
}
TEST_CASE(return_values)
{
using MyVariant = Variant<int, String, float>;
{
MyVariant the_value { 42.0f };
float value = the_value.visit(
[&](const int&) { return 1.0f; },
[&](const String&) { return 2.0f; },
[&](const float& f) { return f; });
EXPECT_EQ(value, 42.0f);
}
{
MyVariant the_value { 42 };
int value = the_value.visit(
[&](int& i) { return i; },
[&](String&) { return 2; },
[&](float&) { return 3; });
EXPECT_EQ(value, 42);
}
{
const MyVariant the_value { "str" };
String value = the_value.visit(
[&](const int&) { return String { "wrong" }; },
[&](const String& s) { return s; },
[&](const float&) { return String { "wrong" }; });
EXPECT_EQ(value, "str");
}
}
TEST_CASE(return_values_by_reference)
{
auto ref = adopt_ref_if_nonnull(new Object());
Variant<int, String, float> the_value { 42.0f };
auto& value = the_value.visit(
[&](const int&) -> RefPtr<Object>& { return ref; },
[&](const String&) -> RefPtr<Object>& { return ref; },
[&](const float&) -> RefPtr<Object>& { return ref; });
EXPECT_EQ(ref, value);
EXPECT_EQ(ref->ref_count(), 1u);
EXPECT_EQ(value->ref_count(), 1u);
}