#include #include namespace larra::xmpp { struct SomeStruct { std::string field1; float field2 = 1.f; template auto Field1(this Self&& self, std::string field1) -> decltype(auto) { return utils::FieldSetHelper::With<0>(std::forward(self), std::move(field1)); } template auto Field2(this Self&& self, float field2) -> decltype(auto) { return utils::FieldSetHelper::With<"field2">(std::forward(self), std::move(field2)); } }; TEST(Set, Basic) { auto obj = SomeStruct{}.Field1("Hello").Field2(.0f); EXPECT_EQ(obj.field1, "Hello"); EXPECT_EQ(obj.field2, .0f); } struct SomeStruct2 { SomeStruct2(const SomeStruct2&) = delete; SomeStruct2() = default; SomeStruct2(SomeStruct2&&) = default; }; struct SomeStruct3 { SomeStruct2 field1; SomeStruct2 field2; template auto Field1(this Self&& self, SomeStruct2 field1) -> decltype(auto) { return utils::FieldSetHelper::With<0>(std::forward(self), std::move(field1)); } template auto Field2(this Self&& self, SomeStruct2 field2) -> decltype(auto) { return utils::FieldSetHelper::With<"field2">(std::forward(self), std::move(field2)); } }; TEST(Set, NonCopyable) { auto obj = SomeStruct3{}.Field1({}).Field2({}); } struct SomeStruct4 { std::string field1; float field2 = 1.f; static constexpr auto kUtils = utils::CreateFieldsDescription(&SomeStruct4::field1, &SomeStruct4::field2); template auto Field1(this Self&& self, std::string field1) -> decltype(auto) { return kUtils.With<0>(std::forward(self), std::move(field1)); } template auto Field2(this Self&& self, float field2) -> decltype(auto) { return kUtils.With(&SomeStruct4::field2, std::forward(self), std::move(field2)); } }; struct SomeStruct5 { SomeStruct2 field1; SomeStruct2 field2; static constexpr auto kUtils = utils::CreateFieldsDescription(&SomeStruct5::field1, &SomeStruct5::field2); template auto Field1(this Self&& self, SomeStruct2 field1) -> decltype(auto) { return kUtils.With<0>(std::forward(self), std::move(field1)); } template auto Field2(this Self&& self, SomeStruct2 field2) -> decltype(auto) { return kUtils.With(&SomeStruct5::field2, std::forward(self), std::move(field2)); } }; TEST(NonPfrSet, Basic) { auto obj = SomeStruct4{}.Field1("Hello").Field2(.0f); EXPECT_EQ(obj.field1, "Hello"); EXPECT_EQ(obj.field2, .0f); } TEST(NonPfrSet, NonCopyable) { auto obj = SomeStruct5{}.Field1({}).Field2({}); } struct SomeStruct6 { std::string field1; std::string field2; template auto Field1(this Self&& self, std::string field1) -> std::decay_t { return utils::FieldSetHelper::With<"field1", SomeStruct6>(std::forward(self), std::move(field1)); } template auto Field2(this Self&& self, std::string field2) -> std::decay_t { return utils::FieldSetHelper::With<"field2", SomeStruct6>(std::forward(self), std::move(field2)); } }; struct SomeStruct7 : SomeStruct6 { explicit SomeStruct7(SomeStruct6&& obj) : SomeStruct6(std::move(obj)) {}; using SomeStruct6::SomeStruct6; }; TEST(Set, Inheritance) { const SomeStruct7 obj = SomeStruct7{}.Field1("Hello").Field2("World"); ASSERT_EQ(obj.field1, "Hello"); ASSERT_EQ(obj.field2, "World"); } template struct SomeStruct8 { T value; template constexpr auto Value(this Self&& self, TT value) { return utils::FieldSetHelper::With<0, SomeStruct8, false>(std::forward(self), std::move(value)); } }; TEST(Set, OtherType) { constexpr auto value = SomeStruct8{.value = 42}.Value("Hello World"); EXPECT_EQ(value.value, std::string_view{"Hello World"}); } } // namespace larra::xmpp