第九章:触发模式的实现
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109TEST(ReactionTest, TestChangeTrig) { auto a = reaction::var(1); auto b = reaction::var(2); auto c = reaction::var(3); int triggerCountA = 0; int triggerCountB = 0; auto ds = reaction::calc<reaction::AlwaysTrig>([&triggerCountA](int aa, double bb...
第八章:节点关系图的实现
第八章:节点关系图的实现1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677TEST(ReactionTest, TestSelfDependency) { auto a = reaction::var(1); auto dsA = reaction::calc([](int aa) { return aa; }, a); EXPECT_THROW(dsA.reset([&]() { return a() + dsA(); }), std::runtime_error);}TEST(ReactionTest, TestCycleDependency) { auto a = reaction::var(1); auto b = reactio...
第七章:表达式模板的使用
第七章:表达式模板的使用在实现表达式模板之前,我们先做一些准备工作。 首先实现action之间的依赖,一个action可以触发其他的action: 123456789101112131415161718TEST(ReactionTest, TestAction){ auto a = reaction::var(1); auto b = reaction::var(3.14); auto at = reaction::action([](int aa, double bb) { std::cout << "a = " << aa << '\t' << "b = " << bb << '\t'; }, a, b); bool trigger = false; auto att = reaction::action([...
第六章:编译期反射 private 成员
第六章:编译期反射 private 成员 上一章我们已经介绍了对于聚合类型的编译期反射,本章我们介绍对于非聚合类型如何反射。 首先看一下知乎的 YKIKO 在有状态黑魔法中提到的例子:👉 https://zhuanlan.zhihu.com/p/646752343 1234567891011121314#include <iostream>class Bank { double money = 999'999'999'999;public: void check() const { std::cout << money << std::endl; }};template <auto mp>struct Thief {};template struct Thief<&Bank::money>; 这里的 &Bank::money 是一个成员变量指针,不同于普通的指针,它并不依赖于某个对象,而表示该成员...
第五章:编译期反射初探!
第五章:编译期反射初探!在前面,我们提到了除了标签分发,还可以通过编译期反射来判断类的成员有没有某个类型。 反射是程序在运行时或编译期能够**“自我检查、自我操作”的能力**。 程序可以“知道自己有哪些类、成员变量、类型信息”,甚至动态地访问和修改它们。 编译期反射:在编译期间就可以分析、枚举、获取类型的成员信息。 C++26 正式加入反射: 123456789101112#include <meta>struct A { int x; double y; };consteval void analyze() { using namespace std::meta; auto info = reflexpr(A); // 反射出类型信息 auto members = members_of(info); // 获取所有成员 for (auto m : members) { std::println("Member: {}", name...
第三章:实现数据源的生命周期管理
第三章:实现数据源的生命周期管理设计目标回顾在前两章中,我们已经建立了Reaction框架的基础结构,本章将重点解决以下问题: 实现数据源的拷贝和移动语义 使用智能指针和引用计数管理内存 确保用户只持有弱引用,强引用由ObserverGraph统一管理 核心设计:桥接模式与智能指针管理1. 桥接模式的应用桥接模式(Bridge Pattern)是面向对象设计中的经典模式,其核心思想是将抽象(Abstraction)与实现(Implementation)分离,使二者可以独立变化。这种分离通过组合(Composition)而非继承(Inheritance)实现,是”组合优于继承”原则的典型体现。 在Reaction框架中,我们通过以下结构实现桥接模式: 123456template <typename ReactType>class React { /* 抽象接口层 */ };template <typename TriggerPolicy, typename InvalidStrategy, typename Type, typename....
第四章:让数据源作为成员变量
第四章:让数据源作为成员变量在本章中,我们将实现 constVar、action 和 field。 我们的目标是让如下代码成功编译并通过测试: 12345678910TEST(ReactionTest, TestConst) { auto a = reaction::var(1); auto b = reaction::constVar(3.14); auto ds = reaction::calc([](int aa, double bb) { return aa + bb; }, a, b); ASSERT_FLOAT_EQ(ds.get(), 4.14); a.value(2); ASSERT_FLOAT_EQ(ds.get(), 5.14); // b.value(4.14); // compile error;} 123456789TEST(ReactionTest, TestAction) { auto a = reaction::var(1); auto b ...
第二章:让数据流起来!依赖节点管理的实现
第二章:让数据流起来!依赖节点管理的实现在本章中,我们将实现 ObserverNode 和 ObserverGraph,从而能够正确传播数据源的调用链。 我们的目标是让如下代码成功编译并通过测试: 12345678910111213141516TEST(ReactionTest, TestCommonUse) { auto a = reaction::var(1); auto b = reaction::var(3.14); EXPECT_EQ(a.get(), 1); EXPECT_EQ(b.get(), 3.14); auto ds = reaction::calc([](int aa, double bb) { return aa + bb; }, a, b); auto dds = reaction::calc([](auto aa, auto dsds) { return std::to_string(aa) + std::to_string(dsds); }, a, ds); ...
第一章:让代码跑起来!构建响应式框架的起点
第一章:让代码跑起来!构建响应式框架的起点在本章中,我们将从零开始搭建 Reaction 响应式框架的基本工程结构,并实现几个关键的核心组件:DataSource、Expression 和 Resource。这些组件将构成我们响应式框架的计算骨架。 我们的目标是让如下代码成功编译并通过测试: 12345678910auto a = reaction::var(1);auto b = reaction::var(3.14);EXPECT_EQ(a.get(), 1);EXPECT_EQ(b.get(), 3.14);auto ds = reaction::calc([](int aa, double bb) { return aa + bb; }, a, b);auto dds = reaction::calc([](auto aa, auto dsds) { return std::to_string(aa) + std::to_string(dsds); }, a, ds);ASSERT_FLOAT_EQ(ds.get(), 4.14);...
从零实现响应式框架——基本概念和设计思路
走进响应式编程:从理念到 C++20 实现 —— Reaction 响应式框架介绍在现代软件开发中,响应式编程正逐步成为构建数据驱动应用的重要范式。本文将带你深入了解响应式编程的核心理念,比较当前主流响应式框架的优劣,并探讨为何在 C++20 环境下实现响应式框架尤为必要。随后,我们将介绍 Reaction 框架的整体设计思路与架构布局。 🎯 本教程面向谁?本教程适合以下人群阅读: 具备 C++ 基础的开发者:希望通过实战提升对语言本身的理解,掌握更现代的 C++20 编程范式。 对现代 C++ 感兴趣的学习者:希望学习 Concepts、constexpr、模板元编程等特性在工程中的实际用法。 正在求职或准备面试的 C++ 开发者:通过构建完整框架提升项目能力,积累可展示的实战经验。 希望了解响应式编程原理的人:尤其是在 Vue、React 等前端框架中有相关经验,想了解背后机制在 C++ 中的实现方式。 如果你希望从零构建一个现代化、类型安全、高性能的响应式框架,那么这份系列教程将为你提供系统的思路与代码支撑。 1. 什么是响应式编程?响应式编程是一种以“数据驱动视...