Using templates instead of bridge template in C ++

I have three types of data transfer: RS485, I2C and Bluetooth. Each data line has functions such as connecting, reading and writing data. On PC software, I have to implement application / protocol layers for working with devices. In my previous question about OOP, I received answers for using the Bridge template or factory method, but I think it can be done better. I would ask if templates are better for this task. Here is my simple example of how I want to use it:

// Low level datalink class
class RS485
{
public:
    void send(const char *data) {
        // datalink function to send data using RS485
        printf("RS485: %s \n", data);
    }
};

class I2C
{
public:
    void send(const char *data) {
        // datalink function to send data using I2C
        printf("I2C: %s \n", data);
    }
};

class BT
{
public:
    void send(const char *data) {
        // datalink function to send data using Bluetooth
        printf("BT %s \n", data);
    }
};

// Protocol class
template<typename Comm>
class MODBUS
{
public:
    MODBUS(Comm *c) { _c = c; }

    void send(const char *data) {
        printf("MODBUS\n");
        _c->send(data);
    }
private:
    Comm *_c;
};

// Protocol class
template<typename Comm>
class TCP
{
public:
    TCP(Comm *c) { _c = c; }

    void send(const char *data) {
        printf("TCP\n");
        _c->send(data);
    }
private:
    Comm *_c;
};

int main() {
    // Modbus over I2C
    I2C *i2c = new I2C();
    MODBUS<I2C> *mb_i2c = new MODBUS<I2C>(i2c);
    mb_i2c->send("Data ...");

    // Modbus over RS485
    RS485 *rs = new RS485();
    MODBUS<RS485> *mb_rs = new MODBUS<RS485>(rs);
    mb_rs->send("Data ...");

    // Tcp over Modbus over RS485
    TCP< MODBUS<RS485> > *tcp_modbus_rs = new TCP< MODBUS<RS485> >(mb_rs);
    tcp_modbus_rs->send("Data ...");

    return 0;
}
+4
source share
5 answers

, (). send , ?

- - , .

: , :

struct TCP
{
    void onsend(const char* data) {}
};

struct MODBUS
{
    void onsend(const char* data) {}
};

struct RS485
{
    void onsend(const char* data) {}
};

template<typename F, typename Prot, typename... TProtocols>
auto channel(F&& f, Prot&& prot, TProtocols&&... protocols)
{
    return [&](const char* data)
    {
        f(prot, data);
        channel(f, protocols...)(data);
    };
}

template<typename F, typename Prot>
auto channel(F&& f, Prot&& prot)
{
    return [&](const char* data)
    {
        f(prot, data);
    };
}

int main()
{
    TCP tcp;
    MODBUS modbus;
    RS485 rs;

    auto chan = channel([](auto&& protocol, const char* data)
    {
        protocol.onsend(data);
    }, 
    tcp, modbus, rs);

    const char msg[] = "asdfasdf";
    chan(msg);
}

, , , , ?

+1

mixins-from-below, . , . () .
, :

#include<cstdio>

// Low level datalink class
struct RS485 {
    void send(const char *data) {
        // datalink function to send data using RS485
        printf("RS485: %s \n", data);
    }
};

struct I2C {
    void send(const char *data) {
        // datalink function to send data using I2C
        printf("I2C: %s \n", data);
    }
};

struct BT {
    void send(const char *data) {
        // datalink function to send data using Bluetooth
        printf("BT %s \n", data);
    }
};

// Protocol class
template<typename Comm>
struct MODBUS: private Comm {
    void send(const char *data) {
        printf("MODBUS\n");
        Comm::send(data);
    }
};

// Protocol class
template<typename Comm>
struct TCP: private Comm {
    void send(const char *data) {
        printf("TCP\n");
        Comm::send(data);
    }
};

int main() {
    // Modbus over I2C
    MODBUS<I2C> mb_i2c{};
    mb_i2c.send("Data ...");

    // Modbus over RS485
    MODBUS<RS485> mb_rs{};
    mb_rs.send("Data ...");

    // Tcp over Modbus over RS485
    TCP< MODBUS<RS485> > tcp_modbus_rs{};
    tcp_modbus_rs.send("Data ...");
}

, , .
:

// Protocol class
template<typename Comm>
struct MODBUS: private Comm {
    template<typename... T>
    MODBUS(T&&... t): Comm{std::forward<T>(t)...} {}

    void send(const char *data) {
        printf("MODBUS\n");
        Comm::send(data);
    }
};

, :

#include<cstdio>
#include<utility>

// Low level datalink class
struct RS485 {
    RS485(int) {}

    void send(const char *data) {
        // datalink function to send data using RS485
        printf("RS485: %s \n", data);
    }
};

struct I2C {
    I2C(char, double) {}

    void send(const char *data) {
        // datalink function to send data using I2C
        printf("I2C: %s \n", data);
    }
};

struct BT {
    void send(const char *data) {
        // datalink function to send data using Bluetooth
        printf("BT %s \n", data);
    }
};

