首页 > 解决方案 > Is there a way to pass different structs to a single class constructor

问题描述

I have my own FIFO class that works OK, but I'd like to extend its flexibility.

Right now, the data struct that goes in the FIFO is defined in the FIFO class, so every FIFO object has the same data struct.

It would be nice if every object could define its own FIFO struct and pass it to the FIFO class. The FIFO class shouldn't care what the structure looks like, it just queues and enqueues whatever struct got passed to the FIFO constructor. This is actually well beyond my current skill set, but I thought with a little help, maybe I could pull it off.

Here's a simple example of what I'm trying to do that I haven't been able to compile:

class FIFO
{
public:
    FIFO(struct myStruct&, uint32_t depth)
    {
        std::array<myStruct, depth>;
    }
};

struct struct1
{
    double s1Var1;
    uint32_t s1Var2;
};

struct struct2
{
    bool s2Var1;
};

FIFO fifo1 = new FIFO(struct1, 16);

FIFO fifo2 = new FIFO(struc2, 8);

I get this error at the std::array<myStruct, depth> line:

Error: non-type template argument is not a constant expression

And this error at FIFO fifo1 = new FIFO(struct1, 16):

Error: 'struct1' does not refer to a value

and the same error for struct2 at FIFO fifo2 = new FIFO(struct2, 8).

If the solution is straight forward, I'd appreciate any help. If there's some topic I need to read up on before I try this, I'd be happy if someone would point me at it.

Looking at the comments, maybe I should have been more complete. This is for an embedded systems with lots of external devices of dubious reliability (mostly RS232 and some I2C). The actual IO to the devices is non-blocking DMA or interrupts. So, if I have a GPS device that talks over a UART, the GPS driver knows what its FIFO structure should look like. The GPS driver instantiates a UART object and passes it the GPS struct. The UART object instantiates a FIFO object with (in this case) the GPS struct. The FIFO class has the usual FIFO methods: enqueue, dequeue, isFull, isEmpty, etc.

When the over-arching state machine (SM) needs something from the GPS like a position fix, it calls something like GPS1.getPostionFix() method. The GPS driver does something like uart.writeCommand(getFix) and eventually the return message winds up in the UART's FIFO. The next cycle through the state machine, the SM asks the GPS driver if there's a fix available. The GPS calls something like uart.readFifo() which returns the latest message in the FIFO or -1 if the FIFO is empty. The GPS driver defined the GPS struct in the first place so it can parse, process and provide the position fix to the SM. The UART driver doesn't know anything about the struct it's enqueueing or dequeuing which seem like decent encapsulation to me. If anyone is still reading, comments on this approach would also be greatly appreciated.

标签: c++structconstructor

解决方案


Is there a way to pass different structs to a single class constructor

No, it isn't possible to pass a type as a function argument (and constructors are (special member-) functions).

However, it is possible to pass types as template arguments, and a constructor can be an instance of a function template... Or the class itself can be instance of a class template. For example:

template<class T, std::size_t depth>
struct Fifo
{
    Fifo()
    {
        std::array<T, depth> local_variable;
    }
};


Fifo<struct1, 16> fifo1;
Fifo<struct2, 8 > fifo2;

std::array itself is such a class template.


P.S. Avoid using all uppercase names for types (excluding single upper case charcter names which are conventional for template variables). Those names are conventionally reserved for macros.

P.P.S Avoid owning bare pointers. Avoid unnecessary dynamic allocation altogether.


推荐阅读