c++templates

C++ template: access members from source template struct


I want to create following class template:

Example of user code. This is what I want to keep as simple as possible:

//list of sensors with a member for each sensor
typedef struct {
    cOneSensor_f A4_temp1 = cOneSensor_f ("A4t1", 0x1234 /*, x, y, ... and some more configuration data*/);
    cOneSensor_i B4_speed = cOneSensor_i ("B4s0", 0x2001 /*, x, y, ... and some more configuration data*/);
}Sensor_list_4_s;

//put the list inside a class template to be able to control all of them as a whole,
//but also access each sensor individually
cSensorsList<Sensor_list_4_s> Sensor_list_4( 4 );

//get sensor values
void do_sensors_stuff()
{
    //all sensors as a whole
    Sensor_list_4.update();

    //access each sensor individually
    float A4t1 = Sensor_list_4.A4_temp1();
    int   B4s0 = Sensor_list_4.B4_speed();
}

Behind the scene It can be as complicated as needed. It could be somehting like this:

class cOneSensor {}
class cOneSensor_f: class cOneSensor {}
class cOneSensor_i: class cOneSensor {}

template <typename T>
class cSensorsList: public T
{
private:
    int bus_code;
    cOneSensor *p_to_sensors_array;
    int nSensors;

public:
    cSensorsList(int bus_code):bus_code(bus_code)
    {
        //---  here is what I don't know how to do: get sensor list from typename T
        nSensors = 0; //getSensorListSize_from_T(/* T */);
        p_to_sensors_array= 0;//getSensorListPointer_from_T<T>(/* T */);
        // ---
    }
    void update(void) {
        for (int i=0; i<nSensors; i++)
            p_to_sensors_array[i].update();
    }
};

With this code I get:

But I don't know how to:


Solution

  • Since base class is an struct, not a class, the this pointer points to first inherited member from template. There is not vtable.

    Also, given all derived cOneSensor_X classes are the same size, we can calculate the number of members on base template struct T.

    template <typename T>
    class cSensorsList: public T
    {
    //...
    public:
        cSensorsList(int bus_code):bus_code(bus_code)
        {
            nSensors = sizeof(T)/sizeof(cOneSensor);
            p_sensors_array = (cOneSensor*)this; // <<--- pointer to first inherited member
        }
        void update(void) {/*...*/}
    };
    

    Note: If derived cOneSensor_X classes are not the same size, you can try a more sophisticated algoritm and sequencially capturing initial position of each member.

    But I'm pretty sure (or I wish) there should be a more elegant solution.