补全边角
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
#include <structive/property/property.hpp>
|
||||
struct Capability_Mismatch {
|
||||
const int value{};
|
||||
};
|
||||
int main() {
|
||||
auto schema = structive::object<Capability_Mismatch>(structive::field<&Capability_Mismatch::value>(structive::key<"value">, structive::read_write));
|
||||
return static_cast<int>(schema.property_count);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <structive/property/property.hpp>
|
||||
struct Duplicate_Key {
|
||||
int left{};
|
||||
int right{};
|
||||
};
|
||||
int main() {
|
||||
auto schema = structive::object<Duplicate_Key>(structive::field<&Duplicate_Key::left>(structive::key<"value">), structive::field<&Duplicate_Key::right>(structive::key<"value">));
|
||||
return static_cast<int>(schema.property_count);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#include <structive/property/property.hpp>
|
||||
struct Duplicate_Storage {
|
||||
int value{};
|
||||
};
|
||||
int main() {
|
||||
auto schema = structive::object<Duplicate_Storage>(structive::field<&Duplicate_Storage::value>(structive::key<"first">), structive::field<&Duplicate_Storage::value>(structive::key<"second">));
|
||||
return static_cast<int>(schema.property_count);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include <structive/property/property.hpp>
|
||||
struct Foreign {
|
||||
int value{};
|
||||
};
|
||||
struct Local {
|
||||
int value{};
|
||||
};
|
||||
int main() {
|
||||
auto schema = structive::object<Local>(structive::synchronization(structive::sync_independent<&Foreign::value>()), structive::field<&Local::value>(structive::key<"value">));
|
||||
return static_cast<int>(schema.property_count);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <structive/property/property.hpp>
|
||||
#include <string>
|
||||
struct Incompatible_Constraint {
|
||||
int value{};
|
||||
};
|
||||
int main() {
|
||||
auto only_string = structive::constraint<"string_only">([](const std::string&) { return true; });
|
||||
auto schema = structive::object<Incompatible_Constraint>(structive::field<&Incompatible_Constraint::value>(structive::key<"value">, only_string));
|
||||
return static_cast<int>(schema.property_count);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#include <structive/property/property.hpp>
|
||||
struct Missing_Key {
|
||||
int value{};
|
||||
};
|
||||
int main() {
|
||||
auto schema = structive::object<Missing_Key>(structive::field<&Missing_Key::value>());
|
||||
return static_cast<int>(schema.property_count);
|
||||
}
|
||||
@@ -20,6 +20,16 @@ struct Test_Tag_Attribute {
|
||||
};
|
||||
template <int Value>
|
||||
inline constexpr Test_Tag_Attribute<Value> test_tag{};
|
||||
struct Test_Multi_Category {};
|
||||
template <int Value>
|
||||
struct Test_Multi_Attribute {
|
||||
using attribute_category = Test_Multi_Category;
|
||||
static constexpr bool single_valued = false;
|
||||
static constexpr bool inheritable = false;
|
||||
static constexpr int value = Value;
|
||||
};
|
||||
template <int Value>
|
||||
inline constexpr Test_Multi_Attribute<Value> test_multi{};
|
||||
#define REQUIRE(expression) do { if (!(expression)) { std::fprintf(stderr, "REQUIRE failed: %s:%d: %s\n", __FILE__, __LINE__, #expression); std::abort(); } } while (false)
|
||||
struct Device : Property_Object<Device> {
|
||||
Device() = default;
|
||||
@@ -35,7 +45,7 @@ struct structive::Type_Descriptor<Device> {
|
||||
static auto get() {
|
||||
return object<Device>(
|
||||
synchronization(sync_all_independent, sync_group<&Device::min_speed, &Device::max_speed>("speed_range")),
|
||||
field<&Device::temperature>(key<"temperature">, min_value<-50>, max_value<200>, unit<"C">, test_tag<7>),
|
||||
field<&Device::temperature>(key<"temperature">, min_value<-50>, max_value<200>, unit<"C">, test_tag<7>, test_multi<3>, test_multi<5>),
|
||||
field<&Device::pressure>(key<"pressure">),
|
||||
field<&Device::min_speed>(key<"minimum_speed">),
|
||||
field<&Device::max_speed>(key<"maximum_speed">),
|
||||
@@ -106,6 +116,13 @@ struct structive::Type_Descriptor<Read_Only_Device> {
|
||||
);
|
||||
}
|
||||
};
|
||||
struct Empty_Device : Property_Object<Empty_Device> {};
|
||||
template <>
|
||||
struct structive::Type_Descriptor<Empty_Device> {
|
||||
static auto get() {
|
||||
return object<Empty_Device>();
|
||||
}
|
||||
};
|
||||
struct Pure_Read_Only_Device : Property_Object<Pure_Read_Only_Device> {
|
||||
int id{21};
|
||||
int version{4};
|
||||
@@ -120,6 +137,10 @@ struct structive::Type_Descriptor<Pure_Read_Only_Device> {
|
||||
);
|
||||
}
|
||||
};
|
||||
template <class Property>
|
||||
concept Can_Read_Multi_Attribute_As_Single = requires(const Property& property_value) {
|
||||
property_value.template attribute<Test_Multi_Category>();
|
||||
};
|
||||
template <class Object>
|
||||
concept Can_Write_Immutable = requires(Object& object) {
|
||||
object.template write<&Device::immutable_id>(1);
|
||||
@@ -180,7 +201,24 @@ int main() {
|
||||
REQUIRE(schema.template property<&Device::max_speed>().key() == "maximum_speed");
|
||||
using Temperature_Property = std::remove_cvref_t<decltype(schema.template property<&Device::temperature>())>;
|
||||
static_assert(Temperature_Property::template has_attribute<Test_Tag_Category>);
|
||||
static_assert(Temperature_Property::template attribute_count<Test_Tag_Category> == 1);
|
||||
static_assert(Temperature_Property::template attribute_count<Test_Multi_Category> == 2);
|
||||
static_assert(!Can_Read_Multi_Attribute_As_Single<Temperature_Property>);
|
||||
REQUIRE(Temperature_Property::template attribute_type<Test_Tag_Category>::value == 7);
|
||||
int multi_sum = 0;
|
||||
schema.template property<&Device::temperature>().template for_each_attribute<Test_Multi_Category>([&](const auto& attribute) {
|
||||
multi_sum += std::remove_cvref_t<decltype(attribute)>::value;
|
||||
});
|
||||
REQUIRE(multi_sum == 8);
|
||||
const auto& empty_schema = type_descriptor<Empty_Device>();
|
||||
static_assert(type_descriptor_schema_t<Empty_Device>::property_count == 0);
|
||||
REQUIRE(empty_schema.synchronization_plan().property_rules().empty());
|
||||
Empty_Device empty_device;
|
||||
REQUIRE(empty_device.resolved_synchronization().lock_count == 0);
|
||||
Property_Object_Base& empty_erased = empty_device;
|
||||
REQUIRE(empty_erased.runtime_property_count() == 0);
|
||||
int empty_value = 0;
|
||||
REQUIRE(empty_erased.runtime_read("missing", &empty_value, &runtime_read_int) == Runtime_Access_Result::unknown_property);
|
||||
Device device;
|
||||
REQUIRE(device.resolved_synchronization().lock_count == 3);
|
||||
REQUIRE(device.lock_slot<&Device::immutable_id>() == Resolved_Synchronization_View::unsynchronized_slot);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <semaphore>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <typeinfo>
|
||||
@@ -24,6 +25,15 @@ struct structive::Type_Descriptor<Runtime_Device> {
|
||||
);
|
||||
}
|
||||
};
|
||||
struct Move_Only_Runtime_Device : Property_Object<Move_Only_Runtime_Device> {
|
||||
std::unique_ptr<int> value{std::make_unique<int>(1)};
|
||||
};
|
||||
template <>
|
||||
struct structive::Type_Descriptor<Move_Only_Runtime_Device> {
|
||||
static auto get() {
|
||||
return object<Move_Only_Runtime_Device>(field<&Move_Only_Runtime_Device::value>(key<"value">));
|
||||
}
|
||||
};
|
||||
struct Runtime_Read_Capture {
|
||||
std::size_t calls{};
|
||||
std::size_t index{};
|
||||
@@ -82,6 +92,20 @@ static void test_runtime_metadata_and_results() {
|
||||
REQUIRE(erased.runtime_write("value", typeid(double), &wrong_type) == Runtime_Access_Result::type_mismatch);
|
||||
REQUIRE(erased.runtime_write("missing", typeid(int), &value) == Runtime_Access_Result::unknown_property);
|
||||
}
|
||||
static void test_runtime_copy_write_boundary() {
|
||||
using Schema = type_descriptor_schema_t<Move_Only_Runtime_Device>;
|
||||
using Property = typename Schema::template property_type<0>;
|
||||
static_assert(Property::writable);
|
||||
static_assert(!Property::runtime_copy_writable);
|
||||
Move_Only_Runtime_Device device;
|
||||
device.write<&Move_Only_Runtime_Device::value>(std::make_unique<int>(9));
|
||||
REQUIRE(*device.value == 9);
|
||||
Property_Object_Base& erased = device;
|
||||
std::unique_ptr<int> replacement = std::make_unique<int>(11);
|
||||
REQUIRE(erased.runtime_write("value", typeid(std::unique_ptr<int>), &replacement) == Runtime_Access_Result::unsupported_runtime_write);
|
||||
REQUIRE(*device.value == 9);
|
||||
REQUIRE(*replacement == 11);
|
||||
}
|
||||
static void test_runtime_access_uses_managed_synchronization() {
|
||||
Runtime_Device device;
|
||||
Property_Object_Base& erased = device;
|
||||
@@ -134,6 +158,7 @@ static void test_runtime_read_only_fast_path() {
|
||||
}
|
||||
int main() {
|
||||
test_runtime_metadata_and_results();
|
||||
test_runtime_copy_write_boundary();
|
||||
test_runtime_access_uses_managed_synchronization();
|
||||
test_runtime_read_only_fast_path();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user