// Protocol class
template<typename Comm>
struct MODBUS: private Comm {
    template<typename... T>
    MODBUS(T&&... t): Comm{std::forward<T>(t)...} {}

    void send(const char *data) {
        printf("MODBUS\n");
        Comm::send(data);
    }
};

// Protocol class
template<typename Comm>
struct TCP: private Comm {
    template<typename... T>
    TCP(T&&... t): Comm{std::forward<T>(t)...} {}

    void send(const char *data) {
        printf("TCP\n");
        Comm::send(data);
    }
};

int main() {
    // Modbus over I2C
    MODBUS<I2C> mb_i2c{'c', .3};
    mb_i2c.send("Data ...");

    // Modbus over RS485
    MODBUS<RS485> mb_rs{42};
    mb_rs.send("Data ...");

    // Tcp over Modbus over RS485
    TCP< MODBUS<RS485> > tcp_modbus_rs{23};
    tcp_modbus_rs.send("Data ...");
}
+1

.

, , ""?

( ).

, .

#include <stdio.h>
#include <memory>

struct DataLink {
    virtual void send(const char *data) = 0;
    virtual ~DataLink(){}
};

typedef std::shared_ptr<DataLink> DLPtr;

struct RS485 : DataLink {
    void send(const char *data) { printf("RS485: %s \n", data);}
};

struct I2C : DataLink {
    void send(const char *data) { printf("I2C: %s \n", data); }
};

struct BT : DataLink {
    void send(const char *data) { printf("BT %s \n", data); }
};

struct MODBUS : DataLink {
    DLPtr channel;
    MODBUS(const DLPtr& channel) : channel(channel) {}
    void send(const char *data) {
        printf("MODBUS\n");
        channel->send(data);
    }
};

struct TCP : DataLink {
    DLPtr channel;
    TCP(const DLPtr& channel) : channel(channel) {}
    void send(const char *data) {
        printf("TCP\n");
        channel->send(data);
    }
};

int main() {
    DLPtr dl1(new MODBUS(DLPtr(new I2C)));
    dl1->send("data ...");
    DLPtr dl2(new MODBUS(DLPtr(new RS485)));
    dl2->send("data ...");
    DLPtr dl3(new TCP(DLPtr(new MODBUS(DLPtr(new RS485)))));
    dl3->send("data ...");
    return 0;
}
+1

, :

class Sender
{
public:
    virtual ~Sender() = default;
    virtual void send(const char *data) = 0;
};

// Low level datalink class
class RS485 : public Sender
{
public:
    void send(const char *data) override {
        // datalink function to send data using RS485
        printf("RS485: %s \n", data);
    }
};

class I2C: public Sender
{
public:
    void send(const char *data) override {
        // datalink function to send data using I2C
        printf("I2C: %s \n", data);
    }
};

class BT : public Sender
{
public:
    void send(const char *data) override {
        // datalink function to send data using Bluetooth
        printf("BT %s \n", data);
    }
};

// Protocol class
class MODBUS : public Sender
{
public:
    explicit MODBUS(Sender* sender) : sender(sender) {}

    void send(const char *data) override {
        printf("MODBUS\n");
        sender->send(data);
    }
private:
    Sender *sender;
};

// Protocol class
class TCPS : public Sender
{
public:
    expolicit TCP(Sender* sender) : sender(sender) {}

    void send(const char *data) override {
        printf("TCP\n");
        sender->send(data);
    }
private:
    Sender* sender;
};

int main() {
    // Modbus over I2C
    I2C i2c;
    MODBUS mb_i2c(&i2c);
    mb_i2c.send("Data ...");

    // Modbus over RS485
    RS485 rs;
    MODBUS mb_rs(&rs);
    mb_rs.send("Data ...");

    // Tcp over Modbus over RS485
    TCP tcp_modbus_rs(mb_rs);
    tcp_modbus_rs.send("Data ...");
}
0
// strong typedef:
struct sink:std::function<void(char const*)>{
  using std::function<void(char const*)>::function; // inherit ctors
};
using step=std::function<void(char const*, sink)>;

inlne sink operator|( step s, sink e ){
  return [=](char const* data){
    s( data, e );
  };
}
inlne step operator|( step one, step two ){
  return [=](char const* data, sink end){
    two( data, one|end );
  };
}

.

step fake_step(sts::string name){
  return [name](char const* data, sink s){
    std::cout<<name<<": \n";
    s(data);
  };
}
auto tcp=fake_step("tcp");
auto modbus=fake_step("modbus");

sink fake_sink(std::string name){
  return [name](char const* data){
    std::cout << name << ": " << data << "\n";
  };
}
auto ABC=fake_sink("ABC");
auto XYZ=fake_sink("XYZ");


auto tcp_over_xyz = tcp|XYZ;

; crtp koenig . , , .

std:: function; .

0

Source: https://habr.com/ru/post/1684154/


All Articles