-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
158 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#ifndef ALIA_SIGNAL_FIELD_MACROS_HPP | ||
#define ALIA_SIGNAL_FIELD_MACROS_HPP | ||
|
||
#include <alia/signals/operators.hpp> | ||
|
||
// __declspec(property(...)) is non-standard. | ||
#if defined(__clang__) || defined(_MSC_VER) | ||
|
||
#define ALIA_PP_CONCAT(a, b) ALIA_PP_CONCAT1(a, b) | ||
#define ALIA_PP_CONCAT1(a, b) ALIA_PP_CONCAT2(a, b) | ||
#define ALIA_PP_CONCAT2(a, b) a##b | ||
|
||
#define ALIA_PP_FE_2_0(F, a, b) | ||
#define ALIA_PP_FE_2_1(F, a, b, x) F(a, b, x) | ||
#define ALIA_PP_FE_2_2(F, a, b, x, ...) \ | ||
F(a, b, x) ALIA_PP_FE_2_1(F, a, b, __VA_ARGS__) | ||
#define ALIA_PP_FE_2_3(F, a, b, x, ...) \ | ||
F(a, b, x) ALIA_PP_FE_2_2(F, a, b, __VA_ARGS__) | ||
#define ALIA_PP_FE_2_4(F, a, b, x, ...) \ | ||
F(a, b, x) ALIA_PP_FE_2_3(F, a, b, __VA_ARGS__) | ||
#define ALIA_PP_FE_2_5(F, a, b, x, ...) \ | ||
F(a, b, x) ALIA_PP_FE_2_4(F, a, b, __VA_ARGS__) | ||
|
||
#define ALIA_PP_GET_MACRO(_0, _1, _2, _3, _4, _5, NAME, ...) NAME | ||
#define ALIA_PP_FOR_EACH_2(F, a, b, ...) \ | ||
ALIA_PP_GET_MACRO( \ | ||
_0, \ | ||
__VA_ARGS__, \ | ||
ALIA_PP_FE_2_5, \ | ||
ALIA_PP_FE_2_4, \ | ||
ALIA_PP_FE_2_3, \ | ||
ALIA_PP_FE_2_2, \ | ||
ALIA_PP_FE_2_1, \ | ||
ALIA_PP_FE_2_0) \ | ||
(F, a, b, __VA_ARGS__) | ||
|
||
#define ALIA_DEFINE_STRUCT_SIGNAL_FIELD(signal_type, struct_name, field_name) \ | ||
auto ALIA_PP_CONCAT(ALIA_PP_CONCAT(_get_, field_name), _signal)() \ | ||
{ \ | ||
return (*this)->*&struct_name::field_name; \ | ||
} \ | ||
__declspec(property( \ | ||
get = ALIA_PP_CONCAT(ALIA_PP_CONCAT(_get_, field_name), _signal))) \ | ||
alia::field_signal< \ | ||
ALIA_PP_CONCAT(ALIA_PP_CONCAT(signal_type, _), struct_name), \ | ||
decltype(struct_name::field_name)> \ | ||
field_name; | ||
|
||
#define ALIA_DEFINE_STRUCT_SIGNAL_FIELDS(signal_type, struct_name, ...) \ | ||
ALIA_PP_FOR_EACH_2( \ | ||
ALIA_DEFINE_STRUCT_SIGNAL_FIELD, \ | ||
signal_type, \ | ||
struct_name, \ | ||
__VA_ARGS__) | ||
|
||
#define ALIA_DEFINE_CUSTOM_STRUCT_SIGNAL( \ | ||
signal_name, signal_type, struct_name, ...) \ | ||
struct signal_name : alia::signal_type<struct_name> \ | ||
{ \ | ||
using signal_ref::signal_ref; \ | ||
ALIA_DEFINE_STRUCT_SIGNAL_FIELDS( \ | ||
signal_type, struct_name, __VA_ARGS__) \ | ||
}; | ||
|
||
#define ALIA_DEFINE_STRUCT_SIGNAL(signal_type, struct_name, ...) \ | ||
ALIA_DEFINE_CUSTOM_STRUCT_SIGNAL( \ | ||
ALIA_PP_CONCAT(ALIA_PP_CONCAT(signal_type, _), struct_name), \ | ||
signal_type, \ | ||
struct_name, \ | ||
__VA_ARGS__) | ||
|
||
#define ALIA_DEFINE_STRUCT_SIGNALS(struct_name, ...) \ | ||
ALIA_DEFINE_STRUCT_SIGNAL(readable, struct_name, __VA_ARGS__) \ | ||
ALIA_DEFINE_STRUCT_SIGNAL(duplex, struct_name, __VA_ARGS__) | ||
|
||
#endif | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
#include <alia/signals/field_macros.hpp> | ||
|
||
#include <testing.hpp> | ||
|
||
#include <alia/signals/basic.hpp> | ||
#include <alia/signals/lambdas.hpp> | ||
|
||
// __declspec(property(...)) is non-standard. | ||
#if defined(__clang__) || defined(_MSC_VER) | ||
|
||
namespace { | ||
|
||
struct foo | ||
{ | ||
int x; | ||
std::string y; | ||
}; | ||
|
||
ALIA_DEFINE_STRUCT_SIGNALS(foo, x, y) | ||
|
||
} // namespace | ||
|
||
TEST_CASE("ALIA_DEFINE_STRUCT_SIGNALS", "[signals][field_macros]") | ||
{ | ||
using namespace alia; | ||
|
||
foo f = {2, "1.5"}; | ||
auto f_signal = lambda_duplex( | ||
always_has_value, | ||
[&]() { return f; }, | ||
always_ready, | ||
[&](foo const& v) { f = v; }, | ||
[&]() { return combine_ids(make_id(f.x), make_id(f.y)); }); | ||
|
||
REQUIRE((std::is_same<readable_foo::value_type, foo>::value)); | ||
REQUIRE(signal_is_readable<readable_foo>::value); | ||
REQUIRE(!signal_is_writable<readable_foo>::value); | ||
|
||
readable_foo rf = f_signal; | ||
|
||
REQUIRE(signal_has_value(rf.x)); | ||
REQUIRE(read_signal(rf.x) == 2); | ||
|
||
REQUIRE((std::is_same<duplex_foo::value_type, foo>::value)); | ||
REQUIRE(signal_is_readable<duplex_foo>::value); | ||
REQUIRE(signal_is_writable<duplex_foo>::value); | ||
|
||
duplex_foo df = f_signal; | ||
|
||
typedef decltype(df.x) x_signal_t; | ||
REQUIRE((std::is_same<x_signal_t::value_type, int>::value)); | ||
REQUIRE(signal_is_readable<x_signal_t>::value); | ||
REQUIRE(signal_is_writable<x_signal_t>::value); | ||
|
||
REQUIRE(signal_has_value(df.x)); | ||
REQUIRE(read_signal(df.x) == 2); | ||
REQUIRE(signal_ready_to_write(df.x)); | ||
write_signal(df.x, 1); | ||
REQUIRE(f.x == 1); | ||
|
||
auto x_signal = df.x; | ||
auto y_signal = df.y; | ||
|
||
typedef decltype(y_signal) y_signal_t; | ||
REQUIRE((std::is_same<y_signal_t::value_type, std::string>::value)); | ||
REQUIRE(signal_is_readable<y_signal_t>::value); | ||
REQUIRE(signal_is_writable<y_signal_t>::value); | ||
|
||
REQUIRE(y_signal.value_id() != x_signal.value_id()); | ||
REQUIRE(signal_has_value(y_signal)); | ||
REQUIRE(read_signal(y_signal) == "1.5"); | ||
REQUIRE(signal_ready_to_write(y_signal)); | ||
captured_id original_y_id = y_signal.value_id(); | ||
write_signal(y_signal, "0.5"); | ||
REQUIRE(y_signal.value_id() != original_y_id.get()); | ||
REQUIRE(f.y == "0.5"); | ||
} | ||
|
||
#endif |