修复builder 调用方式
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
#include "renderive/base/memory/Memory_Resource.hpp"
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
template <Property_Product Product_Type, Property_Set Properties_Type, Property_Validator<Properties_Type> Validator_Type = No_Property_Validator<Properties_Type>>
|
||||
class Property_Builder {
|
||||
@@ -12,43 +14,97 @@ public:
|
||||
using Properties = Properties_Type;
|
||||
using Validator = Validator_Type;
|
||||
using Self = Property_Builder;
|
||||
Property_Builder() requires std::default_initializable<Properties> && std::default_initializable<Validator> : properties{}, validator{} {}
|
||||
explicit Property_Builder(Properties properties) requires std::default_initializable<Validator> : properties(std::move(properties)), validator{} {}
|
||||
Property_Builder(Properties properties, Validator validator) : properties(std::move(properties)), validator(std::move(validator)) {}
|
||||
Property_Builder() requires std::default_initializable<Validator> {
|
||||
bind_constructor();
|
||||
}
|
||||
template <class... Args> requires (sizeof...(Args) > 0) && std::default_initializable<Validator>
|
||||
explicit Property_Builder(Args&&... args) {
|
||||
bind_constructor(std::forward<Args>(args)...);
|
||||
}
|
||||
template <auto Member, Property_Member_Assignable<Properties, Member> Value>
|
||||
Self& set(Value&& value) {
|
||||
properties.*Member = std::forward < Value > (value);
|
||||
properties_.*Member = std::forward<Value>(value);
|
||||
return *this;
|
||||
}
|
||||
template <Property_Configurator<Properties> Configure>
|
||||
Self& configure(Configure&& configure) {
|
||||
std::invoke(std::forward < Configure > (configure), properties);
|
||||
std::invoke(std::forward<Configure>(configure), properties_);
|
||||
return *this;
|
||||
}
|
||||
const Properties& properties_value() const noexcept {
|
||||
return properties;
|
||||
return properties_;
|
||||
}
|
||||
template <class... Args> requires Property_Constructible<Product, Properties, Args&&...>
|
||||
std::shared_ptr<Product> build(Args&&... args) const {
|
||||
validator(properties);
|
||||
return std::make_shared<Product>(properties, std::forward<Args>(args)...);
|
||||
[[nodiscard]] std::shared_ptr<Product> build() {
|
||||
validator_(properties_);
|
||||
auto construct = std::exchange(shared_constructor_, {});
|
||||
clear_constructors();
|
||||
return construct(properties_);
|
||||
}
|
||||
template <class... Args> requires Property_Constructible<Product, Properties, Args&&...>
|
||||
std::shared_ptr<Product> build_with_resource(std::pmr::memory_resource& memory_resource, Args&&... args) const {
|
||||
validator(properties);
|
||||
return std::allocate_shared<Product>(std::pmr::polymorphic_allocator<Product>(&memory_resource), properties, std::forward<Args>(args)...);
|
||||
[[nodiscard]] std::shared_ptr<Product> build_with_resource(std::pmr::memory_resource& memory_resource) {
|
||||
validator_(properties_);
|
||||
auto construct = std::exchange(resource_shared_constructor_, {});
|
||||
clear_constructors();
|
||||
return construct(memory_resource, properties_);
|
||||
}
|
||||
template <class... Args> requires Property_Constructible<Product, Properties, Args&&...>
|
||||
std::unique_ptr<Product> build_unique(Args&&... args) const {
|
||||
validator(properties);
|
||||
return std::make_unique<Product>(properties, std::forward<Args>(args)...);
|
||||
[[nodiscard]] std::unique_ptr<Product> build_unique() {
|
||||
validator_(properties_);
|
||||
auto construct = std::exchange(unique_constructor_, {});
|
||||
clear_constructors();
|
||||
return construct(properties_);
|
||||
}
|
||||
template <class... Args> requires Property_Constructible<Product, Properties, Args&&...>
|
||||
Memory_Resource_Unique_Ptr<Product> build_unique_with_resource(std::pmr::memory_resource& memory_resource, Args&&... args) const {
|
||||
validator(properties);
|
||||
return make_memory_resource_unique<Product>(memory_resource, properties, std::forward<Args>(args)...);
|
||||
[[nodiscard]] Memory_Resource_Unique_Ptr<Product> build_unique_with_resource(std::pmr::memory_resource& memory_resource) {
|
||||
validator_(properties_);
|
||||
auto construct = std::exchange(resource_unique_constructor_, {});
|
||||
clear_constructors();
|
||||
return construct(memory_resource, properties_);
|
||||
}
|
||||
private:
|
||||
Properties properties;
|
||||
[[no_unique_address]] Validator validator;
|
||||
using Shared_Constructor = std::function<std::shared_ptr<Product>(const Properties&)>;
|
||||
using Resource_Shared_Constructor = std::function<std::shared_ptr<Product>(std::pmr::memory_resource&, const Properties&)>;
|
||||
using Unique_Constructor = std::function<std::unique_ptr<Product>(const Properties&)>;
|
||||
using Resource_Unique_Constructor = std::function<Memory_Resource_Unique_Ptr<Product>(std::pmr::memory_resource&, const Properties&)>;
|
||||
template <class... Args>
|
||||
void bind_constructor(Args&&... args) {
|
||||
auto stored = std::make_shared<std::tuple<std::decay_t<Args>...>>(std::forward<Args>(args)...);
|
||||
shared_constructor_ = [stored](const Properties& properties) mutable {
|
||||
return std::apply(
|
||||
[&](auto&... values) {
|
||||
return std::make_shared<Product>(properties, std::move(values)...);
|
||||
},
|
||||
*stored);
|
||||
};
|
||||
resource_shared_constructor_ = [stored](std::pmr::memory_resource& memory_resource, const Properties& properties) mutable {
|
||||
return std::apply(
|
||||
[&](auto&... values) {
|
||||
return std::allocate_shared<Product>(std::pmr::polymorphic_allocator<Product>(&memory_resource), properties, std::move(values)...);
|
||||
},
|
||||
*stored);
|
||||
};
|
||||
unique_constructor_ = [stored](const Properties& properties) mutable {
|
||||
return std::apply(
|
||||
[&](auto&... values) {
|
||||
return std::make_unique<Product>(properties, std::move(values)...);
|
||||
},
|
||||
*stored);
|
||||
};
|
||||
resource_unique_constructor_ = [stored](std::pmr::memory_resource& memory_resource, const Properties& properties) mutable {
|
||||
return std::apply(
|
||||
[&](auto&... values) {
|
||||
return make_memory_resource_unique<Product>(memory_resource, properties, std::move(values)...);
|
||||
},
|
||||
*stored);
|
||||
};
|
||||
}
|
||||
void clear_constructors() {
|
||||
shared_constructor_ = {};
|
||||
resource_shared_constructor_ = {};
|
||||
unique_constructor_ = {};
|
||||
resource_unique_constructor_ = {};
|
||||
}
|
||||
Properties properties_{};
|
||||
[[no_unique_address]] Validator validator_{};
|
||||
Shared_Constructor shared_constructor_;
|
||||
Resource_Shared_Constructor resource_shared_constructor_;
|
||||
Unique_Constructor unique_constructor_;
|
||||
Resource_Unique_Constructor resource_unique_constructor_;
|
||||
};
|
||||
|
||||
@@ -34,6 +34,9 @@ template <class Layer, class Parent_Next, class Business_Builder>
|
||||
struct Builder
|
||||
: Parent_Next, Business_Builder {
|
||||
using Business_Builder::Business_Builder;
|
||||
using Business_Builder::set;
|
||||
using Business_Builder::configure;
|
||||
using Business_Builder::build;
|
||||
};
|
||||
template <class Layer>
|
||||
struct State_Root
|
||||
|
||||
@@ -10,6 +10,7 @@ class Frame_Strategy_Real_Time_Data_Observer;
|
||||
class Real_Time_Data_Base;
|
||||
class Real_Time_Data_Binding;
|
||||
class Scene_Base;
|
||||
class Scene_2D_Base;
|
||||
namespace renderive::inheritance {
|
||||
struct Observation_Source;
|
||||
}
|
||||
@@ -51,5 +52,6 @@ private:
|
||||
friend class Real_Time_Data_Base;
|
||||
friend class Real_Time_Data_Binding;
|
||||
friend class Scene_Base;
|
||||
friend class Scene_2D_Base;
|
||||
std::unique_ptr<Impl> d_ptr;
|
||||
};
|
||||
|
||||
@@ -2,44 +2,51 @@
|
||||
#include "renderive/base/property/Concepts.hpp"
|
||||
#include "renderive/base/property/Validators.hpp"
|
||||
#include "renderive/scene/Inheritance.hpp"
|
||||
#include <concepts>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
namespace renderive::scene {
|
||||
template <Property_Product Product_Type, Property_Set Properties_Type,
|
||||
Property_Validator<Properties_Type> Validator_Type =
|
||||
No_Property_Validator<Properties_Type>>
|
||||
template <Property_Product Product_Type, Property_Set Properties_Type, Property_Validator<Properties_Type> Validator_Type = No_Property_Validator<Properties_Type>>
|
||||
struct Scene_Builder {
|
||||
using Product = Product_Type;
|
||||
using Properties = Properties_Type;
|
||||
using Validator = Validator_Type;
|
||||
using Self = Scene_Builder;
|
||||
Scene_Builder() requires std::default_initializable<Properties> &&
|
||||
std::default_initializable<Validator>
|
||||
= default;
|
||||
explicit Scene_Builder(Properties properties) requires std::default_initializable<Validator> : properties_(std::move(properties)) {}
|
||||
Scene_Builder(Properties properties, Validator validator) : properties_(std::move(properties)),
|
||||
validator_(std::move(validator)) {}
|
||||
template <auto Member,
|
||||
Property_Member_Assignable<Properties, Member> Value>
|
||||
Scene_Builder() requires std::default_initializable<Validator> : constructor_(make_constructor()) {}
|
||||
template <class... Args> requires (sizeof...(Args) > 0) && std::default_initializable<Validator>
|
||||
explicit Scene_Builder(Args&&... args) : constructor_(make_constructor(std::forward<Args>(args)...)) {}
|
||||
template <auto Member, Property_Member_Assignable<Properties, Member> Value>
|
||||
Self& set(Value&& value) {
|
||||
properties_.*Member = std::forward < Value > (value);
|
||||
properties_.*Member = std::forward<Value>(value);
|
||||
return *this;
|
||||
}
|
||||
template <Property_Configurator<Properties> Configure>
|
||||
Self& configure(Configure&& configure) {
|
||||
std::invoke(std::forward < Configure > (configure), properties_);
|
||||
std::invoke(std::forward<Configure>(configure), properties_);
|
||||
return *this;
|
||||
}
|
||||
template <class... Args>
|
||||
[[nodiscard]] std::unique_ptr<Product> build(Args&&... args) const {
|
||||
[[nodiscard]] std::unique_ptr<Product> build() {
|
||||
validator_(properties_);
|
||||
return scene_inheritance::Builder_Access::make<Product>(
|
||||
properties_, std::forward<Args>(args)...);
|
||||
auto construct = std::exchange(constructor_, {});
|
||||
return construct(properties_);
|
||||
}
|
||||
private:
|
||||
using Constructor = std::function<std::unique_ptr<Product>(const Properties&)>;
|
||||
template <class... Args>
|
||||
static Constructor make_constructor(Args&&... args) {
|
||||
auto stored = std::make_shared<std::tuple<std::decay_t<Args>...>>(std::forward<Args>(args)...);
|
||||
return [stored = std::move(stored)](const Properties& properties) mutable {
|
||||
return std::apply(
|
||||
[&](auto&... values) {
|
||||
return scene_inheritance::Builder_Access::make<Product>(properties, std::move(values)...);
|
||||
},
|
||||
*stored);
|
||||
};
|
||||
}
|
||||
Properties properties_{};
|
||||
[[no_unique_address]] Validator validator_{};
|
||||
Constructor constructor_;
|
||||
};
|
||||
} // namespace renderive::scene
|
||||
}
|
||||
|
||||
@@ -519,6 +519,10 @@ Scene_2D_Base::Impl::Impl(std::pmr::memory_resource& memory_resource) : Scene_Ba
|
||||
Scene_2D_Base::Attach_Builder Scene_2D_Base::attach_builder() {
|
||||
return Attach_Builder(*this);
|
||||
}
|
||||
Scene_2D_Base::Attach_Builder Scene_2D_Base::attach_builder(
|
||||
const Renderable& anchor) {
|
||||
return Attach_Builder(dynamic_cast<Scene_2D_Base&>(anchor->d_func().scene()));
|
||||
}
|
||||
Scene_Base::Edit_Operation Scene_2D_Base::edit_renderables(Renderable_Edit edit) {
|
||||
if (!edit) {
|
||||
std::promise<Scene_Edit_Error> promise;
|
||||
|
||||
@@ -261,6 +261,7 @@ public:
|
||||
Scene_2D_Base();
|
||||
explicit Scene_2D_Base(std::pmr::memory_resource& memory_resource);
|
||||
Attach_Builder attach_builder();
|
||||
[[nodiscard]] static Attach_Builder attach_builder(const Renderable& anchor);
|
||||
[[nodiscard]] Edit_Operation edit_renderables(Renderable_Edit edit);
|
||||
struct Observer
|
||||
: Scene_Base::next_Observer<Observer> {};
|
||||
|
||||
@@ -2,14 +2,19 @@
|
||||
#include <memory>
|
||||
#include "Property_Test_Types.hpp"
|
||||
TEST(property_builder_test, builds_independent_product) {
|
||||
auto product = Property_Direct_Builder{Property_Direct_Properties{.value = 42}}.build(7);
|
||||
auto product = Property_Direct_Builder{7}
|
||||
.set<&Property_Direct_Properties::value>(42)
|
||||
.build();
|
||||
EXPECT_EQ(product->value, 42);
|
||||
EXPECT_EQ(product->id, 7);
|
||||
}
|
||||
TEST(property_builder_test, configures_properties) {
|
||||
auto product = Property_Direct_Builder{}.set<&Property_Direct_Properties::value>(10).configure([](Property_Direct_Properties& properties) {
|
||||
properties.value += 5;
|
||||
}).build(1);
|
||||
auto product = Property_Direct_Builder{1}
|
||||
.set<&Property_Direct_Properties::value>(10)
|
||||
.configure([](Property_Direct_Properties& properties) {
|
||||
properties.value += 5;
|
||||
})
|
||||
.build();
|
||||
EXPECT_EQ(product->value, 15);
|
||||
}
|
||||
TEST(property_builder_test, supports_external_validator) {
|
||||
@@ -17,7 +22,9 @@ TEST(property_builder_test, supports_external_validator) {
|
||||
EXPECT_THROW(builder.build(), std::invalid_argument);
|
||||
}
|
||||
TEST(property_builder_test, builds_unique_product) {
|
||||
auto product = Property_Direct_Builder{Property_Direct_Properties{.value = 12}}.build_unique(3);
|
||||
auto product = Property_Direct_Builder{3}
|
||||
.set<&Property_Direct_Properties::value>(12)
|
||||
.build_unique();
|
||||
static_assert(std::same_as<decltype(product), std::unique_ptr<Property_Direct_Product>>);
|
||||
EXPECT_EQ(product->value, 12);
|
||||
EXPECT_EQ(product->id, 3);
|
||||
|
||||
@@ -91,9 +91,12 @@ TEST(scene_memory_resource_test, supports_independent_resource_aware_components)
|
||||
history.update(1);
|
||||
history.update(2);
|
||||
EXPECT_EQ(history.size(), 2);
|
||||
Property_Builder<Scene_Memory_Resource_Test_Property_Product, Scene_Memory_Resource_Test_Properties> builder({3});
|
||||
auto product = builder.build_with_resource(memory_resource, 4);
|
||||
auto unique_product = builder.build_unique_with_resource(memory_resource, 5);
|
||||
auto product = Property_Builder<Scene_Memory_Resource_Test_Property_Product, Scene_Memory_Resource_Test_Properties>{4}
|
||||
.set<&Scene_Memory_Resource_Test_Properties::value>(3)
|
||||
.build_with_resource(memory_resource);
|
||||
auto unique_product = Property_Builder<Scene_Memory_Resource_Test_Property_Product, Scene_Memory_Resource_Test_Properties>{5}
|
||||
.set<&Scene_Memory_Resource_Test_Properties::value>(3)
|
||||
.build_unique_with_resource(memory_resource);
|
||||
EXPECT_EQ(product->value, 7);
|
||||
EXPECT_EQ(unique_product->value, 8);
|
||||
EXPECT_GT(memory_resource.allocation_count(), 0);
|
||||
|
||||
Reference in New Issue
Block a user