Skip to content

a simple signal system that's meant to be a type safe implementation of the observer pattern that does not require a specific observer class and is simple to use

License

Notifications You must be signed in to change notification settings

zer0problem/Signal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 

Repository files navigation

Signal

A simple signal system that's meant to be a type safe implementation of the observer pattern that does not require a specific observer class and is simple to use, this requires C++17

A simple example in with a Main function

// SignalTests.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include <iostream>
#include "Signal.h"

void BasicFunction()
{
    std::cout << "a function taking no arguments" << std::endl;
}
void AddNumbers(int a, int b)
{
    std::cout << (a + b) << std::endl;
}

class Foo
{
public:
    void Print()
    {
        std::cout << "Foo print from " << this << std::endl;
    }
};

void Fighter(Foo *aFoo)
{
    std::cout << aFoo << " is a real fighter" << std::endl;
}

void PrintSquared(float aNum)
{
    std::cout << (aNum * aNum) << std::endl;
}

int main()
{
    Signal basicSignal;

    // connecting a function without an object
    basicSignal.Connect<&BasicFunction>();
    // this does not work, it's type safe so it will not compile and complain about wrong argument types and counts
    //basicSignal.Connect<&AddNumbers>();

    // connect an object with a member function
    Foo foo;
    basicSignal.Connect<&Foo::Print>(&foo);

    // connect an object with a non-member function
    basicSignal.Connect<&Fighter>(&foo);

    // Emits the signal, calls all connected functions with the objects in the order they were connected
    basicSignal.Emit();

    // Disconnecting has the same syntax
    basicSignal.Disconnect<&BasicFunction>();
    basicSignal.Disconnect<&Foo::Print>(&foo);
    basicSignal.Disconnect<&Fighter>(&foo);

    // Signals can be made to take arguments as well
    Signal<float> advancedSignal;

    // the function still needs to take the proper arguments
    advancedSignal.Connect<&PrintSquared>();

    // Emitting needs the proper arguments for the signal
    advancedSignal.Emit(3.2);
}

// a function taking no arguments
// Foo print from 0000003D94B5F9A4
// 0000003D94B5F9A4 is a real fighter
// 10.24

Creating a signal

Signal mySignal; // this one takes no arguments
Signal<int, float> myOtherSignal; // this one takes an 'int' and a 'float'

Connecting to it

// with a global function
void SomeFunction();
mySignal.Connect<&SomeFunction>();

// with a member function
class SomeClass {
public:
  void SomeClassFunction();
};
SomeClass myObject;
mySignal.Connect<&SomeClass::SomeClassFunction>(&myObject);

// with an object pointer connected as first argument to a function
void SomeOtherFunction(SomeClass *aObject);
mySignal.Connect<&SomeOtherFunction>(&myObject);

Emitting

mySignal.Emit();
myOtherSignal.Emit(42, 3.22f);

Disconnecting, this has the same syntax as connecting

mySignal.Disconnect<&SomeFunction>();
mySignal.Disconnect<&SomeClass::SomeClassFunction>(&myObject);
mySignal.Disconnect<&SomeOtherFunction>(&myObject);

About

a simple signal system that's meant to be a type safe implementation of the observer pattern that does not require a specific observer class and is simple to use

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages