Skip to main content
added 104 characters in body
Source Link

Allows to deduce the type automagically. This function iterates over "something" passed the second parameter. It compiles, if the passed type provides the operations/attributes used in the function. And yes, this works only since c++17

Allows to deduce the type automagically. This function iterates over "something" passed the second parameter. It compiles, if the passed type provides the operations/attributes used in the function.

Allows to deduce the type automagically. This function iterates over "something" passed the second parameter. It compiles, if the passed type provides the operations/attributes used in the function. And yes, this works only since c++17

add why to use a new compiler
Source Link

If you want to use a recent compiler (The Arduino IDE uses gcc4.9) you can build your own gcc avr toolchain rather easily. Then you have gcc 7.2 with c++17 support ! An other very good reason to use gcc 7.2 is, that they have improved the error messages by a great deal.

My conclusion is, there is no excuse using c, except you havn't yet learned c++. And use a new compiler !

If you want to use a recent compiler (The Arduino IDE uses gcc4.9) you can build your own gcc avr toolchain rather easily. Then you have gcc 7.2 with c++17 support !

My conclusion is, there is no excuse using c, except you havn't yet learned c++.

If you want to use a recent compiler (The Arduino IDE uses gcc4.9) you can build your own gcc avr toolchain rather easily. Then you have gcc 7.2 with c++17 support ! An other very good reason to use gcc 7.2 is, that they have improved the error messages by a great deal.

My conclusion is, there is no excuse using c, except you havn't yet learned c++. And use a new compiler !

add an elaborated example for crtp
Source Link

The avr runtime does not support exceptions nor dynamic memory allocation (you can provide an implementation, thoughas has been stated. you can provide an implementation though.

more on templates

The following code uses the "curiously recurring template pattern" CRTP. It is used to create a job class, which i use for a primitive scheduling

This template builds a chain of registrable items.

template<class registered>
struct Registered {
    static registered *registry;
    registered *chain;
    Registered() : chain(registry) {registry=static_cast<registered*>(this);}
};

The job class applies the CRTP pattern. The constructor takes the actual callback where the work is done, and how often the job is done.

class Job : public Registered<Job>
{
    voidFuncPtr m_p;
    uint16_t m_periodic;
    uint32_t m_lastrun;
    uint16_t m_initialdelay;
    public:
    Job(voidFuncPtr p,uint16_t periode=0,uint16_t initialdelay=0):m_p(p),m_periodic(periode),m_lastrun(0),m_initialdelay(initialdelay)
    {
        
    }
    void run(uint32_t t_ms)
    {
        // tbd handle wraparound !!
        if(t_ms >= m_lastrun + m_periodic + m_initialdelay)
        {
            m_p();
            m_lastrun=t_ms;
            m_initialdelay=0;
        }
    }
};

to use the job class i just create the instances for the jobs and pass lambdas or regular function pointers

Job jserial([](){mqttrouteradapter.handleSerialMQTT();},10);
Job jupdate(updatemc,1);
Job jprint(printstate,500);

initialize the beginning of the chain of jobs

template<> Job *Registered< Job >::registry = 0;

and inside main, run an infinite loop which calls the jobs.

while (1)
    {
        for ( auto p = Job::registry; p; p=p->chain )
        p->run(millis());
    }

Lambdas

allowsAllows to deduce the type automagically. This function iterates over "something" passed the second parameter. It compiles, if the passed type provides the operations/attributes used in the function.

whilevoid runRx(1const char* data, auto msg_registry)
  {
    for ( auto p = Job::registry;msg_registry; p; p=pp = p->chain ) {
        p->run(millis>rx()data);
    }
}

using a recent compiler

If you want to use a recent compiler (The Arduino IDE uses gcc4.9) you can build your own gcc avr toolchain rather easily. Then you have gcc 7.2 with c++17 support !

My conclusion is, there is no excuse using c, except you havn't yet learned c++.

The avr runtime does not support exceptions nor dynamic memory allocation (you can provide an implementation, though.

Lambdas

allows to deduce the type automagically

while (1)
 {
    for ( auto p = Job::registry; p; p=p->chain )
    p->run(millis());

}

The avr runtime does not support exceptions nor dynamic memory allocation, as has been stated. you can provide an implementation though.

more on templates

The following code uses the "curiously recurring template pattern" CRTP. It is used to create a job class, which i use for a primitive scheduling

This template builds a chain of registrable items.

template<class registered>
struct Registered {
    static registered *registry;
    registered *chain;
    Registered() : chain(registry) {registry=static_cast<registered*>(this);}
};

The job class applies the CRTP pattern. The constructor takes the actual callback where the work is done, and how often the job is done.

class Job : public Registered<Job>
{
    voidFuncPtr m_p;
    uint16_t m_periodic;
    uint32_t m_lastrun;
    uint16_t m_initialdelay;
    public:
    Job(voidFuncPtr p,uint16_t periode=0,uint16_t initialdelay=0):m_p(p),m_periodic(periode),m_lastrun(0),m_initialdelay(initialdelay)
    {
        
    }
    void run(uint32_t t_ms)
    {
        // tbd handle wraparound !!
        if(t_ms >= m_lastrun + m_periodic + m_initialdelay)
        {
            m_p();
            m_lastrun=t_ms;
            m_initialdelay=0;
        }
    }
};

to use the job class i just create the instances for the jobs and pass lambdas or regular function pointers

Job jserial([](){mqttrouteradapter.handleSerialMQTT();},10);
Job jupdate(updatemc,1);
Job jprint(printstate,500);

initialize the beginning of the chain of jobs

template<> Job *Registered< Job >::registry = 0;

and inside main, run an infinite loop which calls the jobs.

while (1)
    {
        for ( auto p = Job::registry; p; p=p->chain )
        p->run(millis());
    }

Lambdas

Allows to deduce the type automagically. This function iterates over "something" passed the second parameter. It compiles, if the passed type provides the operations/attributes used in the function.

void runRx(const char* data, auto msg_registry) {
    for (auto p = msg_registry; p; p = p->chain) {
        p->rx(data);
    }
}

using a recent compiler

If you want to use a recent compiler (The Arduino IDE uses gcc4.9) you can build your own gcc avr toolchain rather easily. Then you have gcc 7.2 with c++17 support !

My conclusion is, there is no excuse using c, except you havn't yet learned c++.

Source Link
Loading