Skip to content

Commit

Permalink
v2.1 (#17)
Browse files Browse the repository at this point in the history
* v2.1

* add event reference

* update only on real changes
  • Loading branch information
TheLartians authored May 3, 2019
1 parent 527420d commit 7a625c6
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 28 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
# ---- Project ----

project(LarsEvent
VERSION 2.0.3
VERSION 2.1
LANGUAGES CXX
)

Expand Down
22 changes: 19 additions & 3 deletions include/lars/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ namespace lars{
data->observers.emplace_back(StoredHandler{data->IDCounter,std::make_shared<Handler>(h)});
return data->IDCounter++;
}


protected:
Event(const Event &) = default;
Event &operator=(const Event &) = default;

public:

struct Observer:public lars::Observer::Base{
Expand Down Expand Up @@ -100,9 +104,7 @@ namespace lars{
Event():data(std::make_shared<Data>()){
}

Event(const Event &) = delete;
Event(Event &&other):Event(){ *this = std::move(other); }
Event &operator=(const Event &) = delete;
Event &operator=(Event &&other){
std::swap(data, other.data);
return *this;
Expand Down Expand Up @@ -142,5 +144,19 @@ namespace lars{
}

};

template <typename ... Args> class EventReference: public Event<Args...> {
protected:
using Base = Event<Args...>;

public:
EventReference(const Base &other):Base(other){}

EventReference &operator=(const Base &other){
Base::operator=(other);
return *this;
}
};


}
23 changes: 20 additions & 3 deletions include/lars/observable_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@

namespace lars {

namespace observable_value_detail {
// source: https://stackoverflow.com/questions/6534041/how-to-check-whether-operator-exists
struct No {};
template<typename T, typename Arg> No operator== (const T&, const Arg&);
template<typename T, typename Arg = T> struct HasEqual {
enum { value = !std::is_same<decltype(*(T*)(0) == *(Arg*)(0)), No>::value };
};
}

template <class T> class ObservableValue {
protected:
T value;
Expand All @@ -21,9 +30,17 @@ namespace lars {
ObservableValue(ObservableValue &&) = delete;
ObservableValue &operator=(ObservableValue &&) = delete;

template <typename ... Args> void set(Args ... args){
value = T(std::forward<Args>(args)...);
onChange.emit(value);
template <typename ... Args> void set(Args && ... args){
if constexpr (observable_value_detail::HasEqual<T>::value) {
T newValue(std::forward<Args>(args)...);
if (value != newValue) {
value = std::move(newValue);
onChange.emit(value);
}
} else {
value = T(std::forward<Args>(args)...);
onChange.emit(value);
}
}

template <typename ... Args> void setSilently(Args ... args){
Expand Down
12 changes: 6 additions & 6 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ FetchContent_MakeAvailable(Catch2)
# ---- Create binary ----

file(GLOB tests_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
add_executable(lars-event-tests ${tests_sources})
target_link_libraries(lars-event-tests PUBLIC Catch2 LarsEvent)
set_target_properties(lars-event-tests PROPERTIES CXX_STANDARD 17 COMPILE_FLAGS "-Wall -pedantic -Wextra -Werror")
add_executable(LarsEventTests ${tests_sources})
target_link_libraries(LarsEventTests PUBLIC Catch2 LarsEvent)
set_target_properties(LarsEventTests PROPERTIES CXX_STANDARD 17 COMPILE_FLAGS "-Wall -pedantic -Wextra -Werror")

# ---- Add tests ----

ENABLE_TESTING()
ADD_TEST(lars-event-tests lars-event-tests)
ADD_TEST(LarsEventTests LarsEventTests)

# ---- code coverage ----

if (${ENABLE_TEST_COVERAGE})
set_target_properties(lars-event-tests PROPERTIES CXX_STANDARD 17 COMPILE_FLAGS "-O0 -g -fprofile-arcs -ftest-coverage --coverage")
target_link_options(lars-event-tests PUBLIC "--coverage")
set_target_properties(LarsEventTests PROPERTIES CXX_STANDARD 17 COMPILE_FLAGS "-O0 -g -fprofile-arcs -ftest-coverage --coverage")
target_link_options(LarsEventTests PUBLIC "--coverage")
endif()
14 changes: 13 additions & 1 deletion tests/event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ using namespace lars;
// instantiate template for coverage
template class lars::Event<>;

TEST_CASE("Event"){
TEST_CASE("Event", "[event]"){

SECTION("connect and observe"){
lars::Event<> event;
Expand Down Expand Up @@ -117,3 +117,15 @@ TEST_CASE("Event"){

}

TEST_CASE("EventReference", "[event]"){
lars::Event<> onA, onB;
lars::EventReference<> onR(onA);
unsigned aCount = 0, bCount = 0;
onR.connect([&](){ aCount++; });
onA.emit();
onR = onB;
onR.connect([&](){ bCount++; });
onB.emit();
REQUIRE(aCount == 1);
REQUIRE(bCount == 1);
}
44 changes: 30 additions & 14 deletions tests/observable_value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,44 @@

#include <lars/observable_value.h>

using namespace lars;

// instantiate templates for coverage
template class lars::ObservableValue<int>;
template class lars::DependentObservableValue<int,int,int>;

TEST_CASE("Observable Value") {
using namespace lars;

ObservableValue value(0);

unsigned total = 0;
value.onChange.connect([&](auto &v){ total+=v; });
TEST_CASE("ObservableValue", "[observable_value]") {
int current = 0;
ObservableValue value(current);
unsigned changes = 0;
value.onChange.connect([&](auto &v){
REQUIRE(current == v);
changes++;
});
REQUIRE(*value == 0);
value.set(1);
value.set(2);
REQUIRE(total == 3);
current++;
value.set(current);
value.set(current);
value.set(current);
current++;
value.set(current);
value.set(current);
REQUIRE(changes == 2);
REQUIRE(*value == 2);
}

TEST_CASE("Dependent Observable Value") {
using namespace lars;
TEST_CASE("ObservableValue without comparison operator", "[observable_value]") {
struct A{ };
ObservableValue<A> value;
unsigned changes = 0;
value.onChange.connect([&](auto &){ changes++; });
value.set();
value.set();
value.set();
REQUIRE(changes == 3);
}

TEST_CASE("Dependent Observable Value", "[observable_value]") {
ObservableValue a(1);
ObservableValue b(1);
DependentObservableValue sum([](auto a, auto b){ return a+b; },a,b);
Expand All @@ -48,9 +65,8 @@ TEST_CASE("Dependent Observable Value") {
REQUIRE(*prod == 10);
}

TEST_CASE("Operators") {
TEST_CASE("Operators", "[observable_value]") {
using namespace lars;

struct A { int a = 0; };
ObservableValue<A> value;
REQUIRE(value->a == 0);
Expand Down

0 comments on commit 7a625c6

Please sign in to comment.